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

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

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

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

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

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

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

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

בקצרה:

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

עריכת המניפסט של האפליקציה

כדי להשתמש ב-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() כשמופע האפליקציה מקבל את הקריאה החוזרת (callback) הזו, הוא אמור לבצע סנכרון מלא עם שרת האפליקציות. אם לא שלחת הודעה לאפליקציה המכשיר ב-4 השבועות האחרונים, FCM לא יתקשר למספר onDeletedMessages().

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

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

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

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

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

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

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

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

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

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

  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 צריך להיות תומך גם בהפעלה ישירה (אין גישה לאחסון שמוגן בפרטי כניסה במצב הפעלה ישירה).

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