איך מקבלים הודעות באפליקציה ל-Android

אופן הפעולה של התראות ב-Firebase משתנה בהתאם לחזית או לרקע במצב של האפליקציה המקבלת. אם רוצים שאפליקציות שפועלות בחזית יקבלו התראות או הודעות נתונים, תצטרכו לכתוב קוד כדי הקריאה החוזרת (callback) של onMessageReceived. הסבר על ההבדל בין הודעות התראה להודעות נתונים מופיע בקטע סוגי הודעות.

טיפול בהודעות

כדי לקבל הודעות, צריך להשתמש בשירות שמרחיב את FirebaseMessagingService. השירות שלך צריך לבטל את onMessageReceived ואת onDeletedMessages קריאה חוזרת (callback).

חלון הזמן לטיפול בהודעה עשוי להיות קצר מ-20 שניות, בהתאם לעיכובים שהצטברו לפני הקריאה ל-onMessageReceived, כולל עיכובים במערכת ההפעלה, זמן ההפעלה של האפליקציה, ה-thread הראשי חסום על ידי פעולות אחרות או onMessageReceived הקודם השיחות נמשכות יותר מדי זמן. לאחר מכן, התנהגויות שונות של מערכות ההפעלה, כמו תהליך הרג או של Android O מגבלות הביצוע ברקע עלולות להפריע ליכולת שלכם להשלים את העבודה.

onMessageReceived זמין לרוב סוגי ההודעות, עם האפשרויות הבאות חריגים:

  • הודעות התראה שנשלחות כשהאפליקציה פועלת ברקע. כאן כיסוי, ההתראה מועברת למגש המערכת של המכשיר. כשמשתמש מקייש על התראה, מרכז האפליקציות נפתח כברירת מחדל.

  • הודעות עם מטען ייעודי (payload) גם של התראות וגם של מטען ייעודי (payload) של נתונים, כשמתקבלות ברקע. במקרה כזה, ההתראה מועברת למגש המערכת של המכשיר, ומטען הייעודי (payload) של הנתונים נמסר בתוספות לכוונת הרכישה של פעילות מרכז האפליקציות שלך.

בקצרה:

מצב האפליקציה התראה נתונים שניהם
חזית onMessageReceived onMessageReceived onMessageReceived
רקע מגש המערכת onMessageReceived התראה: מגש מערכת
נתונים: בתוספות של הכוונה.
למידע נוסף על סוגי ההודעות, ראו התראות והודעות נתונים.

עריכה של קובץ המניפסט של האפליקציה

כדי להשתמש ב-FirebaseMessagingService, עליך להוסיף את הפרטים הבאים ל מניפסט אפליקציה:

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

מומלץ גם להגדיר ערכי ברירת מחדל כדי להתאים אישית את מראה ההתראות. שלך אפשרות לציין סמל ברירת מחדל מותאם אישית וצבע ברירת מחדל מותאם אישית שיחולו בכל פעם ערכים מקבילים לא מוגדרים במטען הייעודי (payload) של ההתראות.

צריך להוסיף את השורות האלה בתוך תג application להגדרת סמל ברירת מחדל וצבע מותאם אישית:

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
     See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
     notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

ב-Android מוצג סמל ברירת המחדל המותאם אישית עבור

  • כל הודעות ההתראות שנשלחות מכלי היצירה של התראות.
  • כל הודעת התראה שלא מגדירה באופן מפורש את הסמל במטען הייעודי (payload) של ההתראות.

ב-Android נעשה שימוש בצבע ברירת המחדל בהתאמה אישית עבור

  • כל הודעות ההתראות שנשלחו מאת כתיבת התראות
  • כל הודעת התראה שלא מגדירה באופן מפורש את הצבע בהתראה מטען ייעודי (payload).

אם לא הוגדר סמל ברירת מחדל מותאם אישית ולא הוגדר סמל במטען הייעודי (payload) של ההתראות, ב-Android מוצג סמל האפליקציה שמעובד בלבן.

שינוי onMessageReceived

על ידי שינוי השיטה FirebaseMessagingService.onMessageReceived, אפשר לבצע פעולות על סמך RemoteMessage של האובייקט ולקבל את נתוני ההודעה:

Kotlin+KTX

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    Log.d(TAG, "From: ${remoteMessage.from}")

    // Check if message contains a data payload.
    if (remoteMessage.data.isNotEmpty()) {
        Log.d(TAG, "Message data payload: ${remoteMessage.data}")

        // Check if data needs to be processed by long running job
        if (needsToBeScheduled()) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob()
        } else {
            // Handle message within 10 seconds
            handleNow()
        }
    }

    // Check if message contains a notification payload.
    remoteMessage.notification?.let {
        Log.d(TAG, "Message Notification Body: ${it.body}")
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

Java

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());

        if (/* Check if data needs to be processed by long running job */ true) {
            // For long-running tasks (10 seconds or more) use WorkManager.
            scheduleJob();
        } else {
            // Handle message within 10 seconds
            handleNow();
        }

    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}

שינוי onDeletedMessages

במצבים מסוימים, FCM לא יכולה להעביר הודעה. הדבר קורה כשיש יותר מדי הודעות (מעל 100) בהמתנה עבור האפליקציה שלך במכשיר מסוים בזמן שהיא מתחברת או אם המכשיר לא מחובר FCM ביותר מחודש אחד. במקרים כאלה, יכול להיות שתקבלו קריאה חוזרת ל-FirebaseMessagingService.onDeletedMessages(). כשמכונה של אפליקציה מקבלת את הקריאה החוזרת הזו, היא צריכה לבצע סנכרון מלא עם שרת האפליקציה. אם לא שלחת הודעה לאפליקציה המכשיר ב-4 השבועות האחרונים, FCM לא יתקשר למספר onDeletedMessages().

טיפול בהודעות של התראות באפליקציה ברקע

כשהאפליקציה פועלת ברקע, Android מפנה הודעות התראה אל במגש המערכת. הקשה של משתמש על ההתראה פותחת את מרכז האפליקציות על ידי כברירת מחדל.

הנתונים האלה כוללים הודעות שמכילות גם הודעה וגם עומס נתונים (וכל ההודעות שנשלחות ממסוף ההתראות). במקרים כאלה, ההתראה מועברת לסרגל המערכת של המכשיר, ועומסי הנתונים מועברים ב-extras של ה-intent של הפעילות של מרכז האפליקציות.

לקבלת תובנות לגבי מסירת ההודעות לאפליקציה שלך: ה FCM במרכז הבקרה לדיווח, שבו נרשם מספר ההודעות שנשלחו ונפתחו במכשירי Apple ו-Android, יחד עם נתונים לגבי 'חשיפות' (התראות שמשתמשים רואים) באפליקציות ל-Android.

קבלת הודעות FCM במצב הפעלה ישירה

מפתחים שרוצים לשלוח הודעות של FCM לאפליקציות עוד לפני המכשיר לא נעול יכול לאפשר לאפליקציה ל-Android לקבל הודעות כשהמכשיר לא נעול נמצאת במצב הפעלה ישירה. לדוגמה, ייתכן שתרצו שהמשתמשים באפליקציה שלכם לקבל התראות על התראות גם במכשיר נעול.

כשיוצרים את התרחיש לדוגמה הזה, חשוב לשים לב שיטות מומלצות והגבלות למצב הפעלה ישירה חשוב במיוחד להביא בחשבון את החשיפה של הודעות שמופעלת בהן הפעלה ישירה. כל משתמש שיש לו גישה למכשיר יכול לראות את ההודעות האלה בלי להזין את פרטי הכניסה של המשתמש.

דרישות מוקדמות

  • יש להגדיר את המכשיר למצב הפעלה ישירה.
  • במכשיר צריכה להיות מותקנת הגרסה העדכנית ביותר של Google Play Services (19.0.54 ואילך).
  • האפליקציה חייבת להשתמש ב-FCM SDK (com.google.firebase:firebase-messaging) כדי לקבל הודעות FCM.

איך מפעילים את הטיפול בהודעות באפליקציה במצב הפעלה ישירה

  1. בקובץ Gradle ברמת האפליקציה, מוסיפים תלות בספריית התמיכה הישירה של FCM:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. כדי להפוך את האפליקציה למודעת את ההפעלה הישירה FirebaseMessagingService, מוסיפים את המאפיין android:directBootAware="true" למניפסט של האפליקציה:

    <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false"
        android:directBootAware="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    

חשוב לוודא שה-FirebaseMessagingService הזה יכול לפעול במצב הפעלה ישירה. לבדיקה לעמוד בדרישות הבאות:

  • השירות לא צריך לגשת לאחסון מוגן בפרטי כניסה בזמן שהוא פועל במצב הפעלה ישירה.
  • אסור לשירות לנסות להשתמש ברכיבים כמו Activities,‏ BroadcastReceivers או Services אחרים שלא מסומנים כרכיבים שתומכים בהפעלה ישירה, בזמן שהוא פועל במצב הפעלה ישירה.
  • בנוסף, אסור לספריות שבהן השירות משתמש לגשת לאחסון שמוגן באמצעות פרטי כניסה, או לבצע קריאה לרכיבים שלא תומכים ב-directBootAware במהלך ההפעלה במצב הפעלה ישירה. כלומר, כל הספריות שבהן האפליקציה משתמשת ומתבצעת קריאה אליהן מהשירות צריכות להיות מותאמות לטעינה ישירה, או שהאפליקציה צריכה לבדוק אם היא פועלת במצב טעינה ישירה ולא לבצע קריאה אליהן במצב הזה. לדוגמה, ערכות ה-SDK של Firebase פועלות עם הפעלה ישירה (אפשר לכלול אותן באפליקציה בלי לגרום לקריסה שלה במצב הפעלה ישירה), אבל ממשקי API רבים של Firebase לא תומכים בקריאה במצב הפעלה ישירה.
  • אם האפליקציה משתמשת ב-Application בהתאמה אישית, צריך לבצע גם הפעלה ישירה של Application (אין גישה לאחסון המוגן באמצעות פרטי כניסה במצב הפעלה ישירה).

אפשר לקבל הנחיות לגבי שליחת הודעות למכשירים במצב הפעלה ישירה: שליחת הודעות עם אפשרות הפעלה ישירה.