כדי לטרגט הודעה למספר מכשירים, משתמשים בהודעות בנושאים. התכונה הזו מאפשרת לשלוח הודעה לכמה מכשירים שהביעו הסכמה לקבלת עדכונים בנושא מסוים.
המדריך הזה מתמקד בשליחת הודעות בנושאים משרת האפליקציה באמצעות Admin SDK או API ל-REST של FCM, ובקבלה וטיפול בהודעות באפליקציה ל-Android. נסביר על טיפול בהודעות באפליקציות ברקע ובחזית. תהליך ההגדרה כולל את כל השלבים הנדרשים, משלב ההגדרה ועד האימות.
הגדרת ה-SDK
יכול להיות שבקטע הזה יהיו שלבים שכבר ביצעתם אם הגדרתם אפליקציית לקוח ל-Android ל-FCM או אם ביצעתם את השלבים לשליחת ההודעה הראשונה.
לפני שמתחילים
מתקינים או מעדכנים את Android Studio לגרסה האחרונה.
צריך לוודא שהפרויקט עומד בדרישות הבאות (שימו לב: למוצרים מסוימים יכולות להיות דרישות מחמירות יותר):
- מטרגטת לרמת API 21 (Lollipop) ומעלה
- מכשיר עם Android מגרסה 5.0 ואילך
- נעשה שימוש ב-Jetpack (AndroidX), שכולל עמידה בדרישות הגרסה הבאות:
com.android.tools.build:gradle
גרסה 7.3.0 ואילךcompileSdkVersion
28 ואילך
מגדירים מכשיר פיזי או משתמשים במכונה וירטואלית כדי להריץ את האפליקציה.
חשוב לזכור שחבילות SDK של Firebase עם תלות ב-Google Play Services מחייבות התקנה של Google Play Services במכשיר או במכונה הווירטואלית.נכנסים ל-Firebase באמצעות חשבון Google.
אם עדיין אין לכם פרויקט ב-Android ואתם רוצים לנסות מוצר של Firebase, תוכלו להוריד אחת מהדוגמאות למתחילים.
יצירת פרויקט Firebase
לפני שתוכלו להוסיף את Firebase לאפליקציה ל-Android, תצטרכו ליצור פרויקט Firebase כדי לקשר אותו לאפליקציה. במאמר הסבר על פרויקטים ב-Firebase מוסבר בהרחבה על פרויקטים ב-Firebase.
רישום האפליקציה ב-Firebase
כדי להשתמש ב-Firebase באפליקציה ל-Android, צריך לרשום את האפליקציה בפרויקט Firebase. לעיתים קרובות, רישום האפליקציה נקרא 'הוספת' האפליקציה לפרויקט.
נכנסים למסוף Firebase.
במרכז הדף 'סקירה כללית של הפרויקט', לוחצים על הסמל Android (
) או על הוספת אפליקציה כדי להפעיל את תהליך העבודה להגדרה.מזינים את שם החבילה של האפליקציה בשדה Android package name.
(אופציונלי) מזינים מידע נוסף על האפליקציה: הכינוי של האפליקציה וSHA-1 של אישור החתימה לניפוי באגים.
לוחצים על רישום האפליקציה.
הוספת קובץ תצורה של Firebase
מורידים את קובץ התצורה של Firebase ל-Android (
) ומוסיפים אותו לאפליקציה:google-services.json לוחצים על Download google-services.json כדי לקבל את קובץ התצורה של Firebase ל-Android.
מעבירים את קובץ התצורה לתיקיית השורש של המודול (ברמת האפליקציה) באפליקציה.
כדי לאפשר לערכות ה-SDK של Firebase לגשת לערכים בקובץ התצורה
, צריך את הפלאגין של Google services ל-Gradle (google-services.json google-services
).בקובץ Gradle ברמת השורש (ברמת הפרויקט) (
<project>/build.gradle.kts
או<project>/build.gradle
), מוסיפים את הפלאגין של שירותי Google כתלייה:Kotlin
plugins { id("com.android.application") version "7.3.0" apply false // ... // Add the dependency for the Google services Gradle plugin id("com.google.gms.google-services") version "4.4.2" apply false }
Groovy
plugins { id 'com.android.application' version '7.3.0' apply false // ... // Add the dependency for the Google services Gradle plugin id 'com.google.gms.google-services' version '4.4.2' apply false }
בקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל
<project>/<app-module>/build.gradle.kts
או<project>/<app-module>/build.gradle
), מוסיפים את הפלאגין של שירותי Google:Kotlin
plugins { id("com.android.application") // Add the Google services Gradle plugin id("com.google.gms.google-services") // ... }
Groovy
plugins { id 'com.android.application' // Add the Google services Gradle plugin id 'com.google.gms.google-services' // ... }
הוספת ערכות SDK של Firebase לאפליקציה
בקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל
<project>/<app-module>/build.gradle.kts
או<project>/<app-module>/build.gradle
), מוסיפים את התלות בספרייה Firebase Cloud Messaging ל-Android. מומלץ להשתמש ב-Firebase Android BoM כדי לשלוט בגרסאות הספרייה.כדי ליהנות מחוויה אופטימלית עם Firebase Cloud Messaging, מומלץ להפעיל את Google Analytics בפרויקט Firebase ולהוסיף לאפליקציה את Firebase SDK for Google Analytics.
dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:33.5.1")) // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries // When using the BoM, you don't specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-messaging") implementation("com.google.firebase:firebase-analytics") }
כשמשתמשים ב-Firebase Android BoM, האפליקציה תמיד תשתמש בגרסאות תואמות של ספריות Firebase ל-Android.
(חלופה) מוסיפים יחסי תלות של ספריית Firebase בלי להשתמש ב-BoM
אם בוחרים לא להשתמש ב-Firebase BoM, צריך לציין את כל הגרסאות של ספריות Firebase בשורת התלות שלהן.
שימו לב: אם אתם משתמשים במספר ספריות של Firebase באפליקציה, מומלץ מאוד להשתמש ב-BoM כדי לנהל את הגרסאות של הספריות, וכך לוודא שכל הגרסאות תואמות.
dependencies { // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-messaging:24.0.3") implementation("com.google.firebase:firebase-analytics:22.1.2") }
סנכרון הפרויקט ב-Android עם קובצי Gradle.
הרשמה של אפליקציית הלקוח לנושא
אפליקציות לקוח יכולות להירשם לכל נושא קיים, או ליצור נושא חדש. כשאפליקציית לקוח נרשמת לנושא חדש (שעדיין לא קיים בפרויקט Firebase שלכם), נוצר נושא חדש בשם הזה ב-FCM וכל לקוח יכול להירשם אליו לאחר מכן.
כדי להירשם לנושא, אפליקציית הלקוח קוראת ל-Firebase Cloud Messaging
subscribeToTopic()
עם שם הנושא FCM. השיטה הזו מחזירה Task
, שאפשר להשתמש בו על ידי מאזין להשלמה כדי לקבוע אם המינוי הצליח:
Kotlin+KTX
Firebase.messaging.subscribeToTopic("weather") .addOnCompleteListener { task -> var msg = "Subscribed" if (!task.isSuccessful) { msg = "Subscribe failed" } Log.d(TAG, msg) Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() }
Java
FirebaseMessaging.getInstance().subscribeToTopic("weather") .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { String msg = "Subscribed"; if (!task.isSuccessful()) { msg = "Subscribe failed"; } Log.d(TAG, msg); Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } });
כדי לבטל את ההרשמה, אפליקציית הלקוח קוראת ל-Firebase Cloud Messaging unsubscribeFromTopic()
עם שם הנושא.
קבלת הודעות בנושא וטיפול בהן
FCM מעביר הודעות בנושאים באותו אופן שבו הוא מעביר הודעות אחרות במורד הזרם.
כדי לקבל הודעות, צריך להשתמש בשירות באורך של
FirebaseMessagingService
.
השירות צריך לשנות את הערכים של פונקציות ה-callbacks onMessageReceived
ו-onDeletedMessages
.
חלון הזמן לטיפול בהודעה עשוי להיות קצר מ-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) של ההתראות.
אם לא מגדירים סמל ברירת מחדל מותאם אישית ולא מגדירים סמל במטען הייעודי של ההתראה, מערכת 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 מפנה את הודעות ההתראות למגש המערכת. כשמשתמש מקייש על ההתראה, מרכז האפליקציות נפתח כברירת מחדל.
הנתונים האלה כוללים הודעות שמכילות גם הודעה וגם עומס נתונים (וכל ההודעות שנשלחות ממסוף ההתראות). במקרים כאלה, ההתראה מועברת למגש המערכת של המכשיר, והמטען הייעודי (Payload) של הנתונים מועבר בנוסף לכוונה של הפעילות במרכז האפליקציות.
כדי לקבל תובנות לגבי שליחת הודעות לאפליקציה שלך, אפשר לעיין ב מרכז הבקרה לדיווח של FCM, שבו נרשם מספר ההודעות שנשלחו ונפתחו במכשירי Apple ו-Android, וגם נתוני ה'חשיפות' (התראות שמשתמשים ראו) באפליקציות ל-Android.
יצירת בקשות לשליחה
אחרי שיוצרים נושא, על ידי הרשמה למופעים של אפליקציות לקוח לנושא בצד הלקוח או דרך ה-API של השרת, אפשר לשלוח אליו הודעות. אם זו הפעם הראשונה שאתם יוצרים בקשות שליחה ל-FCM, כדאי לעיין במדריך בנושא סביבת השרת ו-FCM כדי לקבל מידע חשוב על ההגדרה והרקע.
בלוגיקה של השליחה בקצה העורפי, מציינים את שם הנושא הרצוי כפי שמוצג:
Node.js
// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';
const message = {
data: {
score: '850',
time: '2:45'
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
Java
// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setTopic(topic)
.build();
// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'
# See documentation on defining a message payload.
message = messaging.Message(
data={
'score': '850',
'time': '2:45',
},
topic=topic,
)
# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Go
// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Topic: topic,
}
// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
C#
// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";
// See documentation on defining a message payload.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
Topic = topic,
};
// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic" : "foo-bar",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message"
}
}
}
פקודת cURL:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message": {
"topic" : "foo-bar",
"notification": {
"body": "This is a Firebase Cloud Messaging Topic Message!",
"title": "FCM Message"
}
}
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
כדי לשלוח הודעה לשילוב של נושאים, צריך לציין תנאי, שהוא ביטוי בוליאני שמציין את נושאי היעד. לדוגמה, התנאי הבא ישלח הודעות למכשירים שנרשמו ל-TopicA
ול-TopicB
או ל-TopicC
:
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
הפונקציה FCM מחשבת קודם את כל התנאים בסוגריים, ואז מחשבת את הביטוי מימין לשמאל. בביטוי שלמעלה, משתמש שנרשם לנושא מסוים לא מקבל את ההודעה. גם משתמש שלא נרשם ל-TopicA
לא מקבל את ההודעה. השילובים הבאים מקבלים אותו:
TopicA
וגםTopicB
TopicA
וגםTopicC
אפשר לכלול עד חמישה נושאים בביטוי המותנה.
כדי לשלוח לתנאי:
Node.js
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';
// See documentation on defining a message payload.
const message = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
condition: condition
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
Java
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
Message message = Message.builder()
.setNotification(Notification.builder()
.setTitle("$GOOG up 1.43% on the day")
.setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
.build())
.setCondition(condition)
.build();
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"
# See documentation on defining a message payload.
message = messaging.Message(
notification=messaging.Notification(
title='$GOOG up 1.43% on the day',
body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
),
condition=condition,
)
# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Go
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Condition: condition,
}
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
C#
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
var message = new Message()
{
Notification = new Notification()
{
Title = "$GOOG up 1.43% on the day",
Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
},
Condition = condition,
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"condition": "'dogs' in topics || 'cats' in topics",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message",
}
}
}
פקודת cURL:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"notification": {
"title": "FCM Message",
"body": "This is a Firebase Cloud Messaging Topic Message!",
},
"condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
השלבים הבאים
- תוכלו להשתמש בשרת כדי להירשם למופעים של אפליקציות לקוח לנושאים ולבצע משימות ניהול אחרות. ניהול מינויים לנושאים בשרת