Send Messages to Multiple Devices

Firebase Cloud Messaging provides two ways to target a message to multiple devices:

  • Topic messaging, which allows you to send a message to multiple devices that have opted in to a particular topic.
  • Device group messaging, which allows you to send a message to multiple devices that belong to a group you define.

This tutorial focuses on sending topic messages from your app server using the HTTP or XMPP protocols for FCM, and receiving and handling them in an android app. We'll cover message handling for both backgrounded and foregrounded apps. All the steps to achieve this are covered, from setup to verification.

Set up the SDK

This section may cover steps you already completed if you have set up an Android client app for FCM or worked through the steps to Send your First Message.

Prerequisites

  • A device running Android 2.3 (Gingerbread) or newer, and Google Play services 9.6.1 or newer
  • The Google Repository from the Android SDK Manager
  • Android Studio 1.5 or higher

If you don't have an Android Studio project already, you can download one of our quickstart samples if you just want to try a Firebase feature. If you're using a quickstart, remember to get the application ID from the build.gradle file in your project's module folder (typically app/), as you'll need this package name for the next step.

Add Firebase to your app

To add Firebase to your app you'll need a Firebase project and a Firebase configuration file for your app.

  1. Create a Firebase project in the Firebase console, if you don't already have one. If you already have an existing Google project associated with your mobile app, click Import Google Project. Otherwise, click Create New Project.
  2. Click Add Firebase to your Android app and follow the setup steps. If you're importing an existing Google project, this may happen automatically and you can just download the config file.
  3. When prompted, enter your app's package name. It's important to enter the package name your app is using; this can only be set when you add an app to your Firebase project.
  4. At the end, you'll download a google-services.json file. You can download this file again at any time.
  5. If you haven't done so already, copy this into your project's module folder, typically app/.

Add the SDK

If you would like to integrate the Firebase libraries into one of your own projects, you need to perform a few basic tasks to prepare your Android Studio project. You may have already done this as part of adding Firebase to your app.

First, add rules to your root-level build.gradle file, to include the google-services plugin:

buildscript {
    // ...
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:3.0.0'
    }
}

Then, in your module Gradle file (usually the app/build.gradle), add the apply plugin line at the bottom of the file to enable the Gradle plugin:

apply plugin: 'com.android.application'

android {
  // ...
}

dependencies {
  // ...
  compile 'com.google.firebase:firebase-core:9.6.1'
  compile 'com.google.firebase:firebase-messaging:9.6.1'
  // Getting a "Could not find" error? Make sure you have
  // the latest Google Repository in the Android SDK manager
}

// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'

You should also add the dependencies for the Firebase SDKs you want to use. We recommend starting with com.google.firebase:firebase-core, which provides Firebase Analytics functionality. See the list of available libraries.

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.

To subscribe to a topic, the client app calls Firebase Cloud Messaging subscribeToTopic() with the FCM topic name:

FirebaseMessaging.getInstance().subscribeToTopic("news");

To unsubscribe, the client app calls Firebase Cloud Messaging unsubscribeFromTopic() with the topic name.

Receive and handle topic messages

FCM delivers topic messages in the same way as other downstream messages.

To receive messages, use a service that extends FirebaseMessagingService. Your service should override the onMessageReceived callback, which is provided for most message types, with the following exceptions:

  • Notifications delivered when your app is in the background. In this case, the notification is delivered to the device’s system tray. A user tap on a notification opens the app launcher by default.

  • Messages with both notification and data payload, both background and foreground. In this case, the notification is delivered to the device’s system tray, and the data payload is delivered in the extras of the intent of your launcher Activity.

In summary:

App state Notification Data Both
Foreground onMessageReceived onMessageReceived onMessageReceived
Background System tray onMessageReceived Notification: system tray
Data: in extras of the intent.
For more information about message types, see Notifications and data messages.

Edit the app manifest

To use FirebaseMessagingService, you need to add the following in your app manifest:

<service
    android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

Override onMessageReceived

By overriding the method FirebaseMessagingService.onMessageReceived, you can perform actions based on the received RemoteMessage object and get the message data:

@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());
    }

    // 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.
}

Handle notification messages in a backgrounded app

When your app is in the background, Android directs notification messages to the system tray. A user tap on the notification opens the app launcher by default.

This includes messages that contain both notification and data payload (and all messages sent from the Notifications console). In these cases, the notification is delivered to the device's system tray, and the data payload is delivered in the extras of the intent of your launcher Activity.

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

Send feedback about...

Need help? Visit our support page.