Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Enviar mensajes a varios dispositivos

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Firebase Cloud Messaging ofrece dos formas de enviar un mensaje a varios dispositivos:

Este tutorial se enfoca en enviar mensajes de temas desde su servidor de aplicaciones usando Admin SDK o REST API para FCM, y recibirlos y manejarlos en una aplicación de Android. Cubriremos el manejo de mensajes para aplicaciones en segundo plano y en primer plano. Se cubren todos los pasos para lograr esto, desde la configuración hasta la verificación.

Configurar el SDK

Esta sección puede cubrir los pasos que ya completó si configuró una aplicación de cliente de Android para FCM o siguió los pasos para enviar su primer mensaje .

Antes de que empieces

  • Instale o actualice Android Studio a su última versión.

  • Asegúrate de que tu proyecto cumpla con estos requisitos:

    • Objetivos API nivel 19 (KitKat) o superior
    • Utiliza Android 4.4 o superior
    • Utiliza Jetpack (AndroidX) , que incluye el cumplimiento de estos requisitos de versión:
      • com.android.tools.build:gradle v3.2.1 o posterior
      • compileSdkVersion 28 o posterior
  • Configure un dispositivo físico o use un emulador para ejecutar su aplicación.
    Tenga en cuenta que los SDK de Firebase que dependen de los servicios de Google Play requieren que el dispositivo o el emulador tengan instalados los servicios de Google Play.

  • Inicie sesión en Firebase con su cuenta de Google.

Si aún no tiene un proyecto de Android y solo desea probar un producto de Firebase, puede descargar uno de nuestros ejemplos de inicio rápido .

Crear un proyecto de Firebase

Antes de poder agregar Firebase a su aplicación de Android, debe crear un proyecto de Firebase para conectarse a su aplicación de Android. Visite Comprender los proyectos de Firebase para obtener más información sobre los proyectos de Firebase.

Registra tu aplicación con Firebase

Para usar Firebase en su aplicación de Android, debe registrar su aplicación con su proyecto de Firebase. Registrar su aplicación a menudo se denomina "agregar" su aplicación a su proyecto.

  1. Ve a la consola de Firebase .

  2. En el centro de la página de descripción general del proyecto, haga clic en el ícono de Android ( ) o Agregar aplicación para iniciar el flujo de trabajo de configuración.

  3. Ingrese el nombre del paquete de su aplicación en el campo de nombre del paquete de Android .

  4. (Opcional) Ingrese otra información de la aplicación: apodo de la aplicación y certificado de firma de depuración SHA-1 .

  5. Haga clic en Registrar aplicación .

Agregar un archivo de configuración de Firebase

  1. Descargue y luego agregue el archivo de configuración de Firebase Android ( google-services.json ) a su aplicación:

    1. Haga clic en Descargar google-services.json para obtener su archivo de configuración de Firebase Android.

    2. Mueva su archivo de configuración al directorio raíz del módulo (nivel de aplicación) de su aplicación.

  2. Para que los valores en su archivo de configuración google-services.json sean accesibles para los SDK de Firebase, necesita el complemento Gradle de servicios de Google ( google-services ).

    1. En su archivo Gradle de nivel raíz (nivel de proyecto) ( <project>/build.gradle ), agregue el complemento de servicios de Google como una dependencia de buildscript:

      buildscript {
      
          repositories {
            // Make sure that you have the following two repositories
            google()  // Google's Maven repository
            mavenCentral()  // Maven Central repository
          }
      
          dependencies {
            ...
      
            // Add the dependency for the Google services Gradle plugin
            classpath 'com.google.gms:google-services:4.3.14'
          }
      }
      
      allprojects {
        ...
      
        repositories {
          // Make sure that you have the following two repositories
          google()  // Google's Maven repository
          mavenCentral()  // Maven Central repository
        }
      }
      
    2. En el archivo Gradle de tu módulo (nivel de aplicación) (generalmente <project>/<app-module>/build.gradle ), agrega el complemento de servicios de Google:

      plugins {
          id 'com.android.application'
      
          // Add the Google services Gradle plugin
          id 'com.google.gms.google-services'
          ...
      }
      

Agregue los SDK de Firebase a su aplicación

  1. En el archivo Gradle de tu módulo (nivel de aplicación) (generalmente <project>/<app-module>/build.gradle ), agrega la dependencia para la biblioteca de Android Firebase Cloud Messaging. Recomendamos usar Firebase Android BoM para controlar el control de versiones de la biblioteca.

    Para una experiencia óptima con Firebase Cloud Messaging, recomendamos habilitar Google Analytics en su proyecto de Firebase y agregar Firebase SDK para Google Analytics a su aplicación.

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:31.1.0')
    
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging'
        implementation 'com.google.firebase:firebase-analytics'
    }
    

    Al usar Firebase Android BoM , su aplicación siempre usará versiones compatibles de las bibliotecas de Firebase Android.

    (Alternativa) Agregar dependencias de la biblioteca de Firebase sin usar el BoM

    Si elige no usar Firebase BoM, debe especificar cada versión de la biblioteca de Firebase en su línea de dependencia.

    Tenga en cuenta que si usa varias bibliotecas de Firebase en su aplicación, le recomendamos enfáticamente que use la lista de materiales para administrar las versiones de la biblioteca, lo que garantiza que todas las versiones sean compatibles.

    dependencies {
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging:23.1.0'
        implementation 'com.google.firebase:firebase-analytics:21.2.0'
    }
    

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:31.1.0')
    
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging-ktx'
        implementation 'com.google.firebase:firebase-analytics-ktx'
    }
    

    Al usar Firebase Android BoM , su aplicación siempre usará versiones compatibles de las bibliotecas de Firebase Android.

    (Alternativa) Agregar dependencias de la biblioteca de Firebase sin usar el BoM

    Si elige no usar Firebase BoM, debe especificar cada versión de la biblioteca de Firebase en su línea de dependencia.

    Tenga en cuenta que si usa varias bibliotecas de Firebase en su aplicación, le recomendamos enfáticamente que use la lista de materiales para administrar las versiones de la biblioteca, lo que garantiza que todas las versiones sean compatibles.

    dependencies {
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging-ktx:23.1.0'
        implementation 'com.google.firebase:firebase-analytics-ktx:21.2.0'
    }
    

  2. Sincroniza tu proyecto Android con archivos Gradle.

Suscribir la aplicación cliente a un tema

Las aplicaciones cliente pueden suscribirse a cualquier tema existente o pueden crear un tema nuevo. Cuando una aplicación de cliente se suscribe a un nuevo nombre de tema (uno que aún no existe para su proyecto de Firebase), se crea un nuevo tema con ese nombre en FCM y cualquier cliente puede suscribirse posteriormente.

Para suscribirse a un tema, la aplicación cliente llama a Firebase Cloud Messaging subscribeToTopic() con el nombre del tema de FCM. Este método devuelve una Task , que puede ser utilizada por un oyente de finalización para determinar si la suscripción se realizó correctamente:

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

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

Para cancelar la suscripción, la aplicación cliente llama a Firebase Cloud Messaging unsubscribeFromTopic() con el nombre del tema.

Recibir y manejar mensajes temáticos

FCM entrega mensajes temáticos de la misma manera que otros mensajes posteriores.

Para recibir mensajes, use un servicio que amplíe FirebaseMessagingService . Su servicio debe anular las devoluciones de llamada onMessageReceived y onDeletedMessages . Debería manejar cualquier mensaje dentro de los 20 segundos posteriores a la recepción (10 segundos en Android Marshmallow). La ventana de tiempo puede ser más corta dependiendo de las demoras del sistema operativo que se produzcan antes de llamar onMessageReceived . Después de ese tiempo, varios comportamientos del sistema operativo, como los límites de ejecución en segundo plano de Android O, pueden interferir con su capacidad para completar su trabajo. Para obtener más información, consulte nuestra descripción general sobre la prioridad de los mensajes .

onMessageReceived se proporciona para la mayoría de los tipos de mensajes, con las siguientes excepciones:

  • Mensajes de notificación entregados cuando su aplicación está en segundo plano . En este caso, la notificación se envía a la bandeja del sistema del dispositivo. Un toque de usuario en una notificación abre el iniciador de aplicaciones de forma predeterminada.

  • Mensajes con notificación y carga útil de datos, cuando se reciben en segundo plano . En este caso, la notificación se entrega a la bandeja del sistema del dispositivo y la carga de datos se entrega en los extras de la intención de su actividad de iniciador.

En resumen:

estado de la aplicación Notificación Datos Ambas cosas
Primer plano onMessageReceived onMessageReceived onMessageReceived
Fondo Bandeja del sistema onMessageReceived Notificación: bandeja del sistema
Datos: en extras de la intención.
Para obtener más información sobre los tipos de mensajes, consulte Notificaciones y mensajes de datos .

Editar el manifiesto de la aplicación

Para usar FirebaseMessagingService , debe agregar lo siguiente en el manifiesto de su aplicación:

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

Además, se recomienda establecer valores predeterminados para personalizar la apariencia de las notificaciones. Puede especificar un icono predeterminado personalizado y un color predeterminado personalizado que se aplican siempre que no se establezcan valores equivalentes en la carga útil de la notificación.

Agregue estas líneas dentro de la etiqueta de la application para establecer el icono predeterminado personalizado y el color personalizado:

<!-- 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 muestra el icono predeterminado personalizado para

  • Todos los mensajes de notificación enviados desde el redactor de notificaciones .
  • Cualquier mensaje de notificación que no establece explícitamente el icono en la carga de notificación.

Android usa el color predeterminado personalizado para

  • Todos los mensajes de notificación enviados desde el redactor de notificaciones .
  • Cualquier mensaje de notificación que no establezca explícitamente el color en la carga útil de la notificación.

Si no se establece ningún icono predeterminado personalizado y no se establece ningún icono en la carga útil de la notificación, Android muestra el icono de la aplicación representado en blanco.

Anular onMessageReceived

Al anular el método FirebaseMessagingService.onMessageReceived , puede realizar acciones basadas en el objeto RemoteMessage recibido y obtener los datos del mensaje:

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

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}")

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

Anular onDeletedMessages

En algunas situaciones, es posible que FCM no entregue un mensaje. Esto ocurre cuando hay demasiados mensajes (>100) pendientes para su aplicación en un dispositivo en particular en el momento en que se conecta o si el dispositivo no se ha conectado a FCM en más de un mes. En estos casos, puede recibir una devolución de llamada a FirebaseMessagingService.onDeletedMessages() Cuando la instancia de la aplicación recibe esta devolución de llamada, debe realizar una sincronización completa con su servidor de aplicaciones. Si no ha enviado un mensaje a la aplicación en ese dispositivo en las últimas 4 semanas, FCM no llamará a onDeletedMessages() .

Manejar mensajes de notificación en una aplicación en segundo plano

Cuando su aplicación está en segundo plano, Android envía mensajes de notificación a la bandeja del sistema. Un toque de usuario en la notificación abre el iniciador de aplicaciones de forma predeterminada.

Esto incluye mensajes que contienen carga útil de notificación y datos (y todos los mensajes enviados desde la consola de notificaciones). En estos casos, la notificación se entrega a la bandeja del sistema del dispositivo y la carga de datos se entrega en los extras de la intención de su actividad de iniciador.

Para obtener información sobre la entrega de mensajes a su aplicación, consulte el panel de informes de FCM , que registra la cantidad de mensajes enviados y abiertos en dispositivos Apple y Android, junto con datos de "impresiones" (notificaciones vistas por los usuarios) para aplicaciones de Android.

Aplicaciones restringidas en segundo plano (Android P o posterior)

Es posible que FCM no entregue mensajes a las aplicaciones que el usuario puso en segundo plano (por ejemplo, a través de: Configuración -> Aplicaciones y notificaciones -> [nombre de la aplicación] -> Batería). Una vez que su aplicación se elimine de la restricción de fondo, los mensajes nuevos a la aplicación se enviarán como antes. Para evitar la pérdida de mensajes y otros impactos de restricción en segundo plano, asegúrese de evitar los malos comportamientos enumerados por el esfuerzo de Android vitals . Estos comportamientos podrían hacer que el dispositivo Android recomiende al usuario que su aplicación esté restringida en segundo plano. Su aplicación puede verificar si está restringida en segundo plano usando: isBackgroundRestricted() .

Crear solicitudes de envío

Una vez que haya creado un tema, ya sea mediante la suscripción de instancias de la aplicación cliente al tema en el lado del cliente o a través de la API del servidor , puede enviar mensajes al tema. Si es la primera vez que crea solicitudes de envío para FCM, consulte la guía de su entorno de servidor y FCM para obtener información importante sobre antecedentes y configuración.

En su lógica de envío en el backend, especifique el nombre del tema deseado como se muestra:

Nodo.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);

Pitón

# 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)

Vamos

// 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);

DESCANSAR

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"
      }
   }
}

Comando 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

Para enviar un mensaje a una combinación de temas, especifique una condición , que es una expresión booleana que especifica los temas de destino. Por ejemplo, la siguiente condición enviará mensajes a los dispositivos que están suscritos a TopicA y TopicB o TopicC :

"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

FCM primero evalúa cualquier condición entre paréntesis y luego evalúa la expresión de izquierda a derecha. En la expresión anterior, un usuario suscrito a un solo tema no recibe el mensaje. Asimismo, un usuario que no se suscriba a TopicA no recibe el mensaje. Estas combinaciones sí lo reciben:

  • TopicA y TopicB
  • TopicA y TopicC

Puede incluir hasta cinco temas en su expresión condicional.

Para enviar a una condición:

Nodo.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);

Pitón

# 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)

Vamos

// 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);

DESCANSAR

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",
    }
  }
}

Comando 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

Próximos pasos