O serviço Firebase Notificações se comporta de maneira diferente dependendo do estado em primeiro/segundo plano
do app de destino. Se você quer que apps em primeiro plano recebam
mensagens de notificação ou de dados, escreva o código para processar
a callback onMessageReceived
.
Veja uma explicação sobre a diferença entre as mensagens de notificação e de dados
em Tipos de mensagem.
Como processar mensagens
Para receber mensagens, use um serviço que amplie o
FirebaseMessagingService
.
Seu serviço precisa substituir as callbacks onMessageReceived
e onDeletedMessages
. Ele deve processar qualquer mensagem em até 20 segundos após o recebimento (10 segundos no Android
Marshmallow). O período pode ser mais curto, dependendo dos atrasos do SO incorridos antes de chamar
onMessageReceived
. Depois disso, vários comportamentos do SO, como os
limites de execução em segundo plano
do Android O, podem interferir na capacidade de concluir seu trabalho. Para mais informações, consulte nossa visão geral sobre
prioridade de mensagens.
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 da intent. |
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 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.
O Android usa a cor padrão personalizada para:
- todas as mensagens de notificação enviadas pelo Editor do Notificações;
- todas as mensagens de notificação que não definem explicitamente a cor no payload de 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 substituir o método FirebaseMessagingService.onMessageReceived
,
é possível realizar ações com base no objeto
RemoteMessage
recebido e acessar os dados da mensagem:
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}") // 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. }
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,
talvez você receba uma callback para FirebaseMessagingService.onDeletedMessages()
.
Quando isso acontece,
a instância do app precisa executar uma sincronização completa com o servidor do app. Se você não enviou uma mensagem ao app no
dispositivo nas últimas quatro semanas, o FCM não vai chamar 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.
Receber mensagens do FCM no modo de inicialização direta
Os desenvolvedores que quiserem enviar mensagens do FCM para apps antes mesmo do dispositivo ser desbloqueado poderão permitir que um app para Android receba mensagens quando o dispositivo estiver no modo de inicialização direta. Por exemplo, talvez você queira que os usuários do seu app recebam notificações de alarme mesmo em um dispositivo bloqueado.
Ao criar esse caso de uso, observe as práticas recomendadas e restrições gerais para o modo de inicialização direta. É especialmente importante considerar a visibilidade das mensagens enviadas na inicialização direta. Qualquer usuário com acesso ao dispositivo poderá ver essas mensagens sem digitar as credenciais do usuário.
Pré-requisitos
- O dispositivo precisa estar configurado para o modo de inicialização direta.
- O dispositivo precisa ter uma versão recente do Google Play Services instalada (19.0.54 ou superior).
- O app precisa usar o SDK do FCM (
com.google.firebase:firebase-messaging
) para receber mensagens do FCM.
Ativar o gerenciamento de mensagens no modo de inicialização direta no seu app
No arquivo Gradle no nível do app, adicione uma dependência à biblioteca de suporte da inicialização direta do FCM:
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
Adicione o atributo
android:directBootAware="true"
ao manifesto do app para fazerFirebaseMessagingService
funcionar na inicialização direta:<service android:name=".java.MyFirebaseMessagingService" android:exported="false" android:directBootAware="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
É importante garantir que FirebaseMessagingService
possa ser executado no modo de inicialização direta. Verifique
os seguintes requisitos:
- O serviço não deve acessar o armazenamento protegido por credenciais durante a execução no modo de inicialização direta.
- O serviço não deve tentar usar componentes, como
Activities
,BroadcastReceivers
ou outrosServices
que não estão marcados para funcionar no modo de inicialização direta. - Todas as bibliotecas que o serviço usar também não poderão acessar o armazenamento protegido por credenciais nem chamar componentes non-directBootAware durante a execução no modo de inicialização direta. Isso significa que todas as bibliotecas que o app usa e que são chamadas usando o serviço precisam estar marcadas para funcionar na inicialização direta ou o app deve verificar se ele está em execução no modo de inicialização direta para não chamar as bibliotecas se esse for o caso. Por exemplo, os SDKs do Firebase funcionam com a inicialização direta (eles podem ser incluídos em um app sem causar falhas nesse modo), mas muitas APIs do Firebase não são compatíveis com a inicialização direta.
- Se o app está usando um
Application
personalizado, oApplication
também precisa estar marcado para funcionar na inicialização direta (sem acesso ao armazenamento protegido por credenciais no modo de inicialização direta).
Para ver como enviar mensagens para dispositivos no modo de inicialização direta, consulte este link.