במדריך הזה מוסבר איך להגדיר את Firebase Cloud Messaging באפליקציות הלקוח לנייד ולאינטרנט כדי לקבל הודעות בצורה מהימנה.
כדי לקבל הודעות, צריך להשתמש בשירות שמרחיב את FirebaseMessagingService
.
השירות שלכם צריך לבטל את ההגדרות של הקריאות החוזרות onMessageReceived
ו-onDeletedMessages
.
onMessageReceived
מסופק לרוב סוגי ההודעות, למעט:
הודעות התראה שנמסרות כשהאפליקציה פועלת ברקע. במקרה הזה, ההתראה מועברת למגש המערכת של המכשיר. כשמשתמש מקיש על הודעה, מרכז האפליקציות נפתח כברירת מחדל.
הודעות עם מטען ייעודי (payload) של התראה ונתונים, כשהן מתקבלות ברקע. במקרה כזה, ההתראה מועברת למגש המערכת של המכשיר, ומטען הנתונים מועבר בתוספות של ה-Intent של פעילות מרכז האפליקציות.
בקצרה:
מצב האפליקציה | התראה | נתונים | שניהם |
---|---|---|---|
חזית | onMessageReceived |
onMessageReceived |
onMessageReceived |
רקע | מגש המערכת | onMessageReceived |
התראה: מגש המערכת נתונים: בתוספות של הכוונה. |
מידע נוסף על סוגי הודעות זמין במאמר התראות והודעות נתונים.
ה-callback onMessageReceived
מקבל פסק זמן שמאפשר לפרסם התראה, אבל הטיימרים לא מיועדים לאפשר לאפליקציה לגשת לרשת או לבצע פעולות נוספות. לכן, אם האפליקציה שלכם מבצעת פעולות מורכבות יותר, תצטרכו לבצע פעולות נוספות כדי לוודא שהאפליקציה תוכל להשלים את הפעולות שלה.
אם אתם חושבים שהאפליקציה שלכם עשויה להזדקק לזמן של כמעט 10 שניות כדי לטפל בהודעה, כדאי לתזמן משימה של WorkManager או לפעול לפי ההנחיות בנושא WakeLock שבהמשך. במקרים מסוימים, חלון הזמן לטיפול בהודעה עשוי להיות קצר מ-10 שניות, בהתאם לעיכובים שקורים לפני הקריאה של 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) של ההתראה.
אם לא מוגדר סמל ברירת מחדל מותאם אישית ולא מוגדר סמל במטען הייעודי (payload) של ההתראה, מערכת Android מציגה את סמל האפליקציה בצבע לבן.
שינוי של onMessageReceived
אפשר לבצע פעולות על סמך האובייקט RemoteMessage שהתקבל ולקבל את נתוני ההודעה על ידי ביטול השיטה FirebaseMessagingService.onMessageReceived
:
Kotlin
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. }
המכשיר לא יכול לעבור למצב שינה בזמן טיפול בהודעות FCM
אם האפליקציה צריכה למנוע את כניסת המכשיר למצב שינה בזמן עיבוד הודעת FCM, היא צריכה להחזיק WakeLock במהלך הזמן הזה או ליצור משימה ב-WorkManager. WakeLocks מתאימים לפעילויות עיבוד קצרות שעשויות לחרוג מהזמן הקצוב לתפוגה שמוגדר כברירת מחדל onMessageReceived
. בתהליכי עבודה מורחבים, כמו שליחת כמה קריאות RPC סדרתיות לשרתים, עדיף להשתמש במשימה של WorkManager מאשר ב-WakeLock. בקטע הזה נתמקד בהסבר על השימוש ב-WakeLocks. WakeLock מונע מהמכשיר להיכנס למצב שינה בזמן שהאפליקציה פועלת, מה שעלול להגביר את השימוש בסוללה. לכן, השימוש ב-WakeLock צריך להיות שמור למקרים שבהם האפליקציה לא צריכה להיות מושהית בזמן הטיפול בהודעה, כמו:
- התראות למשתמש שהן תלויות-זמן.
- אינטראקציות עם משהו מחוץ למכשיר שלא צריך להפריע לו (כמו העברות ברשת או תקשורת עם מכשיר אחר, כמו שעון משויך).
קודם צריך לוודא שהאפליקציה מבקשת את ההרשאה WakeLock (ההרשאה הזו כלולה ב-FCM SDK כברירת מחדל, כך שבדרך כלל לא צריך להוסיף כלום).
<uses-permission android:name="android.permission.WAKE_LOCK" />
לאחר מכן, האפליקציה צריכה לקבל WakeLock בתחילת הקריאה החוזרת (callback) של FirebaseMessagingService.onMessageReceived()
ולשחרר אותו בסוף הקריאה החוזרת.
FirebaseMessagingService
בהתאמה אישית של האפליקציה:
@Override
public void onMessageReceived(final RemoteMessage message) {
// If this is a message that is time sensitive or shouldn't be interrupted
WakeLock wakeLock = getSystemService(PowerManager.class).newWakeLock(PARTIAL_WAKE_LOCK, "myApp:messageReceived");
try {
wakeLock.acquire(TIMEOUT_MS);
// handle message
...
finally {
wakeLock.release();
}
}
שינוי של onDeletedMessages
במקרים מסוימים, יכול להיות שההודעה לא תועבר דרך FCM. השגיאה הזו מתרחשת כשיש יותר מדי הודעות (מעל 100) בהמתנה לאפליקציה במכשיר מסוים בזמן החיבור, או אם המכשיר לא התחבר אל FCM במשך יותר מחודש. במקרים כאלה, יכול להיות שתקבלו שיחת טלפון חוזרת למספר FirebaseMessagingService.onDeletedMessages()
. כשמופע האפליקציה מקבל את הקריאה החוזרת הזו, הוא צריך לבצע סנכרון מלא עם שרת האפליקציה. אם לא שלחתם הודעה לאפליקציה במכשיר הזה ב-4 השבועות האחרונים, FCM לא יתקשרו אליכם onDeletedMessages()
.
טיפול בהודעות התראה באפליקציה שפועלת ברקע
כשהאפליקציה פועלת ברקע, מערכת Android מפנה את הודעות ההתראה למגש המערכת. כברירת מחדל, הקשה של משתמש על ההתראה פותחת את מרכז האפליקציות.
זה כולל הודעות שמכילות גם התראה וגם מטען נתונים (וכל ההודעות שנשלחות ממסוף ההתראות). במקרים כאלה, ההתראה מועברת למגש המערכת של המכשיר, ומטען הנתונים מועבר בתוספים של ה-Intent של פעילות מרכז האפליקציות.
כדי לקבל תובנות לגבי מסירת הודעות לאפליקציה, אפשר לעיין ב
FCMלוח הבקרה של הדוחות, שבו מתועד מספר ההודעות שנשלחו ונפתחו במכשירי Apple ובמכשירי Android, וגם נתונים לגבי 'חשיפות' (התראות שהמשתמשים ראו) באפליקציות ל-Android.