Your first multicast push message using FCM topics

1. Introduction

Goals

In this codelab you will learn how to instrument your multi-platform app so that you can multicast push messages to various subgroups of your app instances using FCM topics.

Once finished, you will be able to leverage the FCM infrastructure to manage these subgroups as well as multicast push messages over the subgroups.

Topics Overview

Topics are an FCM infrastructure supported way of reaching subgroups of your app instances with messages.

FCM provides the APIs to send messages as well as maintain subscriptions to these topics. The act of associating and dissociating an app instance to topic is called subscribe and unsubscribe respectively

Topics should be used for publicly available content. For instance, messages about weather updates. If you want to send user-sensitive messages, use the Firebase Admin SDK for multicasting messages over multiple devices.

Topics-based multicasting is optimized for throughput.

What you'll learn

  • How to subscribe (and unsubscribe) users to topics from a mobile app.
  • How to send multicast push messages using topics.
  • How to send messages to a combination of topics using topic conditions.
  • How to manage topic subscriptions on the server side and do bulk subscriptions and unsubscriptions.

What you'll build

  • An Android App that subscribes/unsubscribes to topics and receives messages when sent to the topics.
  • A server side integration using the Firebase Admin SDK, which will be used to send topic messages via FCM APIs.

What you'll need

  • A browser of your choice, such as Chrome.
  • IntelliJ IDEA IDE for developing Java applications.
    • Make sure to opt-in support for Gradle while installing.
  • Android Studio IDE for developing Android applications.
  • A device to run the Android application. Either of:
    • The Android emulator. (Requires setup in Android Studio).
    • A physical Android device connected to your computer and set to developer mode.
  • A Google account for creating and managing your Firebase project.

2. Getting set up

Get the code

Clone the GitHub repository from the command line:

git clone https://github.com/firebase/quickstart-android.git fcm-codelab

The sample code will be cloned into the fcm-codelab directory.

cd fcm-codelab

The starter app for this codelab is in the messaging directory of the fcm-topics-codelab branch. Take the following steps to reach the starter code. It contains two directories StockNewsApp and StockNewsServer. The former contains the starter Android App and the latter has the starter server side code.

git checkout fcm-topics-codelab
cd messaging/fcm-topics-codelab/starter

The completed version of this codelab is placed in the messaging/fcm-topics-codelab/completed directory.

Create a Firebase project

  1. In the Firebase console, click Add project, name the Firebase project StockNews and click continue. Note: Remember the Project ID for your Firebase project (or click the Edit icon to set your preferred Project ID).

fc08f9a7808e4553.png

  1. You can skip enabling Google Analytics. For the purposes of this codelab, you don't need it. Click Continue.
  2. Click Create project.

Congratulations! You just created your Firebase project. Now, you can click on the project name to enter the console.

3. Platform-specific Firebase app configuration

Most of the code changes required to enable Firebase support are already checked into the project that you're working on. However, in order to add support for mobile platforms, you need to:

  • Register the desired platform on the Firebase project
  • Download the platform-specific configuration file, and add it to the code.

For the purposes of this codelab, we are going to be adding an Android Firebase app.

84e0b3199bef6d8a.pngConfigure Android

  1. In the Firebase Console, select Project Settings in the top of the left navigation bar in the Settings cog, and click the Android icon under Your apps in the General page.

You should see the following dialog : 8254fc299e82f528.png

  1. The important value to provide is the Android package name. Set it to com.ticker.stocknews.
    1. The package name provided here must be the same as the one provided in the AndroidManifest.xml of your starter StockNewsApp code. If you would like to locate or change it, follow these steps:
      1. In the StockNewsApp directory, open the file app/src/main/AndroidManifest.xml.
      2. In the manifest element, find string value of the package attribute. This value is the Android package name.
  1. In the Firebase dialog, paste the copied package name into the Android package name field.
  2. You don't need the Debug signing certificate SHA-1 for this codelab, because this app won't be released. Leave this blank.
  3. Click Register App.
  4. Continuing in the Firebase Console, follow the instructions to download the configuration file google-services.json.
  5. You can skip the remaining setup steps, as everything else is already configured in the starter app code. You will find your app listed on the main page of Firebase Console.
  6. Copy the google-services.json file (that you just downloaded) to messaging/fcm-topics-codelab/starter/StockNewsApp/app directory.

4. Build and run your app

You're ready to actually start work on your app! First, build and run the app.

Import the starter app

Start Android Studio, and import the messaging/fcm-topics-codelab/starter/StockNewsApp from the starter code directory.

After the project has loaded, you may also see an alert that Git isn't tracking all your local changes, you can click "Ignore" or the "X" in the upper right. (You won't be pushing any changes back to the Git repo.)

In the upper-left corner of the project window, you should see something like the image below if you are in the Android view. (If you are in the Project view, you will need to expand the project to see the same thing)

b574ea0089ee87c6.png

Please note that Android Studio might take several seconds to compile the project in the background for the first time. During this time you will see a spinner in the status bar at the bottom of Android Studio:

4bc64eb3b99eb0ae.png

We recommend that you wait until this has finished before making code changes. This will allow Android Studio to pull in all the necessary components.

In addition, if you get a prompt saying "Reload for language changes to take effect?" or something similar, select "Yes".

Emulator Setup

If you need help setting up an Android emulator, refer to the Run your app article.

Understand the Android App starter code

  • The starter code is a lightweight Android App with minimal functionality and UI.
  • A dependency to firebase-messaging SDK is already added to the app/build.gradle file.

f04ff8f48d186dff.png

  • In the AndroidManifest.xml, a MESSAGING_EVENT callback handler is already added.
    • This handler, StockNewsMessagingService.java extends the FirebaseMessagingService class which provides various Firebase Cloud Messaging related functionality. See FirebaseMessagingService documentation to learn more. b843c4d33ee53166.png
    88fad1960f4a6ff5.png
    • The onNewToken function gets called when the FCM Registration Token is created or refreshed. See Monitor token generation for more information.
    • The onMessageReceived function gets called when a message is received and the app is in foreground. Currently, it simply logs the received message.
  • Also, in AndroidManifest.xml, an Android Application class is also provided named StockNewsApplication. a4982a8731492dfc.pngccde692f7f68dc5a.png
    • This class will be the first one to be instantiated when the App starts up.
    • In StockNewsApplication class's onCreate function, an FCM Registration Token creation call is added. It will generate a valid FCM Registration Token and log it.
  • The MainActivity.java adds the RecyclerView that displays the Stock Category choices.
  • SubscriptionAdapter.java implements RecyclerView.Adapter which draws the Stock Category selection screen.
    • Each Stock Category has a name and a subscription toggle next to it.
    • Changing the toggle should make an FCM topic subscription / unsubscription call.
    • You will implement these calls in the upcoming sections.
  • The model/StockCategories.java class contains a list of all Stock Categories and their associated topic names.

b32663ec4e865a18.png

Run the starter app

  1. Connect your Android device to your computer or start an emulator.
  2. In the top toolbar, select your target Android device or emulator and press the run button.

5b27fc5b237e06b9.png

  1. The App UI will look like follows:

ff5b1a1c53231c54.png

  1. The app will create an FCM Registration Token and log it. However nothing will change in the App UI.
    1. Copy and save the FCM Registration Token as it will be used in next steps.

927eb66bc909f36b.png

5. Send a Test Message

Now you are ready to send a test message to the app instance you had set up in the last step.

Import the starter server code

Start IntelliJ IDEA and open the messaging/fcm-topics-codelab/starter/StockNewsServer project.

The project view in your left navigation bar, should look something like this:

da20711f6527dff6.png

Note, it might take a few minutes for IntellIj IDEA to build your project, including pulling the required dependencies.

Understand the server starter code

  • The server starter code is a Gradle-based Java project.
  • The build.gradle file already has the dependency on the firebase-admin SDK added to it. This SDK provides access to various FCM message send functionalities.

650fc733298588f8.png

  • Finally, there are two classes, viz:
    • FcmSender.java: This class contains following methods of note:
      • initFirebaseSDK: Initializes firebase-admin SDK.
      • sendMessageToFcmRegistrationToken: send a message to an FCM Registration Token.
      • sendMessageToFcmTopic: send a message to an FCM topic.
      • sendMessageToFcmTopicCondition: send a message to an FCM topic condition.
    • FcmSubscriptionManager.java: This class contains methods that allow managing topic subscriptions from server side.
      • initFirebaseSDK: Initializes firebase-admin SDK.
      • subscribeFcmRegistrationTokensToTopic: subscribe FCM Registration Token(s) to an FCM topic.
      • unsubscribeFcmRegistrationTokensFromTopic: unsubscribe FCM Registration Token(s) from an FCM topic.

Setting up the server code

  1. First, we need to set up a Firebase Service Account that allows firebase-admin SDK to authorize calls to FCM APIs.
    1. Go to the Firebase Console, click on the gear icon next to Project Overview in the left navigation bar, and select Project settings. 8c2108d4d7c915e9.png
    2. In the settings page, select Service accounts and click Create service account. 84b128cc5dac0a85.png
    3. Now click on Generate new private key button and an automatic download of your key file will begin.
    4. Rename the key file to service-account.json and copy it in the messaging/fcm-topics-codelab/starter/StockNewsServer/src/main/resources folder.
    5. Both FcmSender.java and FcmSubscriptionManager.java load the service-account.json file from classpath using the following code. 8dffbee658e0bdd.png
  2. At this point, the server code is ready. Run Build -> Build Project from the top menu bar.

Sending a Test Message

  1. In FcmSender.java locate the sendMessageToFcmRegistrationToken function and insert the FCM registration token you copied from Run the starter app section into the registrationToken field.
  2. In the main function, uncomment just the sendMessageToFcmRegistrationToken function and click run to execute the code.
    1. Observe how the FCM Registration Token is set into the Token field of the message object.
    2. Furthermore, notice how we have used the send API of FirebaseMessaging interface.

52e4a3ec3f816473.png

  1. This should send a message to the app instance that you have set up in the previous step.
  2. When the app instance is in foreground, you should see the message content logged.

d3540ec1089f97dd.png

  1. And when the App instance is in background, you would observe the message appear in the notifications tray.

31203deca59c03fe.png

Awesome, you used Firebase Admin SDK to send messages to an app instance. Read more about using Firebase Admin SDK in your server.

6. Implement Topic Subscription / Unsubscription

In this step you will implement topic subscription and unsubscription actions, on the Stock Category toggle of the Android App.

When an App user toggles the switch for a particular Stock Category, a topic subscription or unsubscription call will be made.

Review code

  • Navigate to the SubscriptionAdapter.java class in the Android App code and locate the RecyclerViewViewHolder class.

6c0614199e684f6.png

  • The class constructor sets up a listener for the subscription toggle by using setOnCheckedChangeListener.
  • Depending on the switch toggle, subscribe and unsubscribe actions are performed by calling subscribeToStockCategory and unsubscribeFromStockCategory methods respectively.
  • The setData method gets called by the RecyclerView Adapter's onBindViewHolder to bind the ViewHolder with appropriate Stock Category.

Implement topic subscription

  1. In the subscribeToStockCategory method, you will implement the call to subscribeToTopic API of FirebaseMessaging object. The code could look something like this:
   void subscribeToStockCategory() {
      // Making call to FCM for subscribing to the topic for stockCategory
     FirebaseMessaging.getInstance().subscribeToTopic(stockCategory.getTopicName()).addOnSuccessListener(
          unused -> {
            // Subscribing action successful
            Log.i(TAG, "Subscribed to topic: " + stockCategory.getTopicName());
            Toast.makeText(itemView.getContext(), "Subscribed to " + stockCategory.getCategoryName(),
                Toast.LENGTH_SHORT).show();
          });
    }

Implement topic unsubscription

  1. Similarly, in the else condition, you will implement the call to unsubscribeFromTopic API. Something along the lines of follows:
void unsubscribeFromStockCategory() {
      // Making call to FCM for unsubscribing from the topic for stockCategory
      FirebaseMessaging.getInstance().unsubscribeFromTopic(stockCategory.getTopicName())
          .addOnSuccessListener(unused -> {
            // Unsubscribing action successful
            Log.i(TAG, "Unsubscribed from topic: " + stockCategory.getTopicName());
            Toast.makeText(itemView.getContext(), "Unsubscribed from " + stockCategory.getCategoryName(),
                Toast.LENGTH_SHORT).show();
          });
    }

Let's try it out

  1. Run the App and toggle the Stock Category options to execute Subscribe and Unsubscribe actions. It would look something like this:

Subscribe

Unsubscribe

7. Sending your first Topic Message

In this step you will implement server side code to send an FCM topic message.

Implement server side integration for sending topic message

  1. In the server code, jump into FcmSender.java and locate the method named sendMessageToFcmTopic.

56381dd1b40cde9c.png

  1. In the first line, provide the FCM Topic that you want to send the message to.
    • It is a string of the form: /topics/<Topic Name>. For example, /topics/Technology.
  2. In the next lines create a new message object (similar to the one defined in the sendMessageToFcmRegistrationToken function).
    • The difference will be instead of setting the Token field of the message object, you will set the Topic field.
Message message = Message.builder()
        .putData("FOOTECH", "$1000")
        .setNotification(
            Notification.builder()
                .setTitle("Investor confidence in Tech Stocks growing")
                .setBody("Foo Tech leading the way in stock growth for Tech sector.")
                .build())
        .setTopic(topicName)
        .build();
  1. Now add the call to FirebaseMessaging instance to send the message (identical to the send call made in the sendMessageToFcmRegistrationToken function).
FirebaseMessaging.getInstance().send(message);
  1. Finally, update the main function and enable the call to only sendMessageToFcmTopic function.

9a6aa08dd7c28898.png

Send message and validate receipt

  1. Before sending the topic message, first ensure that your app instance is subscribed to the topic you want to send to.
    1. This can be done with a flip of the corresponding toggle. For example:
    4668247408377712.png
  2. You can now send your topic message by executing the main function of FcmSender.java.
  3. Like before you should be able to observe the message receipt on the app instance.
    1. App instance in foreground
    c144721399f610fe.png
    1. App instance in background
    44efc7dfd57e8e9a.png
  4. Bonus: Try unsubscribing to the topic you sent to and re-send the message. You would observe that the message is not being delivered to the app instance.

8. Sending your first Topic Condition Message

The topic condition feature allows you to send messages to a combination of topics enabling you to provide more expressive audience definition.

For example, in our StockNews App, consider the possibility of sending messages to a group of app instances who are subscribed to either Technology or Automotive topics. Such a case may occur, for instance, if there is a noteworthy event involving Waymo.

Topics allows you to express your combination in the form of a boolean expression using following operators

  • && : Logical AND. For example, 'Technology' in topics && 'Automotive' in topics - Targets only the app instances that are subscribed to both Technology and Automotive Topics.
  • || : Logical OR. For example, 'Technology' in topics || 'Automotive' in topics - Targets app instances that are subscribed to either Technology or Automotive topics.
  • () : Parentheses for grouping. For example, 'Technology' in topics && ('Automotive' in topics || 'Energy' in topics) - Targets only app instances that are subscribed to Technology and either Automotive or Energy topics.

Read more about how to build send requests for using this functionality.

Implement server side integration for sending topic condition message

  1. Back in the server code, jump into FcmSender.java and locate the method named sendMessageToFcmTopicCondition.

3719a86c274522cf.png

  1. In the first line, for the topicCondition variable, provide the topic condition you want to send the message to. You can set it to: 'Technology' in topics && 'Automotive' in topics.
  2. In the next lines, create a new message object (similar to the one defined in the sendMessageToFcmTopic function).
    1. The difference will be instead of setting the Topic field of the object, you will set the Condition field.
    Message message = Message.builder()
        .putData("FOOCAR", "$500")
        .setNotification(
            Notification.builder()
                .setTitle("Foo Car shows strong Q2 results")
                .setBody("Foo Car crosses 1B miles. Stocks rally.")
                .build())
        .setCondition(topicCondition)
        .build();
  1. Now add the call to FirebaseMessaging instance to send the message (identical to the send call made in the sendMessageToFcmTopic function).
FirebaseMessaging.getInstance().send(message);
  1. Finally, update the main function and enable the call to only sendMessageToFcmTopicCondition function.

db9588d40d2a0da6.png

Send the message and validate receipt

  1. Before sending the topic message, first ensure that your app instance satisfies the specified topic condition by subscribing the app instance to both Technology and Automotive topics.
  2. You can now send your topic message by executing the main function of FcmSender.java.
  3. Like before, you should be able to observe the message receipt on the app instance.
    1. App instance in foreground
    6f612ace15aa6515.png
    1. App instance in background
    78044a56ac2359cb.png
  4. Bonus: You can now unsubscribe from the Technology topic and resend the topic condition message. You should observe that the message is not received by the app instance.

9. Recap

Let's do a quick recap of what you have learned up to this point.

  • How to initiate a topic subscription / unsubscription from an app instance.
  • Sending a message to the topic and verifying receipt on subscribed app instances.
  • Sending a message to a topic Condition and verifying receipt on an app instance that satisfies the condition.

In the next section, you will learn about how you can subscribe / unsubscribe app instances to topics without needing to instantiate calls from the client side.

c0dc20655d392690.gif

10. Manage Topic Subscriptions from Server Side

Until now, in this codelab, all the topic subscriptions and unsubscriptions calls are initiated from an app instance.

However, in some use cases, you might want to manage the topic subscriptions from Server Side. For instance, you might want to subscribe a subgroup of your existing user base to a new topic without waiting for an app rollout.

In this section, you will learn how to use the Firebase Admin SDK to subscribe and unsubscribe a batch of FCM Registration Tokens to a topic by making calls from the server side.

Implement server side subscription of FCM Registration Tokens to FCM topic

  1. In the server code, jump into FcmSubscriptionManager.java class. Locate the method named subscribeFcmRegistrationTokensToTopic. You will implement the call to subscribeToTopic API here.

5d5709e7b3cbcb04.png

  1. Let's subscribe the app instance to the Energy topic. To do that, firstly provide data for the following two fields:
    1. registrationTokens: a comma separated list of strings representing the FCM Registration Tokens that you would like to create topic subscriptions for.
    2. topicName: the topic name for the Energy topic, i.e. /topics/Energy.
  2. In next few lines implement the call, along these lines:
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
        registrationTokens, topicName);
  1. You can inspect the TopicManagementResponse for some high level result stats. Such as printing the number of successfully created topic subscriptions using getSuccessCount.
System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
  1. Finally, in the main function enable calls to only the subscribeFcmRegistrationTokensToTopic function.

Create subscription and send topic message

  1. At this point you are ready to create the topic subscription and send a message to it.
  2. Execute the main function of FcmSubscriptionManager.java class. This will create a topic subscription.
  3. Now, set up the code to send the message. Similar to before,
    1. In the FcmSender.java, locate sendMessageToFcmTopic function.
    2. Set the topicName to the Energy topic, i.e., /topics/Energy.
    3. Create a Message object and target it to the topic using setTopic.
    4. Finally, update the main method to only enable the sendMessageToFcmTopic function.
  4. Execute the main function of FcmSender.java. This will send the message to your app instance and you can observe it in your app as follows.
    1. App instance in foreground
    40ab6cf71e0e4116.png
    1. App instance in background
    8fba81037198209e.png

Implement server side unsubscription of FCM Registration Tokens to FCM topic

  1. For server side topic unsubscriptions, use this unsubscribeFromTopic API. You will add the relevant code to unsubscribeFcmRegistrationTokensFromTopic function of FcmSubscriptionManager.java class.

8d9e8ea9d34016bd.png

  1. Implementing server side unsubscription code and validating its effect by sending a topic message, is left as an exercise for you.

11. Congratulations

Congratulations you have successfully used FCM topics to send multicast messages to subgroups of your app instances. This will help simplify your ability to timely reach your users with relevant content.

947def3eb33b1e4a.gif

What's next?

Now that you have completed your codelab, consider trying out topics for other platforms using the following guides:

Reference Docs