שליחת הודעות בנושאים ב-Android

בהתאם למודל 'פרסום/הרשמה', שליחת הודעות בנושא FCM מאפשרת לשלוח הודעה לכמה מכשירים שהביעו הסכמה לקבל הודעות בנושא מסוים. אתם כותבים הודעות בנושאים לפי הצורך, ו-FCM מטפלת בניתוב ובמסירה מהימנה של ההודעה למכשירים הנכונים.

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

כמה דברים שכדאי לזכור לגבי נושאים:

  • העברת הודעות לפי נושא מתאימה במיוחד לתוכן כמו מזג האוויר או מידע אחר שזמין לכולם.
  • הודעות בנושאים מותאמות לזרימת נתונים ולא לזמן אחזור. כדי לשלוח הודעות במהירות ומאובטחת למכשירים ספציפיים או לקבוצות קטנות של מכשירים, צריך לטרגט הודעות לאסימוני רישום ולא לנושאים.
  • אם רוצים לשלוח הודעות לכמה מכשירים לכל משתמש, כדאי לשקול את האפשרות העברת הודעות בקבוצת מכשירים בתרחישים כאלה.
  • אפשר להירשם ללא הגבלה לכל נושא. עם זאת, FCM אוכף מגבלות בתחומים הבאים:
    • מכונה אחת של אפליקציה יכולה להירשם לעד 2,000 נושאים.
    • אם אתם משתמשים בייבוא באצווה כדי להירשם למופעי אפליקציה, כל בקשה מוגבלת ל-1,000 מופעי אפליקציה.
    • תדירות המינויים החדשים מוגבלת לכל פרויקט. אם תשלחו יותר מדי בקשות להרשמה בפרק זמן קצר, השרתים של FCM ישיבו עם 429 RESOURCE_EXHAUSTED ('המכסה שלך עולה על המכסה'). ניסיון חוזר עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff).

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

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

ניהול מינויים לנושאים בשרת

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

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

אפשר להעביר רשימה של אסימוני רישום לשיטת המינוי Firebase Admin SDK כדי לרשום את המכשירים המתאימים לנושא:

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Subscribe the devices corresponding to the registration tokens to the
// topic.
getMessaging().subscribeToTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch((error) => {
    console.log('Error subscribing to topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Subscribe the devices corresponding to the registration tokens to the
// topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Subscribe the devices corresponding to the registration tokens to the
# topic.
response = messaging.subscribe_to_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were subscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Subscribe the devices corresponding to the registration tokens to the
// topic.
response, err := client.SubscribeToTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were subscribed successfully")

C#‎

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Subscribe the devices corresponding to the registration tokens to the
// topic
var response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");

באמצעות Admin FCM API אפשר גם לבטל את המינוי של מכשירים לנושא, על ידי העברת אסימוני רישום לשיטה המתאימה:

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
getMessaging().unsubscribeFromTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch((error) => {
    console.log('Error unsubscribing from topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Unubscribe the devices corresponding to the registration tokens from the
# topic.
response = messaging.unsubscribe_from_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were unsubscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
response, err := client.UnsubscribeFromTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were unsubscribed successfully")

C#‎

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Unsubscribe the devices corresponding to the registration tokens from the
// topic
var response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were unsubscribed successfully");

השיטות subscribeToTopic() ו-unsubscribeFromTopic() יוצרות אובייקט שמכיל את התשובה מ-FCM. לפורמט של סוג ההחזרה יש אותו פורמט ללא קשר למספר האסימונים לרישום שצוינו בבקשה.

במקרה של שגיאה (כשהאימות נכשל, כשהנושא או הטוקן לא חוקיים וכו'), השימוש בשיטות האלה גורם לשגיאה. רשימה מלאה של קודי השגיאה, כולל תיאורים והוראות לפתרון, מופיעה במאמר שגיאות ב-Admin FCM API.

קבלה וטיפול בהודעות בנושאים

FCM מעבירה הודעות בנושא בדיוק כמו הודעות אחרות במורד הזרם (downstream).

כדי לקבל הודעות, צריך להשתמש בשירות באורך של FirebaseMessagingService. השירות אמור לבטל את הקריאות החוזרות 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>

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

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

השלבים הבאים