Receba mensagens em um aplicativo Android

As notificações do Firebase se comportam de maneira diferente dependendo do estado de primeiro/segundo plano do aplicativo receptor. Se quiser que aplicativos em primeiro plano recebam mensagens de notificação ou mensagens de dados, você precisará escrever um código para lidar com o retorno de chamada onMessageReceived . Para obter uma explicação sobre a diferença entre mensagens de notificação e de dados, consulte Tipos de mensagens .

Tratamento de mensagens

Para receber mensagens, use um serviço que estenda FirebaseMessagingService . Seu serviço deve substituir os retornos de chamada onMessageReceived e onDeletedMessages .

A janela de tempo para lidar com uma mensagem pode ser inferior a 20 segundos, dependendo dos atrasos ocorridos antes da chamada onMessageReceived , incluindo atrasos do sistema operacional, tempo de inicialização do aplicativo, thread principal sendo bloqueado por outras operações ou chamadas onMessageReceived anteriores demorando muito. Após esse período, vários comportamentos do sistema operacional, como a eliminação de processos do Android ou os limites de execução em segundo plano do Android O, podem interferir na sua capacidade de concluir o trabalho.

onMessageReceived é fornecido para a maioria dos tipos de mensagens, com as seguintes exceções:

  • Mensagens de notificação entregues quando seu aplicativo está em segundo plano . Nesse caso, a notificação é entregue na bandeja do sistema do dispositivo. Um toque do usuário em uma notificação abre o inicializador de aplicativos por padrão.

  • Mensagens com notificação e carga de dados, quando recebidas em segundo plano . Nesse caso, a notificação é entregue na bandeja do sistema do dispositivo, e a carga útil de dados é entregue nos extras da intenção da sua atividade do iniciador.

Resumindo:

Estado do aplicativo Notificação Dados Ambos
Primeiro plano onMessageReceived onMessageReceived onMessageReceived
Fundo Bandeja do sistema onMessageReceived Notificação: bandeja do sistema
Dados: em extras da intenção.
Para obter mais informações sobre tipos de mensagens, consulte Notificações e mensagens de dados .

Edite o manifesto do aplicativo

Para usar FirebaseMessagingService , você precisa adicionar o seguinte ao manifesto do seu aplicativo:

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

Além disso, é recomendável definir valores padrão para personalizar a aparência das notificações. Você pode especificar um ícone padrão personalizado e uma cor padrão personalizada que serão aplicadas sempre que valores equivalentes não forem definidos na carga de notificação.

Adicione estas linhas dentro da tag application para definir o ícone padrão personalizado e a cor personalizada:

<!-- 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 padrão personalizado para

  • Todas as mensagens de notificação enviadas pelo compositor de notificações .
  • Qualquer mensagem de notificação que não defina explicitamente o ícone na carga de notificação.

O Android usa a cor padrão personalizada para

  • Todas as mensagens de notificação enviadas pelo compositor de notificações .
  • Qualquer mensagem de notificação que não defina explicitamente a cor na carga de notificação.

Se nenhum ícone padrão personalizado for definido e nenhum ícone for definido na carga de notificação, o Android exibirá o ícone do aplicativo renderizado em branco.

Substituir onMessageReceived

Ao substituir o método FirebaseMessagingService.onMessageReceived , você pode executar ações com base no objeto RemoteMessage recebido e obter 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, o FCM pode não entregar uma mensagem. Isso ocorre quando há muitas mensagens (>100) pendentes para seu aplicativo em um dispositivo específico no momento da conexão ou se o dispositivo não estiver conectado ao FCM há mais de um mês. Nesses casos, você poderá receber um retorno de chamada para FirebaseMessagingService.onDeletedMessages() . Quando a instância do aplicativo receber esse retorno de chamada, ela deverá realizar uma sincronização completa com o servidor do seu aplicativo. Se você não enviou uma mensagem para o aplicativo nesse dispositivo nas últimas quatro semanas, o FCM não chamará onDeletedMessages() .

Lidar com mensagens de notificação em um aplicativo em segundo plano

Quando seu aplicativo está em segundo plano, o Android direciona as mensagens de notificação para a bandeja do sistema. Um toque do usuário na notificação abre o inicializador de aplicativos por padrão.

Isso inclui mensagens que contêm notificação e carga útil de dados (e todas as mensagens enviadas do console do Notificações). Nesses casos, a notificação é entregue na bandeja do sistema do dispositivo, e a carga de dados é entregue nos extras da intenção da sua atividade do iniciador.

Para obter informações sobre a entrega de mensagens no seu aplicativo, consulte o painel de relatórios do FCM , que registra o número de mensagens enviadas e abertas em dispositivos Apple e Android, juntamente com dados de "impressões" (notificações vistas pelos usuários) para aplicativos Android.

Receba mensagens FCM no modo de inicialização direta

Os desenvolvedores que desejam enviar mensagens FCM para aplicativos antes mesmo de o dispositivo ser desbloqueado podem permitir que um aplicativo Android receba mensagens quando o dispositivo estiver no modo de inicialização direta. Por exemplo, você pode querer que os usuários do seu aplicativo recebam notificações de alarme mesmo em um dispositivo bloqueado.

Ao desenvolver este caso de uso, observe as práticas recomendadas e restrições gerais para o modo de inicialização direta . É particularmente importante considerar a visibilidade das mensagens habilitadas para inicialização direta; qualquer usuário com acesso ao dispositivo pode visualizar essas mensagens sem inserir credenciais de usuário.

Pré-requisitos

  • O dispositivo deve ser configurado para modo de inicialização direta.
  • O dispositivo deve ter uma versão recente do Google Play Services instalada (19.0.54 ou posterior).
  • O aplicativo deve usar o SDK do FCM ( com.google.firebase:firebase-messaging ) para receber mensagens do FCM.

Habilite o tratamento de mensagens no modo de inicialização direta em seu aplicativo

  1. No arquivo Gradle no nível do aplicativo, adicione uma dependência na biblioteca de suporte de inicialização direta do FCM:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. Torne a inicialização direta do FirebaseMessagingService do aplicativo ciente adicionando o atributo android:directBootAware="true" no manifesto do aplicativo:

    <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 este 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 outros Services que não estejam marcados como com reconhecimento de inicialização direta durante a execução no modo de inicialização direta.
  • Quaisquer bibliotecas usadas pelo serviço também não devem acessar o armazenamento protegido por credenciais nem chamar componentes não-directBootAware durante a execução no modo de inicialização direta. Isso significa que quaisquer bibliotecas que o aplicativo usa e que são chamadas a partir do serviço precisarão ter reconhecimento de inicialização direta ou o aplicativo precisará verificar se está sendo executado no modo de inicialização direta e não chamá-las nesse modo. Por exemplo, os SDKs do Firebase funcionam com inicialização direta (eles podem ser incluídos em um aplicativo sem travar no modo de inicialização direta), mas muitas APIs do Firebase não suportam chamadas no modo de inicialização direta.
  • Se o aplicativo estiver usando um Application personalizado, o Application também precisará ter reconhecimento de inicialização direta (sem acesso ao armazenamento protegido por credenciais no modo de inicialização direta).

Para obter orientação sobre como enviar mensagens para dispositivos no modo de inicialização direta, consulte Enviar mensagens habilitadas para inicialização direta .