Based on the publish/subscribe model, FCM topic messaging allows you to send a message to multiple devices that have opted in to a particular topic. You compose topic messages as needed, and Firebase handles routing and delivering the message reliably to the right devices.
For example, users of a local weather forecasting app could opt in to a "severe weather alerts" topic and receive notifications of storms threatening specified areas. Users of a sports app could subscribe to automatic updates in live game scores for their favorite teams.
Some things to keep in mind about topics:
- Topic messaging supports unlimited topics and subscriptions for each app.
- Topic messaging is best suited for content such as news, weather, or other publicly available information.
- Topic messages are optimized for throughput rather than latency. For fast, secure delivery to single devices or small groups of devices, target messages to tokens, not topics.
- If you need to send messages to multiple devices per user, consider Device Group messaging for those use cases.
Subscribe the client app to a topic
Client apps can subscribe to any existing topic, or they can create a new topic. When a client app subscribes to a new topic name (one that does not already exist for your Firebase project), a new topic of that name is created in FCM and any client can subsequently subscribe to it.
The
FIRMessaging
class handles
topic messaging functionality. To subscribe to a topic, call subscribeToTopic:topic
from your application's main thread (FCM is not thread-safe):
[[FIRMessaging messaging] subscribeToTopic:@"/topics/news"]; NSLog(@"Subscribed to news topic");
This makes an asynchronous request to the FCM backend and subscribes the client to the given topic. If the subscription request fails initially, FCM retries until it can subscribe to the topic successfully. Each time the app starts, FCM makes sure that all requested topics have been subscribed.
To unsubscribe, call unsubscribeFromTopic:topic
,
and FCM unsubscribes from the topic in the background.
Manage topic subscriptions on the server
You can take advantage of Instance ID APIs to perform basic topic management tasks from the server side. Given the registration token(s) of client app instances, you can do the following:
-
Find out details about a client app instance's subscriptions, including each topic name and subscribe date. See Get information about app instances.
-
Subscribe or unsubscribe an app instance to a topic. See Create a relationship mapping for an app instance.
-
Subscribe or unsubscribe multiple app instances to a topic. See Manage relationship maps for multiple app instances.
Receive and handle topic messages
FCM delivers topic messages in the same way as other downstream messages.
For devices running iOS 9 and below, implement AppDelegate application:didReceiveRemoteNotification:
to handle notifications received when the client app is in the foreground,
and all data messages that are sent to the client. The message is a dictionary of
keys and values.
Objective-C
// To receive notifications for iOS 9 and below. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // If you are receiving a notification message while your app is in the background, // this callback will not be fired till the user taps on the notification launching the application. // TODO: Handle data of notification // Print message ID. NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); // Print full message. NSLog(@"%@", userInfo); }
Swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // If you are receiving a notification message while your app is in the background, // this callback will not be fired till the user taps on the notification launching the application. // TODO: Handle data of notification // Print message ID. print("Message ID: \(userInfo["gcm.message_id"]!)") // Print full message. print("%@", userInfo) }
For devices running iOS 10 and above, implement UNUserNotificationCenterDelegate userNotificationCenter:willPresentNotification:withCompletionHandler:
to handle notifications received when the client app is in the foreground. The message is a UNNotification
object.
Implement FIRMessagingDelegate applicationReceivedRemoteMessage:
to handle all data messages that are sent to the client. The message is a FIRMessagingRemoteMessage
object.
Objective-C
// Receive displayed notifications for iOS 10 devices. #if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { // Print message ID. NSDictionary *userInfo = notification.request.content.userInfo; NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); // Print full message. NSLog(@"%@", userInfo); } // Receive data message on iOS 10 devices. - (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { // Print full message NSLog(@"%@", [remoteMessage appData]); } #endif
Swift
@available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { // Receive displayed notifications for iOS 10 devices. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo // Print message ID. print("Message ID: \(userInfo["gcm.message_id"]!)") // Print full message. print("%@", userInfo) } } extension AppDelegate : FIRMessagingDelegate { // Receive data message on iOS 10 devices. func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) { print("%@", remoteMessage.appData) } }
Build send requests
From the server side, sending messages to a Firebase Cloud Messaging topic is very similar to
sending messages to an individual device or to a user group. The app
server sets the to
key with a value like /topics/yourTopic
.
Developers can
choose any topic name that matches the regular expression:
"/topics/[a-zA-Z0-9-_.~%]+"
.
To send to combinations of multiple topics, the app server sets the
condition
key to a boolean condition that specifies the
target topics. For example, to send messages to devices that subscribed
to TopicA
and either TopicB
or
TopicC
:
'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)
FCM first evaluates any conditions in parentheses, and then evaluates the expression from left to right. In the above expression, a user subscribed to any single topic does not receive the message. Likewise, a user who does not subscribe to TopicA does not receive the message. These combinations do receive it:
- TopicA and TopicB
- TopicA and TopicC
Conditions for topics support two operators per expression, and parentheses are supported.
For more detail about app server keys, see the reference information for your chosen connection server protocol, HTTP or XMPP. Examples in this page show how to send data messages to topics in both HTTP and XMPP.
HTTP POST request
Send to a single topic:
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
"to": "/topics/foo-bar",
"data": {
"message": "This is a Firebase Cloud Messaging Topic Message!",
}
}
Send to devices subscribed to topics "dogs" or "cats":
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
"condition": "'dogs' in topics || 'cats' in topics",
"data": {
"message": "This is a Firebase Cloud Messaging Topic Message!",
}
}
HTTP response
//Success example: { "message_id": "1023456" } //failure example: { "error": "TopicsMessageRateExceeded" }
XMPP message
Send to a single topic:
<message id="">
<gcm xmlns="google:mobile:data">
{
"to": "/topics/foo-bar",
"message_id": "m-1366082849205" ,
"data": {
"message":"This is a Firebase Cloud Messaging Topic Message!"
}
}
</gcm>
</message>
Send to devices subscribed to topics "dogs" or "cats":
<message id="">
<gcm xmlns="google:mobile:data">
{
"condition": "'dogs' in topics || 'cats' in topics",
"data": {
"message": "This is a Firebase Cloud Messaging Topic Message!",
}
}
</gcm>
</message>
XMPP response
//Success example: { "message_id": "1023456" } //failure example: { "error": "TopicsMessageRateExceeded" }
Expect up to 30 seconds of delay before the FCM Connection Server returns a success or failure response to the topic send requests. Make sure to set the app server's timeout value in the request accordingly.
For the full list of message options, see the reference information for your chosen connection server protocol, HTTP or XMPP.
Next steps
- Learn more about the other way to send to multiple devices — Device group messaging