Envía mensajes a varios dispositivos

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

Este instructivo se enfoca en el envío de mensajes por tema desde el servidor de apps mediante los protocolos HTTP o XMPP para FCM, así como en la recepción y la administración de ellos en la app web. Abordaremos la administración de mensajes en apps en segundo plano y en primer plano.

Configura el SDK

Es posible que ya hayas completado algunos pasos de esta sección si configuraste una app cliente de JavaScript para FCM o configuraste la recepción de mensajes.

Agrega Firebase al proyecto de JavaScript

Si no lo hiciste antes, agrega Firebase al proyecto de JavaScript.

Configura el navegador para recibir mensajes

Deberás agregar un manifiesto de app web que especifique el gcm_sender_id, un valor hard-coded para indicar que FCM está autorizado a enviar mensajes a esta app. Si la app ya tiene un archivo de configuración manifest.json, asegúrate de agregar el ID de remitente del navegador exactamente como se muestra (no cambies el valor):

{
  "gcm_sender_id": "103953800507"
}

Recupera un objeto de mensajería

// Retrieve Firebase Messaging object.
const messaging = firebase.messaging();

Solicita permiso para recibir notificaciones

El método messaging.requestPermission() muestra un diálogo de consentimiento para informarle al usuario que debe otorgarle permiso a la app para recibir notificaciones en el navegador. Si se niega el permiso, las solicitudes de token de registro de FCM generarán un error.

messaging.requestPermission().then(function() {
  console.log('Notification permission granted.');
  // TODO(developer): Retrieve an Instance ID token for use with FCM.
  // ...
}).catch(function(err) {
  console.log('Unable to get permission to notify.', err);
});

Accede al token de registro

En esta sección, se describe cómo recuperar el token de registro de una instancia de app y cómo supervisar los eventos de actualización de tokens. Dado que el token podría rotarse después del inicio, es importante que controles la actualización de tokens y siempre recuperes el token de registro más reciente.

El token de registro puede cambiar en las siguientes situaciones:

  • La aplicación web borra el token de registro.
  • El usuario borra los datos del navegador. En este caso, debes llamar a getToken para recuperar el nuevo token.

Recupera el token de registro actual

Cuando necesites recuperar el token actual, llama a getToken. Este método muestra un resultado nulo cuando no se cuenta con el permiso necesario. De lo contrario, muestra un token o rechaza la promesa debido a un error.

El servicio de mensajería requiere un archivo firebase-messaging-sw.js. A menos que ya tengas un archivo firebase-messaging-sw.js, crea un archivo vacío con ese nombre y guárdalo en la raíz de tu dominio antes de recuperar un token. Puedes agregar contenido significativo al archivo en etapas posteriores del proceso de configuración del cliente.

Para recuperar el token actual, sigue este ejemplo:

// Get Instance ID token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
messaging.getToken().then(function(currentToken) {
  if (currentToken) {
    sendTokenToServer(currentToken);
    updateUIForPushEnabled(currentToken);
  } else {
    // Show permission request.
    console.log('No Instance ID token available. Request permission to generate one.');
    // Show permission UI.
    updateUIForPushPermissionRequired();
    setTokenSentToServer(false);
  }
}).catch(function(err) {
  console.log('An error occurred while retrieving token. ', err);
  showToken('Error retrieving Instance ID token. ', err);
  setTokenSentToServer(false);
});

Supervisa la actualización de tokens

La devolución de llamada onTokenRefresh se activa cada vez que se genera un nuevo token, por lo que invocar getToken en este contexto garantiza que se accede a un token de registro vigente y disponible.

// Callback fired if Instance ID token is updated.
messaging.onTokenRefresh(function() {
  messaging.getToken().then(function(refreshedToken) {
    console.log('Token refreshed.');
    // Indicate that the new Instance ID token has not yet been sent to the
    // app server.
    setTokenSentToServer(false);
    // Send Instance ID token to app server.
    sendTokenToServer(refreshedToken);
    // ...
  }).catch(function(err) {
    console.log('Unable to retrieve refreshed token ', err);
    showToken('Unable to retrieve refreshed token ', err);
  });
});

Una vez que obtienes el token, envíalo al servidor de apps y almacénalo con el método que prefieras. Puedes usar la API de servidor Instance ID para obtener información sobre las suscripciones.

Suscribe la app cliente a un tema

Para cualquier par de token de registro y nombre de tema, puedes agregar el token al tema mediante la API de servidor Instance ID de Google. Llama a la API de Instance ID en este extremo y proporciona el token de registro de la instancia de la app y el nombre del tema:

 https://iid.googleapis.com/iid/v1/<REGISTRATION_TOKEN>/rel/topics/<TOPIC_NAME>

Para suscribir una instancia de la app a un tema denominado “películas”, por ejemplo, envía la siguiente solicitud POST desde tu servidor hacia el extremo y agrega la clave de API del servidor en el encabezado de la autorización como se muestra en este ejemplo:

https://iid.googleapis.com/iid/v1/nKctODamlM4:CKrh_PC8kIb7O...clJONHoA/rel/topics/movies
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

Para proteger la confidencialidad de la clave del servidor, nunca envíes este tipo de solicitud desde el cliente.

Si la solicitud se ejecuta correctamente, se mostrará la respuesta HTTP 200 OK. Para obtener más información sobre las respuestas de error y la forma de enviar solicitudes por lotes, consulta cómo crear asignaciones de relaciones para instancias de apps.

Recibe y administra mensajes por temas

El comportamiento de los mensajes varía si la página se encuentra en primer plano (tiene el “foco”) o en segundo plano, escondida detrás de otras pestañas o completamente cerrada. En todos los casos, la página debe controlar la devolución de llamada de onMessage, pero en los casos en segundo plano, es posible que también necesites controlar setBackgroundMessageHandler o configurar la notificación en pantalla para permitir que el usuario lleve tu app web al primer plano.

Estado de la app Notificación Datos Ambos
En primer plano onMessage onMessage onMessage
En segundo plano (service worker) Notificación que muestra el SDK setBackgroundMessageHandler Notificación que muestra el SDK

Maneja mensajes cuando la aplicación web está en primer plano

Para recibir el evento onMessage, tu app debe definir el service worker de mensajería de Firebase en firebase-messaging-sw.js. Otra opción es especificar un service worker existente con useServiceWorker.

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': 'YOUR-SENDER-ID'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

Cuando la app se encuentra en primer plano (el usuario está viendo tu página web actualmente), puedes recibir datos y cargas de notificaciones directamente en la página.

// Handle incoming messages. Called when:
// - a message is received while the app has focus
// - the user clicks on an app notification created by a service worker
//   `messaging.setBackgroundMessageHandler` handler.
messaging.onMessage(function(payload) {
  console.log('Message received. ', payload);
  // ...
});

Maneja mensajes cuando la aplicación web está en segundo plano

Todos los mensajes que se reciben mientras la app está en segundo plano desencadenan una notificación en pantalla en el navegador. Puedes especificar opciones para esta notificación, como un título o una acción cuando se hace clic, ya sea en la solicitud de envío del servidor de apps o mediante el uso de la lógica del service worker en el cliente.

Configurar opciones de notificación en la solicitud de envío

En el caso de los mensajes de notificación que se envían desde el servidor de apps, la API de JavaScript de FCM es compatible con la clave click_action. Por lo general, esta se dirige a una página de la aplicación web, como en este ejemplo:

https://fcm.googleapis.com//v1/projects/<YOUR-PROJECT-ID>/messages:send
Content-Type: application/json
Authorization: bearer <YOUR-ACCESS-TOKEN>

{
  "message": {
    "topic": "matchday"
    "notification": {
      "title": "Background Message Title",
      "body": "Background message body"
    },
    "webpush": {
      "fcm_options": {
        "link": "https://dummypage.com"
      }
    }
  }
}

Si la acción de hacer clic apunta a una página que ya está abierta en una pestaña del navegador, la pestaña se pondrá en primer plano cuando se haga clic en la notificación. Si la página no está abierta, se abrirá en una pestaña nueva cuando se haga clic en la notificación.

Debido a que los mensajes de datos no son compatibles con click_action, se recomienda que agregues una carga útil de notificación a todos los mensajes de datos. También puedes administrar notificaciones con el service worker.

Para ver una explicación de la diferencia entre los mensajes de notificación y los de datos, consulta los tipos de mensaje.

Cómo configurar las opciones de notificación en el service worker

Tanto para los mensajes de notificación como para los de datos, puedes configurar las opciones de notificación en el service worker. Primero, inicia tu app en el service worker:

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': 'YOUR-SENDER-ID'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

Para establecer opciones, llama a setBackgroundMessageHandler en firebase-messaging-sw.js. En este ejemplo, se configuran las opciones de título, cuerpo, ícono y acción de clic.

messaging.setBackgroundMessageHandler(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  var notificationTitle = 'Background Message Title';
  var notificationOptions = {
    body: 'Background Message body.',
    icon: '/firebase-logo.png'
  };

  return self.registration.showNotification(notificationTitle,
    notificationOptions);
});

Crea solicitudes de envío

Desde el servidor, enviar mensajes a un tema de Firebase Cloud Messaging es muy similar a enviar mensajes a un dispositivo individual o a un grupo de usuarios. El servidor de apps establece la clave to con el valor /topics/yourTopic. Los desarrolladores pueden elegir cualquier nombre de tema que coincida con la expresión regular "/topics/[a-zA-Z0-9-_.~%]+".

Solicitud HTTP POST del tema

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

Envía con 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!",
  },
  "topic" : "foo-bar"
}' "https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1"

Respuesta HTTP del tema

{
    "name": "projects/myproject-b5ae1/messages/5735743068807585451"
}

Mensaje XMPP del tema

Envía a un tema individual:

<message id="">
  <gcm xmlns="google:mobile:data">
{
  "to" : /topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

Respuesta XMPP del tema

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

Enviar comentarios sobre…

¿Necesitas ayuda? Visita nuestra página de asistencia.