Ir para o console

Enviar mensagens a vários dispositivos

O Firebase Cloud Messaging oferece duas maneiras de direcionar uma mensagem a vários dispositivos:

Este tutorial concentra-se no envio de mensagens de tópicos do seu servidor do app, usando os protocolos HTTP ou XMPP para o FCM, e no recebimento e processamento dessas mensagens em um app da Web. Abordaremos o processamento de mensagens para apps em primeiro e segundo plano.

Configurar o SDK

Se você configurou um app cliente em JavaScript no FCM ou completou as etapas para receber mensagens, talvez as etapas abordadas nesta seção já tenham sido concluídas.

Adicionar o Firebase a seu projeto do JavaScript

Adicione o Firebase a seu projeto do JavaScript, caso ainda não tenha feito isso.

Configurar o navegador para receber mensagens

É necessário adicionar um manifesto do app da Web que especifique o gcm_sender_id, um valor codificado indicando que o FCM está autorizado a enviar mensagens para esse aplicativo. Caso seu aplicativo já tenha um arquivo de configuração manifest.json, certifique-se de adicionar o código do remetente do navegador exatamente como mostrado (não altere o valor):

{
  "gcm_sender_id": "103953800507"
}

Recuperar um objeto de mensagem

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

Solicitar permissão para receber notificações

O método messaging.requestPermission() exibe uma caixa de diálogo de consentimento para que os usuários permitam que seu app receba notificações no navegador. Se a permissão for negada, as solicitações de token de registro do FCM resultarão em erro.

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

Acessar o token de registro

Esta seção descreve como recuperar o token de registro de uma instância de app e como monitorar os eventos de atualização dele. Como o token pode passar por um rodízio após a primeira inicialização, recomendamos que você recupere o token de registro mais atualizado.

O token de registro pode mudar quando:

  • o app da Web exclui o token de registro;
  • o usuário exclui dados do navegador. Nesse caso, chame getToken para recuperar o novo token.

Recuperar o token de registro atual

Quando você precisar recuperar o token atual, chame getToken: Esse método retorna nulo quando nenhuma permissão foi concedida. Caso contrário, ele retorna um token ou rejeita a promessa por causa de um erro.

O serviço de mensagens requer um arquivo firebase-messaging-sw.js. A menos que você já tenha um arquivo firebase-messaging-sw.js, crie um arquivo vazio com esse nome e coloque-o na raiz do seu domínio antes de recuperar um token. Você pode adicionar conteúdo significativo ao arquivo posteriormente no processo de configuração do cliente.

Para recuperar o token atual:

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

Monitorar a atualização de token

O retorno de chamada de onTokenRefresh é acionado sempre que um novo token é gerado. Portanto, chamar getToken nesse contexto garantirá o acesso a um token de registro atual e disponível.

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

Depois de receber o token, envie-o para o servidor do app e armazene-o usando seu método preferido. Você pode usar a Instance ID Server API para receber informações sobre inscrições.

Inscrever o app cliente em um tópico

Com um token de registro e um nome de tópico, é possível adicionar o token ao tópico usando a Google Instance ID server API. Chame a Instance ID API nesse ponto de extremidade fornecendo o token de registro da instância do app e o nome do tópico:

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

Por exemplo, para inscrever uma instância de app em um tópico nomeado como "movies", envie a seguinte solicitação POST do seu servidor para o ponto de extremidade adicionando a chave de API do servidor ao cabeçalho de autorização desta forma:

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

Nunca envie esse tipo de solicitação do cliente devido à sensibilidade da chave do servidor.

Quando uma solicitação é bem-sucedida, ela retorna HTTP 200 OK. Para mais informações sobre respostas de erro e envio de solicitações em lote, consulte Criar mapas de relacionamento para instâncias de app (em inglês).

É possível transferir uma lista de tokens de registro para o método de assinatura do SDK Admin do Firebase para fazer a assinatura dos dispositivos correspondentes em um tópico:

Node.js

// These registration tokens come from the client FCM SDKs.
var registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Subscribe the devices corresponding to the registration tokens to the
// topic.
admin.messaging().subscribeToTopic(registrationTokens, topic)
  .then(function(response) {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch(function(error) {
    console.log('Error subscribing to topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Subscribe the devices corresponding to the registration tokens to the
// topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Subscribe the devices corresponding to the registration tokens to the
# topic.
response = messaging.subscribe_to_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were subscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Subscribe the devices corresponding to the registration tokens to the
// topic.
response, err := client.SubscribeToTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were subscribed successfully")

A API Admin FCM também permite que você cancele a assinatura de dispositivos em um tópico por meio da transferência de tokens de registro para o método apropriado.

Node.js

// These registration tokens come from the client FCM SDKs.
var registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
admin.messaging().unsubscribeFromTopic(registrationTokens, topic)
  .then(function(response) {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch(function(error) {
    console.log('Error unsubscribing from topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Unubscribe the devices corresponding to the registration tokens from the
# topic.
response = messaging.unsubscribe_from_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were unsubscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
response, err := client.UnsubscribeFromTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were unsubscribed successfully")

Os métodos subscribeToTopic() e unsubscribeFromTopic() resultam em um objeto que contém a resposta do FCM. O tipo de retorno tem o mesmo formato, independentemente do número de tokens de registro especificados na solicitação.

Em caso de erro (falhas de autenticação, token ou tópico inválido etc.), esses métodos resultam em um erro. Para ver uma lista completa de códigos do erro, incluindo descrições e etapas de solução de problemas, consulte Erros da API Admin FCM.

Receber e processar messages de tópico

O comportamento das mensagens varia, dependendo se a página está em primeiro plano (em foco), em segundo plano (escondida atrás de outras guias) ou completamente fechada. Em todos os casos, a página precisa processar o callback onMessage, mas, em casos em segundo plano, talvez você precise manipular setBackgroundMessageHandler ou configurar a notificação de exibição para permitir que o usuário coloque seu app da Web em primeiro plano.

Estado do app Notificação Dados Ambos
Primeiro plano onMessage onMessage onMessage
Segundo plano (service worker) Notificação exibida pelo SDK setBackgroundMessageHandler Notificação exibida pelo SDK

Tratar mensagens quando seu app da Web está em primeiro plano

Para receber o evento de onMessage, seu app precisa definir o service worker de mensagens do Firebase em firebase-messaging-sw.js. Se preferir, especifique um service worker existente com 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();

Quando seu app estiver em primeiro plano (o usuário está visualizando a página da Web), você pode receber payloads de dados e de notificações diretamente na 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);
  // ...
});

Tratar mensagens quando seu app da Web está em segundo plano

Todas as mensagens recebidas enquanto o app está em segundo plano acionam uma notificação de exibição no navegador. Especifique as opções dessa notificação, como um título ou uma ação de clique, na solicitação de envio a partir do servidor de app ou usando a lógica do service worker no cliente.

Como configurar opções na solicitação de envio

Para mensagens de notificação enviadas a partir do servidor do app, a API FCM JavaScript é compatível com a chave fcm_options.link. Em geral, isso é definido para uma página no seu app da Web:

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

Se o valor do link apontar para uma página que já está aberta em uma guia do navegador, um clique na notificação trará essa guia para o primeiro plano. Se a página ainda não estiver aberta, um clique na notificação abrirá a página em uma nova guia.

Como as mensagens de dados não aceitam fcm_options.link, recomenda-se adicionar um payload de notificação a todas as mensagens de dados. Como alternativa, é possível tratar notificações usando o service worker.

Veja uma explicação sobre a diferença entre mensagens de notificação e de dados em Tipos de mensagens.

Configurar opções de notificação no service worker

Para as mensagens de notificação e de dados, é possível definir opções de notificação no service worker. Primeiro, inicialize seu app no 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 definir as opções, chame setBackgroundmensagemHandler em firebase-messaging-sw.js. Neste exemplo, definimos as opções de título, corpo, ícone e ação de clique.

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

Criar solicitações de envio

No servidor, enviar mensagens para um tópico do Firebase Cloud Messaging (FCM) é bem semelhante a enviar mensagens para um dispositivo individual ou um grupo de usuários. O app server define a chave to com um valor como /topics/yourTopic. Os desenvolvedores podem escolher um nome de tópico que corresponda à expressão regular: "/topics/[a-zA-Z0-9-_.~%]+".

Solicitação HTTP POST de tópico

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

Enviar com 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"

Resposta HTTP de tópico

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

Mensagem XMPP de tópico

Enviar para um único tópico:

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

Resposta XMPP de tópico

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

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