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
- 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).
- You can skip enabling Google Analytics. For the purposes of this codelab, you don't need it. Click Continue.
- 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.
Configure Android
- 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 :
- The important value to provide is the Android package name. Set it to
com.ticker.stocknews
.- 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:- In the StockNewsApp directory, open the file
app/src/main/AndroidManifest.xml
. - In the
manifest
element, find string value of thepackage
attribute. This value is the Android package name.
- In the StockNewsApp directory, open the file
- The package name provided here must be the same as the one provided in the
- In the Firebase dialog, paste the copied package name into the Android package name field.
- You don't need the Debug signing certificate SHA-1 for this codelab, because this app won't be released. Leave this blank.
- Click Register App.
- Continuing in the Firebase Console, follow the instructions to download the configuration file
google-services.json
. - 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.
- Copy the
google-services.json
file (that you just downloaded) tomessaging/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)
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:
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.
- In the
AndroidManifest.xml
, aMESSAGING_EVENT
callback handler is already added.- This handler,
StockNewsMessagingService.java
extends theFirebaseMessagingService
class which provides various Firebase Cloud Messaging related functionality. See FirebaseMessagingService documentation to learn more.
- 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.- See Receive messages in an Android app to learn more about the differences between background and foreground message delivery and handling.
- This handler,
- Also, in
AndroidManifest.xml
, an AndroidApplication
class is also provided namedStockNewsApplication
.- This class will be the first one to be instantiated when the App starts up.
- In
StockNewsApplication
class'sonCreate
function, an FCM Registration Token creation call is added. It will generate a valid FCM Registration Token and log it.
- The
MainActivity.java
adds theRecyclerView
that displays the Stock Category choices. SubscriptionAdapter.java
implementsRecyclerView.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.
Run the starter app
- Connect your Android device to your computer or start an emulator.
- In the top toolbar, select your target Android device or emulator and press the run button.
- The App UI will look like follows:
- The app will create an FCM Registration Token and log it. However nothing will change in the App UI.
- Copy and save the FCM Registration Token as it will be used in next steps.
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:
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.
- 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
- First, we need to set up a Firebase Service Account that allows firebase-admin SDK to authorize calls to FCM APIs.
- Go to the Firebase Console, click on the gear icon next to Project Overview in the left navigation bar, and select Project settings.
- In the settings page, select Service accounts and click Create service account.
- Now click on Generate new private key button and an automatic download of your key file will begin.
- Rename the key file to
service-account.json
and copy it in themessaging/fcm-topics-codelab/starter/StockNewsServer/src/main/resources
folder. - Both
FcmSender.java
andFcmSubscriptionManager.java
load theservice-account.json
file from classpath using the following code.
- At this point, the server code is ready. Run Build -> Build Project from the top menu bar.
Sending a Test Message
- In
FcmSender.java
locate thesendMessageToFcmRegistrationToken
function and insert the FCM registration token you copied from Run the starter app section into theregistrationToken
field. - In the
main
function, uncomment just thesendMessageToFcmRegistrationToken
function and click run to execute the code.- Observe how the FCM Registration Token is set into the
Token
field of themessage
object. - Furthermore, notice how we have used the
send
API ofFirebaseMessaging
interface.
- Observe how the FCM Registration Token is set into the
- This should send a message to the app instance that you have set up in the previous step.
- When the app instance is in foreground, you should see the message content logged.
- And when the App instance is in background, you would observe the message appear in the notifications tray.
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 theRecyclerViewViewHolder
class.
- 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
andunsubscribeFromStockCategory
methods respectively. - The
setData
method gets called by the RecyclerView Adapter'sonBindViewHolder
to bind the ViewHolder with appropriate Stock Category.
Implement topic subscription
- In the
subscribeToStockCategory
method, you will implement the call tosubscribeToTopic
API ofFirebaseMessaging
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
- 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
- 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
- In the server code, jump into
FcmSender.java
and locate the method namedsendMessageToFcmTopic
.
- 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
.
- It is a string of the form:
- In the next lines create a new
message
object (similar to the one defined in thesendMessageToFcmRegistrationToken
function).- The difference will be instead of setting the
Token
field of themessage
object, you will set theTopic
field.
- The difference will be instead of setting the
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();
- Now add the call to
FirebaseMessaging
instance to send the message (identical to the send call made in thesendMessageToFcmRegistrationToken
function).
FirebaseMessaging.getInstance().send(message);
- Finally, update the
main
function and enable the call to onlysendMessageToFcmTopic
function.
Send message and validate receipt
- Before sending the topic message, first ensure that your app instance is subscribed to the topic you want to send to.
- This can be done with a flip of the corresponding toggle. For example:
- You can now send your topic message by executing the
main
function ofFcmSender.java
. - Like before you should be able to observe the message receipt on the app instance.
- App instance in foreground
- App instance in background
- 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
- Back in the server code, jump into
FcmSender.java
and locate the method namedsendMessageToFcmTopicCondition
.
- 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
. - In the next lines, create a new
message
object (similar to the one defined in thesendMessageToFcmTopic
function).- The difference will be instead of setting the
Topic
field of the object, you will set theCondition
field.
- The difference will be instead of setting the
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();
- Now add the call to
FirebaseMessaging
instance to send the message (identical to the send call made in thesendMessageToFcmTopic
function).
FirebaseMessaging.getInstance().send(message);
- Finally, update the
main
function and enable the call to onlysendMessageToFcmTopicCondition
function.
Send the message and validate receipt
- 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.
- You can now send your topic message by executing the
main
function ofFcmSender.java
. - Like before, you should be able to observe the message receipt on the app instance.
- App instance in foreground
- App instance in background
- 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.
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
- In the server code, jump into
FcmSubscriptionManager.java
class. Locate the method namedsubscribeFcmRegistrationTokensToTopic
. You will implement the call tosubscribeToTopic
API here.
- Let's subscribe the app instance to the Energy topic. To do that, firstly provide data for the following two fields:
registrationTokens
: a comma separated list of strings representing the FCM Registration Tokens that you would like to create topic subscriptions for.topicName
: the topic name for the Energy topic, i.e./topics/Energy
.
- In next few lines implement the call, along these lines:
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic( registrationTokens, topicName);
- You can inspect the
TopicManagementResponse
for some high level result stats. Such as printing the number of successfully created topic subscriptions usinggetSuccessCount
.
System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
- Finally, in the
main
function enable calls to only thesubscribeFcmRegistrationTokensToTopic
function.
Create subscription and send topic message
- At this point you are ready to create the topic subscription and send a message to it.
- Execute the
main
function ofFcmSubscriptionManager.java
class. This will create a topic subscription. - Now, set up the code to send the message. Similar to before,
- In the
FcmSender.java
, locatesendMessageToFcmTopic
function. - Set the
topicName
to the Energy topic, i.e.,/topics/Energy
. - Create a
Message
object and target it to the topic usingsetTopic
. - Finally, update the
main
method to only enable thesendMessageToFcmTopic
function.
- In the
- Execute the
main
function ofFcmSender.java
. This will send the message to your app instance and you can observe it in your app as follows.- App instance in foreground
- App instance in background
Implement server side unsubscription of FCM Registration Tokens to FCM topic
- For server side topic unsubscriptions, use this
unsubscribeFromTopic
API. You will add the relevant code tounsubscribeFcmRegistrationTokensFromTopic
function ofFcmSubscriptionManager.java
class.
- 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.
What's next?
Now that you have completed your codelab, consider trying out topics for other platforms using the following guides: