שליחת הודעות למספר מכשירים

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

המדריך הזה מתמקד בשליחת הודעות בנושא משרת האפליקציה באמצעות Admin SDK או REST API ל-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 ואילך
  • מגדירים מכשיר פיזי או משתמשים באמולטור כדי להריץ את האפליקציה.
    שימו לב: כדי להשתמש ב-Firebase SDKs עם תלות בשירותי Google Play, צריך להתקין את שירותי Google Play במכשיר או באמולטור.

  • נכנסים ל-Firebase באמצעות חשבון Google.

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

יצירת פרויקט Firebase

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

רישום האפליקציה ב-Firebase

כדי להשתמש ב-Firebase באפליקציית Android, צריך לרשום את האפליקציה בפרויקט Firebase. רישום האפליקציה נקרא לעיתים קרובות "הוספה" של האפליקציה לפרויקט.

  1. עוברים אל מסוף Firebase.

  2. במרכז הדף 'סקירת הפרויקט', לוחצים על הסמל Android () או על הוספת אפליקציה כדי להפעיל את תהליך ההגדרה.

  3. מזינים את שם החבילה של האפליקציה בשדה שם החבילה של Android.

  4. (אופציונלי) מזינים פרטים נוספים על האפליקציה: כינוי לאפליקציה ואישור חתימה לניפוי באגים SHA-1.

  5. לוחצים על רישום האפליקציה.

הוספת קובץ הגדרות של Firebase

  1. מורידים את קובץ התצורה של Firebase (google-services.json) של האפליקציה ומוסיפים אותו לבסיס הקוד:

    1. לוחצים על הורדת google-services.json כדי לקבל את קובץ התצורה של Firebase של האפליקציה.

    2. מעבירים את קובץ ההגדרות אל ספריית השורש של המודול (ברמת האפליקציה) של האפליקציה.

  2. כדי שהערכים בקובץ ההגדרות google-services.json יהיו נגישים ל-Firebase SDKs, צריך את Google services Gradle plugin ‏(google-services).

    1. בקובץ 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.3" 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.3' apply false
      }
    2. בקובץ 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 לאפליקציה

  1. בקובץ 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:34.0.0"))
    
        // 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:25.0.0")
        implementation("com.google.firebase:firebase-analytics:23.0.0")
    }

  2. מסנכרנים את פרויקט Android עם קובצי Gradle.

הרשמה של אפליקציית הלקוח לנושא

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

כדי להירשם למינוי לנושא, אפליקציית הלקוח קוראת ל-Firebase Cloud Messaging subscribeToTopic() עם שם הנושא FCM. השיטה הזו מחזירה Task, שניתן להשתמש בו על ידי listener של השלמה כדי לקבוע אם המינוי הצליח:

Kotlin

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

בקצרה:

מצב האפליקציה התראה נתונים שניהם
חזית 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

אפשר לבצע פעולות על סמך האובייקט 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.
}

השבתה של onDeletedMessages

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

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

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

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

כדי לקבל תובנות לגבי מסירת הודעות לאפליקציה, אפשר לעיין ב 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

השלבים הבאים