Este guia descreve como configurar o Firebase Cloud Messaging nos seus apps cliente para dispositivos móveis e Web para que você possa receber mensagens de forma confiável.
Para receber mensagens, use um serviço que amplie o
FirebaseMessagingService
.
Seu serviço precisa substituir as callbacks onMessageReceived
e onDeletedMessages
.
O onMessageReceived
está disponível para a maioria dos tipos de mensagens, com as seguintes exceções:
Mensagens de notificação entregues quando seu app estiver em segundo plano. Nesse caso, a notificação é entregue à bandeja do sistema do dispositivo. Quando um usuário toca na notificação, a tela de início do app é aberta por padrão.
Mensagens com payload de notificação e dados, quando recebidas em segundo plano. Nesse caso, a notificação é entregue à bandeja do sistema do dispositivo, e o payload de dados é entregue nos extras da intent da atividade da sua tela de início.
Em resumo:
Estado do app | Notificação | Dados | Ambos |
---|---|---|---|
Primeiro plano | onMessageReceived |
onMessageReceived |
onMessageReceived |
Segundo plano | Bandeja do sistema | onMessageReceived |
Notificação: bandeja do sistema Dados: nos extras do intent. |
Para mais informações sobre os tipos de mensagens, consulte Notificações e mensagens de dados.
O callback onMessageReceived
recebe tempos limite que permitem postar uma notificação, mas os timers não foram projetados para permitir que o app acesse a rede ou faça
trabalho adicional. Assim, se o app fizer algo mais complicado, você precisará fazer um trabalho
adicional para garantir que ele possa concluir a tarefa.
Se você acha que o app pode levar quase 10 segundos para processar uma mensagem, programe um job do WorkManager ou siga as orientações do WakeLock abaixo. Em alguns casos, a janela
de tempo em que a mensagem pode ser processada pode ser menor do que 10 segundos dependendo dos atrasos incorridos antes de chamar onMessageReceived
, incluindo atrasos do SO, o tempo de inicialização do aplicativo, a linha de execução principal bloqueada por outras operações ou onMessageReceived
chamadas estão demorando muito. Depois que o timer expirar, o app poderá estar sujeito à eliminação de processos ou a
limites de execução em segundo plano. As latências de transações de rede e inicialização de apps podem ser significativas. Portanto, em caso de dúvida,
planeje o processamento de mensagens para que ele seja executado por muito tempo se houver dependências assíncronas, como acesso
à rede ou requisitos de carregamento de dados intensivos.
Editar o manifesto do app
Para usar FirebaseMessagingService
, adicione o seguinte ao
manifesto do seu app:
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Além disso, recomendamos que você defina valores padrão para personalizar a aparência das notificações. É possível especificar uma cor e um ícone padrão personalizados que serão aplicados sempre que valores equivalentes não estiverem definidos no payload da notificação.
Adicione estas linhas na tag
application
para definir a cor e o ícone padrão personalizados:
<!-- 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" />
O Android exibe e usa o ícone personalizado padrão para:
- todas as mensagens de notificação enviadas pelo Editor do Notificações;
- todas as mensagens de notificação que não definem explicitamente o ícone no payload da notificação.
Se não houver um ícone personalizado padrão ou nenhum ícone estiver definido no payload de notificação, o Android exibirá o ícone do aplicativo renderizado na cor branca.
Substituir onMessageReceived
Ao modificar o método FirebaseMessagingService.onMessageReceived
, é possível
realizar ações com base no objeto
RemoteMessage
recebido e acessar os dados da mensagem:
Kotlin
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}") // Check if data needs to be processed by long running job if (needsToBeScheduled()) { // 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. }
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. }
Manter o dispositivo ativado ao processar mensagens do FCM
Se o app precisar manter o dispositivo ativo enquanto processa uma mensagem do FCM, ele precisará
manter um WakeLock durante esse período ou criar um job do WorkManager. Os WakeLocks funcionam bem
para atividades de processamento curtas que podem exceder os tempos limite padrão do onMessageReceived
. Para fluxos de trabalho estendidos, como o envio de vários RPCs seriais aos servidores, é mais adequado usar um
trabalho do WorkManager do que um WakeLock. Nesta seção, vamos focar em como usar
WakeLocks. Um
WakeLock impede que o dispositivo entre em suspensão enquanto o app está em execução, o que pode resultar em maior uso da bateria. Portanto, o uso de WakeLocks deve ser reservado para casos em que o app não pode ser pausado ao processar a mensagem, como:
- Notificações urgentes para o usuário.
- Interações com algo fora do dispositivo que não deve ser interrompido, como transferências de rede ou comunicações com outro dispositivo, como um smartwatch pareado.
Primeiro, verifique se o app solicita a permissão WakeLock. O SDK do FCM inclui essa permissão por padrão, então normalmente não é preciso adicionar nada.
<uses-permission android:name="android.permission.WAKE_LOCK" />
Em seguida, seu app precisará adquirir um WakeLock no início do callback FirebaseMessagingService.onMessageReceived()
e liberá-lo no final.
FirebaseMessagingService
personalizado do app:
@Override
public void onMessageReceived(final RemoteMessage message) {
// If this is a message that is time sensitive or shouldn't be interrupted
WakeLock wakeLock = getSystemService(PowerManager.class).newWakeLock(PARTIAL_WAKE_LOCK, "myApp:messageReceived");
try {
wakeLock.acquire(TIMEOUT_MS);
// handle message
...
finally {
wakeLock.release();
}
}
Substituir onDeletedMessages
Em algumas situações, é possível que o FCM não entregue uma mensagem. Isso ocorre quando há muitas
mensagens pendentes (mais de 100) no
app em um dispositivo específico no momento em que ele é conectado ou se o dispositivo não for conectado ao
FCM por mais de um mês. Nesses casos, você pode receber um callback para
FirebaseMessagingService.onDeletedMessages()
. Ao receber esse retorno de chamada, a instância do app precisa executar uma sincronização completa com seu servidor do app. Se você não enviou uma mensagem ao app no
dispositivo nas últimas quatro semanas, o FCM não vai chamar o onDeletedMessages()
.
Processar mensagens de notificação em um app em segundo plano
Quando seu app está em segundo plano, o Android direciona as notificações para a bandeja do sistema. Quando um usuário toca nelas, a tela de início do aplicativo é aberta por padrão.
Isso inclui mensagens que contêm payload de notificação e dados, assim como todas aquelas enviadas pelo console do Notificações. Nesses casos, a notificação é entregue à bandeja do sistema do dispositivo e o payload de dados é entregue nos extras da intent da atividade da tela de início.
Confira as informações sobre a entrega de mensagens ao seu app
no
painel de relatórios do FCM, que registra o
número de mensagens enviadas e abertas em dispositivos Apple e Android, além de
dados de "impressões" (notificações vistas pelos usuários) para apps Android.