Recibir mensajes en una aplicación de Android

Las notificaciones de Firebase se comportan de manera diferente según el estado de primer plano o de fondo de la aplicación receptora. Si desea que las aplicaciones en primer plano reciban mensajes de notificación o mensajes de datos, deberá escribir código para manejar la devolución de llamada onMessageReceived . Para obtener una explicación de la diferencia entre mensajes de notificación y de datos, consulte Tipos de mensajes .

Manejo de mensajes

Para recibir mensajes, utilice un servicio que extienda FirebaseMessagingService . Su servicio debe anular las devoluciones de llamada onMessageReceived y onDeletedMessages .

La ventana de tiempo para manejar un mensaje puede ser inferior a 20 segundos dependiendo de los retrasos ocurridos antes de llamar onMessageReceived , incluidos retrasos del sistema operativo, el tiempo de inicio de la aplicación, el bloqueo del hilo principal por otras operaciones o llamadas anteriores onMessageReceived que tardan demasiado. Después de ese tiempo, varios comportamientos del sistema operativo, como la eliminación de procesos de Android o los límites de ejecución en segundo plano de Android O, pueden interferir con su capacidad para completar su trabajo.

onMessageReceived se proporciona para la mayoría de los tipos de mensajes, con las siguientes excepciones:

  • Mensajes de notificación entregados cuando su aplicación está en segundo plano . En este caso, la notificación se envía a la bandeja del sistema del dispositivo. Un usuario que toca una notificación abre el iniciador de aplicaciones de forma predeterminada.

  • Mensajes con carga útil de notificación y datos, cuando se reciben en segundo plano . En este caso, la notificación se envía a la bandeja del sistema del dispositivo y la carga útil de datos se entrega en los extras de la intención de la Actividad del iniciador.

En resumen:

Estado de la aplicación Notificación Datos Ambos
Primer plano onMessageReceived onMessageReceived onMessageReceived
Fondo Bandeja del sistema onMessageReceived Notificación: bandeja del sistema
Datos: en extras de la intención.
Para obtener más información sobre los tipos de mensajes, consulte Notificaciones y mensajes de datos .

Editar el manifiesto de la aplicación

Para usar FirebaseMessagingService , debes agregar lo siguiente en el manifiesto de tu aplicación:

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

Además, se recomienda establecer valores predeterminados para personalizar la apariencia de las notificaciones. Puede especificar un icono predeterminado personalizado y un color predeterminado personalizado que se aplican siempre que no se establezcan valores equivalentes en la carga útil de notificación.

Agregue estas líneas dentro de la etiqueta de la application para configurar el ícono predeterminado personalizado y el color personalizado:

<!-- 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" />

Android muestra el icono predeterminado personalizado para

  • Todos los mensajes de notificación enviados desde el redactor de notificaciones .
  • Cualquier mensaje de notificación que no establezca explícitamente el icono en la carga útil de notificación.

Android usa el color predeterminado personalizado para

  • Todos los mensajes de notificación enviados desde el redactor de notificaciones .
  • Cualquier mensaje de notificación que no establezca explícitamente el color en la carga útil de notificación.

Si no se establece ningún ícono predeterminado personalizado y no se establece ningún ícono en la carga útil de notificación, Android muestra el ícono de la aplicación en blanco.

Anular onMessageReceived

Al anular el método FirebaseMessagingService.onMessageReceived , puedes realizar acciones basadas en el objeto RemoteMessage recibido y obtener los datos del mensaje:

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

onDeletedMessages eliminados

En algunas situaciones, es posible que FCM no entregue un mensaje. Esto ocurre cuando hay demasiados mensajes (>100) pendientes para su aplicación en un dispositivo en particular en el momento en que se conecta o si el dispositivo no se ha conectado a FCM en más de un mes. En estos casos, puede recibir una devolución de llamada a FirebaseMessagingService.onDeletedMessages() . Cuando la instancia de la aplicación recibe esta devolución de llamada, debe realizar una sincronización completa con su servidor de aplicaciones. Si no ha enviado un mensaje a la aplicación en ese dispositivo en las últimas 4 semanas, FCM no llamará a onDeletedMessages() .

Manejar mensajes de notificación en una aplicación en segundo plano

Cuando su aplicación está en segundo plano, Android dirige los mensajes de notificación a la bandeja del sistema. Un toque del usuario en la notificación abre el iniciador de aplicaciones de forma predeterminada.

Esto incluye mensajes que contienen notificaciones y carga útil de datos (y todos los mensajes enviados desde la consola de notificaciones). En estos casos, la notificación se envía a la bandeja del sistema del dispositivo y la carga útil de datos se entrega en los extras de la intención de la Actividad del iniciador.

Para obtener información sobre la entrega de mensajes a su aplicación, consulte el panel de informes de FCM , que registra la cantidad de mensajes enviados y abiertos en dispositivos Apple y Android, junto con datos de "impresiones" (notificaciones vistas por los usuarios) para aplicaciones de Android.

Reciba mensajes FCM en modo de inicio directo

Los desarrolladores que quieran enviar mensajes FCM a aplicaciones incluso antes de que se desbloquee el dispositivo pueden habilitar una aplicación de Android para recibir mensajes cuando el dispositivo esté en modo de inicio directo. Por ejemplo, es posible que desee que los usuarios de su aplicación reciban notificaciones de alarma incluso en un dispositivo bloqueado.

Al desarrollar este caso de uso, observe las mejores prácticas y restricciones generales para el modo de inicio directo . Es particularmente importante considerar la visibilidad de los mensajes habilitados para el arranque directo; cualquier usuario con acceso al dispositivo puede ver estos mensajes sin ingresar las credenciales de usuario.

Requisitos previos

  • El dispositivo debe estar configurado para el modo de inicio directo.
  • El dispositivo debe tener instalada una versión reciente de los servicios de Google Play (19.0.54 o posterior).
  • La aplicación debe utilizar el SDK de FCM ( com.google.firebase:firebase-messaging ) para recibir mensajes de FCM.

Habilite el manejo de mensajes en modo de inicio directo en su aplicación

  1. En el archivo Gradle a nivel de aplicación, agregue una dependencia en la biblioteca de soporte de arranque directo de FCM:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. Haz que el arranque directo de FirebaseMessagingService de la aplicación reconozca el inicio directo agregando el atributo android:directBootAware="true" en el manifiesto de la aplicación:

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

Es importante asegurarse de que este FirebaseMessagingService pueda ejecutarse en modo de inicio directo. Consulta los siguientes requisitos:

  • El servicio no debe acceder al almacenamiento protegido con credenciales mientras se ejecuta en modo de inicio directo.
  • El servicio no debe intentar utilizar componentes, como Activities , BroadcastReceivers u otros Services que no estén marcados como compatibles con el arranque directo mientras se ejecuta en modo de arranque directo.
  • Las bibliotecas que utiliza el servicio tampoco deben acceder al almacenamiento protegido con credenciales ni llamar a componentes que no sean directBootAware mientras se ejecuta en modo de inicio directo. Esto significa que cualquier biblioteca que utilice la aplicación y que se llame desde el servicio deberá tener en cuenta el inicio directo o la aplicación deberá verificar si se está ejecutando en modo de inicio directo y no llamarlas en ese modo. Por ejemplo, los SDK de Firebase funcionan con inicio directo (se pueden incluir en una aplicación sin bloquearla en el modo de inicio directo), pero muchas API de Firebase no admiten que se les llame en el modo de inicio directo.
  • Si la aplicación utiliza una Application personalizada, la Application también deberá ser compatible con el inicio directo (sin acceso al almacenamiento protegido con credenciales en el modo de inicio directo).

Para obtener orientación sobre cómo enviar mensajes a dispositivos en modo de inicio directo, consulte Enviar mensajes habilitados para inicio directo .