Cómo manejar la notificación cuando la aplicación está en segundo plano en Firebase

429

Aquí está mi manifiesto

    <service android:name=".fcm.PshycoFirebaseMessagingServices">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <service android:name=".fcm.PshycoFirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

Cuando la aplicación está en segundo plano y llega la notificación, llega la notificación predeterminada y no ejecuta mi código de onMessageReceived.

Aquí está mi onMessageReceivedcódigo. Esto invoca si mi aplicación se ejecuta en primer plano, no cuando la aplicación está en segundo plano. ¿Cómo ejecutar este código cuando la aplicación también está en segundo plano?

// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // If the application is in the foreground handle both data and notification messages here.
    // 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.
    data = remoteMessage.getData();
    String title = remoteMessage.getNotification().getTitle();
    String message = remoteMessage.getNotification().getBody();
    String imageUrl = (String) data.get("image");
    String action = (String) data.get("action");
    Log.i(TAG, "onMessageReceived: title : "+title);
    Log.i(TAG, "onMessageReceived: message : "+message);
    Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
    Log.i(TAG, "onMessageReceived: action : "+action);

    if (imageUrl == null) {
        sendNotification(title,message,action);
    } else {
        new BigPictureNotification(this,title,message,imageUrl,action);
    }
}
// [END receive_message]
Parth Patel
fuente
1
Está escrito en la muestra de reemplazo de onMessageReceived () , dice la segunda línea de comentarios Not getting messages here? See why this may be: goo.gl/39bRNJ . La solución, como las respuestas a continuación, se puede encontrar en la documentación en Mensajes con notificaciones y cargas de datos
fllo
En pocas palabras, para reactivar su aplicación eliminada, siempre debe enviar una notificación con un objeto de datos para llamar a su controlador de clase de servicio de notificaciones FirebaseMessagingService.onMessageReceived () en su aplicación. También intente enviarlo no desde la consola de Firebase, sino publicarlo desde otro lugar (p. Ej., Servicio postal de prueba en línea).
Zon
1
esta solución funcionó para mí stackoverflow.com/a/44150822/6632278 espero ayuda. Buena suerte
Tony Barajas
que ".fcm" PshycoFirebaseMessagingServices está en su manifiesto? Recibo un error de clase no encontrada ... y no encontré en ninguna parte cuál es esta primera parte del parámetro.
Éder Rocha Bezerra

Respuestas:

661

1. ¿Por qué está pasando esto?

Hay dos tipos de mensajes en FCM (Firebase Cloud Messaging):

  1. Mostrar mensajes : estos mensajes activan la onMessageReceived()devolución de llamada solo cuando su aplicación está en primer plano
  2. Mensajes de datos : estos mensajes activan la onMessageReceived()devolución de llamada incluso si su aplicación está en primer plano / en segundo plano / eliminada

NOTA: el equipo de Firebase aún no ha desarrollado una interfaz de usuario para enviar data-messagesa sus dispositivos. ¡Debe usar su servidor para enviar este tipo!



2. ¿Cómo?

Para lograr esto, debe realizar una POSTsolicitud a la siguiente URL:

POST https://fcm.googleapis.com/fcm/send

Encabezados

  • Clave: Content-Type , Valor: application/json
  • Clave: Authorization , Valor: key=<your-server-key>

Cuerpo usando temas

{
    "to": "/topics/my_topic",
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     }
}

O si quieres enviarlo a dispositivos específicos

{
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     },
    "registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}


NOTA: asegúrese de no agregar clave JSONnotification
NOTA: para obtener la clave del servidor, puede encontrarla en la consola de Firebase:Your project -> settings -> Project settings -> Cloud messaging -> Server Key

3. ¿Cómo manejar el mensaje de notificación push?

Así es como maneja el mensaje recibido:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();
     String myCustomKey = data.get("my_custom_key");

     // Manage data
}
Antonio
fuente
44
Puede enviar claves de "datos" y "notificación" en la misma notificación siguiendo estos pasos stackoverflow.com/a/42279260/2734021 :)
Daniel S.
15
Firebase team have not developed a UI to send data-messages to your devices, yet.¿Ha cambiado esto en el último año?
Hankrecords
2
@Antonio En oreo cuando se apaga la aplicación, no se llama a onMessageReceived. Solo tengo carga útil solo con datos. alguna actualización tienes?
Samir Mangroliya
63
¡Cuando la aplicación está en segundo plano onMessageReceivedno se llama y es un problema grave en FCM! También por favor actualice su respuesta.
Muhammad Babar
2
Bueno, para mí, parece que esto sucede en ciertos dispositivos Android. Pasé horas pensando que era un problema real, pero luego resultó ser nada. Así que mi consejo es probarlo en diferentes dispositivos. Incluso lo probé en una máquina virtual y recibí la notificación incluso cuando se cerró la aplicación. Solo digo esto para ahorrarle tiempo a alguien.
Tarek-Dev
158

Para hacer que la biblioteca de Firebase llame a su onMessageReceived () en los siguientes casos

  1. Aplicación en primer plano
  2. Aplicación en segundo plano
  3. La aplicación ha sido eliminada

no debe poner la 'notificación' de la clave JSON en su solicitud para la API de firebase, sino que debe usar 'datos', consulte a continuación.

El siguiente mensaje no llamará a su onMessageReceived () cuando su aplicación esté en segundo plano o sea eliminada, y no puede personalizar su notificación.

{
   "to": "/topics/journal",
   "notification": {
   "title" : "title",
   "text": "data!",
   "icon": "ic_notification"
    }
}

pero en cambio usar esto funcionará

{
  "to": "/topics/dev_journal",
   "data": {
       "text":"text",
       "title":"",
       "line1":"Journal",
       "line2":"刊物"
   }
} 

Básicamente, el mensaje se envía en el argumento RemoteMessage junto con su objeto de datos como Map, luego puede administrar la notificación en onMessageReceived como en el fragmento aquí

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();

     //you can get your text message here.
     String text= data.get("text");


     NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
        // optional, this is to make beautiful icon
             .setLargeIcon(BitmapFactory.decodeResource(
                                    getResources(), R.mipmap.ic_launcher))  
        .setSmallIcon(smallIcon)  //mandatory
      .......
    /*You can read more on notification here:
    https://developer.android.com/training/notify-user/build-notification.html
    https://www.youtube.com/watch?v=-iog_fmm6mE
    */
}
Teerakiat Chitawattanarat
fuente
1
¿Es posible lograr esto desde la consola Firebase?
Koder
@koder, desafortunadamente la consola de Firebase no es compatible con esto, debe usar la herramienta para enviar la solicitud de mensaje posterior a firebase como curl o postman (complemento de Chrome), la API de mensajería de firebase, consulte el documento aquí - firebase.google.com/docs / cloud-messaging / http-server-ref
Teerakiat Chitawattanarat
1
esto es lo que estaba buscando por más de un día ... Muchas gracias, funcionó perfectamente. y sería mejor si explicara cómo se pueden manejar los pares clave vale en los datos en onMessageReceived () para iniciar una actividad con esos valores.
Boopathi T
25
Su método funciona bien cuando la aplicación está en segundo plano, sin embargo, cuando se cierra la aplicación no recibo datos
Sanzhar
8
El mismo problema de Sanzhar. Si se mata la aplicación, no recibo ningún mensaje.
Giacomo M
104

Siento que todas las respuestas están incompletas, pero todas tienen algo que necesita para procesar una notificación que tiene datos cuando su aplicación está en segundo plano.

Siga estos pasos y podrá procesar sus notificaciones cuando su aplicación esté en segundo plano.

1.Agregue un filtro de intención como este:

<activity android:name=".MainActivity">
      <intent-filter>
           <action android:name=".MainActivity" />
           <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
</activity>

a una actividad que desea procesar los datos de notificación.

  1. Enviar notificaciones con el siguiente formato:

    { 
     "notification" : {
            "click_action" : ".MainActivity", 
            "body" : "new Symulti update !", 
            "title" : "new Symulti update !", 
            "icon" : "ic_notif_symulti" }, 
     "data": { ... },
     "to" : "c9Vaa3ReGdk:APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9" }

La clave aquí es agregar

"click_action" : ".MainActivity"

donde .MainActivity es la actividad con el filtro de intención que agregó en el paso 1.

  1. Obtenga información de "datos" de la notificación en onCreate de ".MainActivity":

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //get notification data info
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
           //bundle must contain all info sent in "data" field of the notification
        }
    }

Y eso debería ser todo lo que necesitas hacer. Espero que esto ayude a alguien :)

Daniel S.
fuente
55
Esta debería ser la respuesta correcta. Ninguno de los documentos dice nada acerca de requerir una acción de clic Y un filtro de intención para que la notificación aparezca en la bandeja. Ambos son obligatorios.
airowe
@airowe no son necesarios para que aparezca la notificación
AlwaysConfused
Tengo bloques de datos y notificaciones pero no puedo recibir datos en actividad.
Ashwani
3
Simplemente no entiendo cómo esta no es la respuesta aceptada. Sin click_action, simplemente no funcionará. Me salvó el día
Arun Shankar
44
Gracias por su apoyo @ArunShankar. La respuesta aceptada fue respondida 7 meses antes que la mía y es una buena respuesta. No puedo entender por qué nadie habla de click_action y es por eso que agregué mi respuesta. Estoy muy feliz de que sea muy útil para mucha gente y eso es lo que importa al final del día :)
Daniel S.
42

De acuerdo con la documentación de Firebase en el envío descendente utilizando Firebase , hay 2 tipos de carga útil:

  1. datos

    Este parámetro especifica los pares clave-valor personalizados de la carga útil del mensaje. La aplicación cliente es responsable de procesar los mensajes de datos. Los mensajes de datos solo tienen pares clave-valor personalizados.

  2. notificación

    Este parámetro especifica los pares de clave-valor predefinidos y visibles para el usuario de la carga útil de notificación. FCM muestra automáticamente el mensaje a los dispositivos del usuario final en nombre de la aplicación cliente. Los mensajes de notificación tienen un conjunto predefinido de claves visibles para el usuario.

Cuando está en primer plano, puede obtener los datos dentro de FCM usando onMessageReceived () , puede obtener sus datos de la carga útil de datos .

data = remoteMessage.getData();
String customData = (String) data.get("customData");

Cuando esté en segundo plano, FCM mostrará notificaciones en la bandeja del sistema en función de la información de la carga útil de notificaciones . El título, el mensaje y el icono que se usaron para la notificación en la bandeja del sistema se obtienen de la carga útil de notificaciones .

{
  "notification": {
        "title" : "title",
        "body"  : "body text",
        "icon"  : "ic_notification",
        "click_action" : "OPEN_ACTIVITY_1"
       }
}

Esta carga útil de notificación se utiliza cuando desea mostrar automáticamente notificaciones en la bandeja del sistema cuando su aplicación está en segundo plano. Para obtener datos de notificaciones cuando su aplicación está en segundo plano, debe agregar click_action dentro de la carga útil de notificaciones .

Si desea abrir su aplicación y realizar una acción específica [en segundo plano], configure click_action en la carga de notificación y asigne un filtro de intención en la Actividad que desea iniciar. Por ejemplo, establezca click_action en OPEN_ACTIVITY_1 para activar un filtro de intención como el siguiente:

<intent-filter>
  <action android:name="OPEN_ACTIVITY_1" />
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

Coloque ese filtro de intención en su manifiesto, dentro de una de sus etiquetas de actividad. Cuando haga clic en la notificación, abrirá la aplicación y pasará directamente a la actividad que defina en click_action, en este caso "OPEN_ACTIVTY_1". Y dentro de esa actividad puede obtener los datos de la siguiente manera:

Bundle b = getIntent().getExtras();
String someData = b.getString("someData");

Estoy usando FCM para mi aplicación de Android y uso la carga útil. Aquí está el ejemplo JSON que estoy usando:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification",
    "click_action" : "OPEN_ACTIVITY_1"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}
Hendy Evan
fuente
"Ponga ese filtro de intención en su manifiesto, dentro de la etiqueta de la aplicación". no puede poner filtro intencional dentro de la etiqueta de la aplicación.
Kyrylo Zapylaiev
sus dows JSON no muestran dónde va la clave click_action.
Josh
esta no es la respuesta correcta? ¿Qué es la acción de clic y dónde va? alguien debería votar o limpiar esto
rana
1
@ KyryloZapylaiev Simplemente corrijo y actualizo la respuesta: "Pon ese filtro de intención en tu manifiesto, dentro de una de tu etiqueta de actividad".
Dika
1
@ Josh actualizado y formateado. puedes revisarlo nuevamente
Dika
32

De acuerdo con los documentos

Manejar mensajes en una aplicación de fondo

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

Esto incluye mensajes que contienen notificaciones y carga de datos. En estos casos, la notificación se entrega a la bandeja del sistema del dispositivo, y la carga de datos se entrega en los extras de la intención de su Actividad de inicio.

Si desea abrir su aplicación y realizar una acción específica, configure click_action en la carga de notificación y asigne un filtro de intención en la Actividad que desea iniciar. Por ejemplo, establezca click_action en OPEN_ACTIVITY_1 para activar un filtro de intención como el siguiente:

 <intent-filter>   <action android:name="OPEN_ACTIVITY_1" />  
 <category android:name="android.intent.category.DEFAULT" />
 </intent-filter>

Editar:

Basado en este hilo :

No puedes configurar la carga útil de click_action con Firebase Console. Puede intentar probar con un comando curl o un servidor http personalizado

curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>" 
     --header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send  
     -d "{\"to\":\"/topics/news\",\"notification\": 
         {\"title\": \"Click Action Message\",\"text\": \"Sample message\",
            \"click_action\":\"OPEN_ACTIVITY_1\"}}"
Shubhank
fuente
1
tienes razón. He leído los documentos. pero estoy confundido donde poner esto en mi manifiesto? tengo que ejecutar el código en onMessageReceived en ese archivo java así que para eso ¿qué debo hacer señor?
Parth Patel
No puede hacer que la aplicación llame automáticamente a MessageReveiced cuando está en segundo plano. En su lugar, debe manejar la intención recibida y hacer que el controlador lo llame. O probablemente sea mejor implementar una clase / método separado que sea invocado tanto por onMessageReveiced como por su manejo de intenciones. Agregué un controlador a onNewIntent de la actividad principal y funciona bien para mí.
Diidu
demasiado tarde para responder a las preguntas de @Parath Patel, pero tal vez esto ayude a alguien más con los mismos problemas, eche un vistazo a mi respuesta aquí stackoverflow.com/a/42279260/2734021
Daniel S.
¿Dónde tenía que poner esta acción? para mi actividad o servicio de Firebasemessage?
Mahdi
** en la redirección de notificaciones múltiples no funciona? por ejemplo: si tengo tres notificaciones de fcm en segundo plano usando "click_action", la primera notificación se redirige con éxito y luego 2 notificaciones, la redirección de actividad no funciona
prasanthMurugan
24

Trabajando a partir de julio de 2019

Android compileSdkVersion 28, buildToolsVersion 28.0.3 y firebase-messaging: 19.0.1

Después de muchas horas de investigación a través de todas las otras preguntas y respuestas de StackOverflow, y probando innumerables soluciones obsoletas, esta solución logró mostrar notificaciones en estos 3 escenarios:

- La aplicación está en primer plano:
la notificación se recibe mediante el método onMessageReceived en mi clase MyFirebaseMessagingService

- La aplicación ha sido eliminada (no se está ejecutando en segundo plano): FCM envía automáticamente la notificación a la bandeja de notificaciones. Cuando el usuario toca la notificación, la aplicación se inicia llamando a la actividad que tiene android.intent.category.LAUNCHER en el manifiesto. Puede obtener la parte de datos de la notificación utilizando getIntent (). GetExtras () en el método onCreate ().

- La aplicación está en segundo plano: FCM envía automáticamente la notificación a la bandeja de notificaciones. Cuando el usuario toca la notificación, la aplicación se pone en primer plano al iniciar la actividad que tiene android.intent.category.LAUNCHER en el manifiesto. Como mi aplicación tiene launchMode = "singleTop" en esa actividad, no se llama al método onCreate () porque ya se ha creado una actividad de la misma clase, sino que se llama al método onNewIntent () de esa clase y obtiene la parte de datos de la notificación allí usando intent.getExtras ().

Pasos: 1- Si define la actividad principal de su aplicación de esta manera:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:screenOrientation="portrait"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name=".MainActivity" />
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

2- agrega estas líneas en el método onCreate () de tu MainActivity.class

Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras != null) {
    for (String key : extras.keySet()) {
        Object value = extras.get(key);
        Log.d(Application.APPTAG, "Extras received at onCreate:  Key: " + key + " Value: " + value);
    }
    String title = extras.getString("title");
    String message = extras.getString("body");
    if (message!=null && message.length()>0) {
        getIntent().removeExtra("body");
        showNotificationInADialog(title, message);
    }
}

y estos métodos a la misma clase MainActivity.class:

@Override
public void onNewIntent(Intent intent){
    //called when a new intent for this class is created.
    // The main case is when the app was in background, a notification arrives to the tray, and the user touches the notification

    super.onNewIntent(intent);

    Log.d(Application.APPTAG, "onNewIntent - starting");
    Bundle extras = intent.getExtras();
    if (extras != null) {
        for (String key : extras.keySet()) {
            Object value = extras.get(key);
            Log.d(Application.APPTAG, "Extras received at onNewIntent:  Key: " + key + " Value: " + value);
        }
        String title = extras.getString("title");
        String message = extras.getString("body");
        if (message!=null && message.length()>0) {
            getIntent().removeExtra("body");
            showNotificationInADialog(title, message);
        }
    }
}


private void showNotificationInADialog(String title, String message) {

    // show a dialog with the provided title and message
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

3- crea la clase MyFirebase así:

package com.yourcompany.app;

import android.content.Intent;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {


    public MyFirebaseMessagingService() {
        super();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);

        Intent dialogIntent = new Intent(this, NotificationActivity.class);
        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        dialogIntent.putExtra("msg", remoteMessage);
        startActivity(dialogIntent);

    }

}

4- crea una nueva clase NotificationActivity.class como esta:

package com.yourcompany.app;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;

import com.google.firebase.messaging.RemoteMessage;

public class NotificationActivity extends AppCompatActivity {

private Activity context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = this;
    Bundle extras = getIntent().getExtras();

    Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);

    if (extras == null) {
        context.finish();
        return;
    }

    RemoteMessage msg = (RemoteMessage) extras.get("msg");

    if (msg == null) {
        context.finish();
        return;
    }

    RemoteMessage.Notification notification = msg.getNotification();

    if (notification == null) {
        context.finish();
        return;
    }

    String dialogMessage;
    try {
        dialogMessage = notification.getBody();
    } catch (Exception e){
        context.finish();
        return;
    }
    String dialogTitle = notification.getTitle();
    if (dialogTitle == null || dialogTitle.length() == 0) {
        dialogTitle = "";
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, R.style.myDialog));
    builder.setTitle(dialogTitle);
    builder.setMessage(dialogMessage);
    builder.setPositiveButton(getResources().getString(R.string.accept), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();

}

}

5- Agrega estas líneas al Manifiesto de tu aplicación, dentro de tus etiquetas

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

    <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id"/>

    <activity android:name=".NotificationActivity"
        android:theme="@style/myDialog"> </activity>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/notification_icon"/>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/color_accent" />

6- agrega estas líneas en tu método Application.java onCreate (), o en el método MainActivity.class onCreate ():

      // notifications channel creation
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      // Create channel to show notifications.
      String channelId = getResources().getString("default_channel_id");
      String channelName = getResources().getString("General announcements");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(new NotificationChannel(channelId,
              channelName, NotificationManager.IMPORTANCE_LOW));
  }

Hecho.

Ahora, para que esto funcione bien en los 3 escenarios mencionados, debe enviar la notificación desde la consola web de Firebase de la siguiente manera:

En la sección Notificación: Título de notificación = Título para mostrar en el cuadro de diálogo de notificación (opcional) Texto de notificación = Mensaje para mostrar al usuario (obligatorio) Luego en la sección Destino: Aplicación = su aplicación de Android y en la sección Opciones adicionales: Canal de notificación de Android = default_channel_id Clave de datos personalizados: valor del título: (el mismo texto aquí que en el campo Título de la sección de notificaciones) clave: valor del cuerpo: (el mismo texto aquí que en el campo Mensaje de la sección de notificaciones) clave: click_action valor: .MainActivity Sound = Deshabilitado
Caduca = 4 semanas

Puede depurarlo en el emulador con API 28 con Google Play.

¡Feliz codificación!

Alvaro
fuente
2
Gracias por esta gran respuesta.
Alex Chengalan
@alvaro, si quiero abrir la URL cuando reciba la notificación, cómo puedo manejar esto
engmms
no funciona en un teléfono opp vivo cuando la aplicación está cerrada o muerta
Desarrollador de Android
No lo he probado en un teléfono Vivo, pero actualmente funciona en muchos otros teléfonos Android. Lea lentamente cada paso, verifique todos los detalles y luego active los puntos de interrupción de depuración en la primera línea de cada uno de los métodos que he mencionado aquí, conecte un teléfono real a su computadora de desarrollo con un cable y depure la aplicación mientras envía Un mensaje de FCM. Compruebe que está enviando los mensajes de FCM con todos los parámetros y el formato que mencioné. ¡Buena suerte!
alvaro
2
Esta es la respuesta más actualizada, ya que ahora se lee en la documentación de Firebase: cuando su aplicación está en segundo plano, Android dirige los mensajes de notificación a la bandeja del sistema. Un usuario que toca la notificación abre el iniciador de aplicaciones de forma predeterminada. Esto incluye mensajes que contienen notificaciones y carga de datos. En estos casos, la notificación se entrega a la bandeja del sistema del dispositivo, y la carga de datos se entrega en los extras de la intención de su Actividad de inicio. ( firebase.google.com/docs/cloud-messaging/android/… ) Tantas respuestas antiguas están desactualizadas
Riot Goof Woof
20

Dado display-messagesque los que se envían desde Firebase Notification UI solo funcionan si tu aplicación está en primer plano. Para data-messages, es necesario hacer una llamada POST a FCM

Pasos

  1. Instale la extensión de Google Chrome del cliente Advanced Rest ingrese la descripción de la imagen aquí

  2. Agregue los siguientes encabezados

    Clave : Tipo de contenido, Valor : aplicación / json

    Clave : Autorización, Valor : clave = "la clave de su servidor" ingrese la descripción de la imagen aquí

  3. Agrega el cuerpo

    • Si usa temas:

      {
          "to" : "/topics/topic_name",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
          }
      }
    • Si usa la identificación de registro:

      {
          "registration_ids" : "[{"id"},{id1}]",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
           }
      }

¡Eso es!. Ahora escuche la onMessageReceiveddevolución de llamada como de costumbre.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();
     String value1 = data.get("key1");
     String value2 = data.get("key2");
}
Skynet
fuente
20

Para capturar el mensaje en segundo plano, debe utilizar un BroadcastReceiver

import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.legacy.content.WakefulBroadcastReceiver
import com.google.firebase.messaging.RemoteMessage

class FirebaseBroadcastReceiver : WakefulBroadcastReceiver() {

    val TAG: String = FirebaseBroadcastReceiver::class.java.simpleName

    override fun onReceive(context: Context, intent: Intent) {

        val dataBundle = intent.extras
        if (dataBundle != null)
            for (key in dataBundle.keySet()) {
                Log.d(TAG, "dataBundle: " + key + " : " + dataBundle.get(key))
            }
        val remoteMessage = RemoteMessage(dataBundle)
        }
    }

y agregue esto a su manifiesto:

<receiver
      android:name="MY_PACKAGE_NAME.FirebaseBroadcastReceiver"
      android:exported="true"
      android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
</receiver>
Romulano
fuente
77
Esto realmente recibe el mensaje de notificación, cuando la aplicación está en segundo plano. Pero no impide que el receptor Firebase predeterminado lo maneje, por lo que el mensaje aún se muestra como una alerta de notificación.
Galya
Por el momento no funciona, por eso propongo esta solución. Hay un error archivado en la base de errores de Google. Es posible que desee comprobar eso.
Romulano
¿Podría publicar un enlace al error aquí
Galya
¿Cómo obtener datos de la notificación?
Ravi Vaghela
Esto claramente no funciona cuando se mata la aplicación. He probado esta solución durante horas. por alguna razón, el receptor funciona mientras la aplicación está en segundo plano y no funciona cuando se
cierra
16
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

}

no se llama cada vez que se llama solo cuando la aplicación está en primer plano

hay un método de anulación al que se llama este método cada vez, no importa qué aplicación esté en primer plano o en segundo plano o eliminada, pero este método está disponible con esta versión de API de Firebase

esta es la versión que tienes que importar desde gradle

compile 'com.google.firebase:firebase-messaging:10.2.1'

este es el método

@Override
public void handleIntent(Intent intent) {
    super.handleIntent(intent);

    // you can get ur data here 
    //intent.getExtras().get("your_data_key") 


}

con la anterior API de Firebase, este método no estaba allí, por lo que en ese caso, la base de fuego se maneja sola cuando la aplicación está en segundo plano ... ahora tiene este método, lo que quiera hacer ... puede hacerlo aquí en este método ... ...

si está utilizando una versión anterior, la actividad predeterminada comenzará en ese caso, puede obtener datos de la misma manera

if(getIntent().getExtras() != null && getIntent().getExtras().get("your_data_key") != null) {
String strNotificaiton = getIntent().getExtras().get("your_data_key").toString();

// Haz lo que quieras .... }

generalmente esta es la estructura del servidor que recibimos en la notificación

{
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon",
        "click_action": "activity name" //optional if required.....
    },
    "data": {
        "product_id": 11,
        "product_details": "details.....",
        "other_info": "......."
    }
}

depende de usted cómo quiere dar esa clave de datos o si desea dar una notificación a cualquier cosa que pueda dar ... lo que sea que dé aquí con la misma clave obtendrá esos datos ........ .

hay pocos casos si no está enviando una acción de clic en ese caso cuando haga clic en la actividad predeterminada de notificación se abrirá, pero si desea abrir su actividad específica cuando la aplicación está en segundo plano, puede llamar a su actividad desde este método handleIntent porque esto se llama cada vez

Avinash Jadaun
fuente
Actualicé la mensajería firebase a 10.2.1, agregué datos al mensaje de notificación y funcionó. Primer plano, fondo y asesinado. Gracias
Firas Shrourou
en Kotlin, recibo este error: (44, 5) 'handleIntent' en 'FirebaseMessagingService' es final y no se puede anular
ugali soft
No funciona por encima de las versiones de Firebase 11
venu46
14

Según los documentos: 17 de mayo de 2017

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

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

Por lo tanto, debe usar la notificación de carga útil + los datos:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}

No hay necesidad de usar click_action. Solo debes obtener exras de la intención en la actividad del LANZADOR

<activity android:name=".MainActivity">
        <intent-filter>
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>

El código Java debe estar en el método onCreate en MainActivity:

Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
    Bundle extras = intent.getExtras();
    String someData= extras.getString("someData");
    String someData2 = extras.getString("someData2");
}

Puedes probar los dos datos de notificación de carga útil desde la consola de notificaciones de Firebase . No olvide completar campos de datos personalizados en la sección Opciones avanzadas

Mihuilk
fuente
14

Aquí hay conceptos más claros sobre el mensaje de Firebase. Lo encontré de su equipo de soporte.

** Firebase tiene tres tipos de mensajes **:

Mensajes de notificación : el mensaje de notificación funciona en segundo plano o en primer plano. Cuando la aplicación está en segundo plano, los mensajes de notificación se entregan a la bandeja del sistema. Si la aplicación está en primer plano, los mensajes son manejados por onMessageReceived()odidReceiveRemoteNotification devoluciones de llamada. Estos son esencialmente lo que se denomina Mostrar mensajes.

Mensajes de datos : en la plataforma Android, los mensajes de datos pueden funcionar en segundo plano y en primer plano. El mensaje de datos será manejado por onMessageReceived (). Una nota específica de la plataforma aquí sería: en Android, la carga útil de datos se puede recuperar en la intención utilizada para iniciar su actividad. Para elaborar, si tiene "click_action":"launch_Activity_1", puede recuperar esta intención getIntent()solo desde Activity_1.

Mensajes con notificaciones y cargas de datos : cuando están en segundo plano, las aplicaciones reciben la carga de notificaciones en la bandeja de notificaciones y solo manejan la carga de datos cuando el usuario toca la notificación. Cuando está en primer plano, su aplicación recibe un objeto de mensaje con ambas cargas disponibles. En segundo lugar, elclick_action parámetro se usa a menudo en la carga de notificación y no en la carga de datos. Si se usa dentro de la carga útil de datos, este parámetro se trataría como un par clave-valor personalizado y, por lo tanto, necesitaría implementar una lógica personalizada para que funcione según lo previsto.

Además, le recomiendo que utilice el onMessageReceivedmétodo (consulte Mensaje de datos) para extraer el paquete de datos. Desde su lógica, verifiqué el objeto del paquete y no he encontrado el contenido de datos esperado. Aquí hay una referencia a un caso similar que podría proporcionar más claridad.

Para más información visita mi este hilo

MD Sajedul Karim
fuente
8

Resumen simple como este

  • si su aplicación se está ejecutando;

    onMessageReceived()

es disparadores.

  • si su aplicación no se está ejecutando (muere al deslizar);

    onMessageReceived()

no se activa y se entrega por direclty. Si tiene algún par especial clave-valor. No funcionan porque onMessageReceived () no funciona.

He encontrado este camino;

En su actividad de iniciador, ponga esta lógica,

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState, R.layout.activity_splash);

    if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("PACKAGE_NAME")) {

        // do what you want

        // and this for killing app if we dont want to start
        android.os.Process.killProcess(android.os.Process.myPid());

    } else {

        //continue to app
    }
}

en este bloque if, busque sus claves de acuerdo con la interfaz de usuario de firebase.

En este ejemplo, mi clave y valor son los anteriores; (perdón por idioma =)) ingrese la descripción de la imagen aquí

Cuando mi código funciona, obtengo "com.rda.note".

android.os.Process.killProcess(android.os.Process.myPid());

con esta línea de código, cerré mi aplicación y abrí Google Play Market

codificación feliz =)

Arda
fuente
6

Descubrí los escenarios,

Cuando la aplicación está en primer plano , onMessageReceived () se llama al método de la FirebaseService .So la pendingIntent definido en la clase de servicio.

Y cuando la aplicación está en segundo plano , se llama a la primera actividad .

Ahora, si se utiliza una actividad de bienvenida , a continuación, debe tener en cuenta la splashactivity se llamará, de lo contrario, si no hay splashActivity, a continuación, cualquiera que sea la primera actividad es, será llamado.

Luego debe verificar getIntent () de firstActivity para ver si tiene algún paquete. Si todo está bien, verá que el paquete está allí con los valores completados. Si el valor en la etiqueta de datos enviada desde el servidor se ve así,

"data": {
    "user_name": "arefin sajib",
    "value": "user name notification"
  }

Luego, en la primera actividad, verá, hay una intención válida ( getIntent () no es nulo ), paquete válido y paquete interno, habrá todo el JSON mencionado anteriormente con datos como clave .

Para este escenario, el código para la extracción de valor se verá así,

    if(getIntent()!=null){
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                try {
                   JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }
Shamsul Arefin Sajib
fuente
3

Gracias a todos por sus respuestas. Pero resolví esto enviando un mensaje de datos en lugar de enviar una Notificación . Código del servidor

<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = "C-l6T_a7HouUK****";
$serverKey = "AAAAaOcKS00:********";
define( 'API_ACCESS_KEY', $serverKey );
$registrationIds = array($token);
// prep the bundle

$msg = array

(
 'message'  => 'here is a message. message',
 'title'        => 'This is a title. title',
 'subtitle' => 'This is a subtitle. subtitle',
 'tickerText'   => 'Ticker text here...Ticker text here...Ticker text 
 here',
 'vibrate'  => 1,
 'sound'        => 1,
 'largeIcon'    => 'large_icon',
 'smallIcon'    => 'small_icon'

);

$fields = array

(
  'registration_ids'    => $registrationIds,
  'data'            => $msg

);
$headers = array

(
  'Authorization: key=' . API_ACCESS_KEY,
 'Content-Type: application/json'

);


$ch = curl_init();

curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' 
);

curl_setopt( $ch,CURLOPT_POST, true );

curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );

curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );

curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );

$result = curl_exec($ch );

curl_close( $ch );

echo $result;

?>

Y capturó los datos en onMessageReceived

public class MyFirebaseMessagingService extends FirebaseMessagingService     {

  private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    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());

      sendNotification(remoteMessage.getData().get("message"));
     }
   // Check if message contains a notification payload.
    else if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    sendNotification(remoteMessage.getNotification().getBody());
    }


}
   private void sendNotification(String messageBody) {
    Intent intent = new Intent(this, Notify.class).putExtra("msg",messageBody);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

    String channelId = "idddd";
    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(MyFirebaseMessagingService.this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("FCM Message")
                    .setContentText(messageBody)
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setContentIntent(pendingIntent);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Android Sanaullah
fuente
1
¿Funciona también con un fondo?
Tabish khan
@Tabishkhan Sí hermano, está funcionando si tienes algún problema, no
dudes
1
hola @AndroidSanaullah, ¿puedes explicar la primera parte del código del servidor, dónde lo pones realmente? Estoy enfrentando el mismo problema, pero no entiendo bien la parte del servidor, ¿estás usando cartero?
Abrió el
curl se utiliza para la solicitud y se le pasan todos los parámetros. @ Shid
Android Sanaullah
2

Elimine la carga de notificación por completo de su solicitud de servidor. Envíe solo datos y trátelos onMessageReceived(), de lo contrario onMessageReceived, no se activará cuando la aplicación esté en segundo plano o se cierre.

Esto es lo que estoy enviando desde el servidor:

{
  "data":{
    "id": 1,
    "missedRequests": 5
    "addAnyDataHere": 123
  },
  "to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......"
}

Para que pueda recibir sus datos de onMessageReceived(RemoteMessage message)esta manera: (digamos que tengo que obtener la identificación)

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }

Y de manera similar, puede obtener cualquier información que haya enviado desde el servidor onMessageReceived().

Zohab Ali
fuente
2

La manera fácil de enviar mensajes incluso si la aplicación está en segundo plano y en primer plano de la siguiente manera: - Para enviar un mensaje usando API, puede usar una herramienta llamada AdvancedREST Client, es una extensión de Chrome, y enviar un mensaje con los siguientes parámetros.

Enlace de la herramienta cliente de descanso: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

use esta url: - https://fcm.googleapis.com/fcm/send Content-Type: application / json Autorización: key = la clave de su servidor o la clave de autorización (consulte la referencia a continuación)

{ "data": {
    "image": "https://static.pexels.com/photos/4825/red-love-romantic-flowers.jpg",
    "message": "Firebase Push Message Using API"
    "AnotherActivity": "True"
     },
  "to" : "device id Or Device token"
}

La clave de autorización se puede obtener visitando la consola de desarrolladores de Google y haciendo clic en el botón Credenciales en el menú de la izquierda para su proyecto. Entre las claves API enumeradas, la clave del servidor será su clave de autorización.

Y debe colocar el tokenID del receptor en la sección "para" de su solicitud POST enviada mediante API.

Syed Danish Haider
fuente
2

desea trabajar enMessageReceived (RemoteMessage remoteMessage) en segundo plano enviar solo notificación de parte de datos, parte esto:

"data":    "image": "",    "message": "Firebase Push Message Using API", 

"AnotherActivity": "True", "to": "id del dispositivo o token del dispositivo"

Con esto, onMessageRecivied es un fondo de llamada y un primer plano sin necesidad de manejar la notificación usando la bandeja de notificaciones en su actividad de iniciador. Maneje la carga útil de datos al usar esto:

  public void onMessageReceived(RemoteMessage remoteMessage)
    if (remoteMessage.getData().size() > 0) 
    Log.d(TAG, "Message data payload: " + remoteMessage.getData());      
usuario3385125
fuente
1

Respuesta de junio de 2018 -

Debe asegurarse de que no haya una palabra clave de "notificación" en ninguna parte del mensaje. Solo incluya "datos", y la aplicación podrá manejar el mensaje en onMessageReceived, incluso en segundo plano o muerto.

Uso de funciones en la nube:

const message = {
    token: token_id,   // obtain device token id by querying data in firebase
    data: {
       title: "my_custom_title",
       body:  "my_custom_body_message"
       }
    }


return admin.messaging().send(message).then(response => {
    // handle response
});

Luego, en su onMessageReceived (), en su clase que extiende com.google.firebase.messaging.FirebaseMessagingService:

if (data != null) {
  Log.d(TAG, "data title is: " + data.get("title");
  Log.d(TAG, "data body is: " + data.get("body");
}

// build notification using the body, title, and whatever else you want.
Jeff Padgett
fuente
¿tienes alguna fuente, es segura?
Yogesh Rathi
Es seguro, lo uso en mis aplicaciones. Sin embargo, 6 meses después de la publicación, no puedo recordar la fuente; me imagino que es la documentación de Firebase.
Jeff Padgett el
1

De acuerdo con OAUTH 2.0:

Habrá un problema de autenticación para este caso porque FCM ahora usa OAUTH 2

Entonces leí la documentación de Firebase y, según la documentación, es una nueva forma de publicar un mensaje de datos;

POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send

Encabezados

Key: Content-Type, Value: application/json

Autenticación

Bearer YOUR_TOKEN 

Cuerpo de ejemplo

{
   "message":{
    "topic" : "xxx",
    "data" : {
         "body" : "This is a Firebase Cloud Messaging Topic Message!",
         "title" : "FCM Message"
          }
      }
 }

En la URL hay un Id. De base de datos que puede encontrar en su consola Firebase. (Ir a los ajustes del proyecto)

Y ahora tomemos nuestro token (será válido solo 1 hora):

Primero en la consola de Firebase, abra Configuración> Cuentas de servicio . Haga clic en Generar nueva clave privada , guarde de forma segura el archivo JSON que contiene la clave. Necesitaba este archivo JSON para autorizar las solicitudes del servidor manualmente. Lo descargué.

Luego creo un proyecto node.js y utilicé esta función para obtener mi token;

var PROJECT_ID = 'YOUR_PROJECT_ID';
var HOST = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];

  router.get('/', function(req, res, next) {
      res.render('index', { title: 'Express' });
      getAccessToken().then(function(accessToken) {
        console.log("TOKEN: "+accessToken)
      })

    });

function getAccessToken() {
return new Promise(function(resolve, reject) {
    var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
    var jwtClient = new google.auth.JWT(
        key.client_email,
        null,
        key.private_key,
        SCOPES,
        null
    );
    jwtClient.authorize(function(err, tokens) {
        if (err) {
            reject(err);
            return;
        }
        resolve(tokens.access_token);
    });
});
}

Ahora puedo usar este token en mi solicitud de publicación. Luego publico mi mensaje de datos, y ahora lo manejan mis aplicaciones en la función MensajeRecibido.

Ozan
fuente
La respuesta aceptada está funcionando, la autenticación de token de Barer no es la forma, necesita leer esto para intentarlo con Postman: stackoverflow.com/questions/45309674/…
Carlos Jesus Arancibia Taborga
1

Desde 2019, Google Firebase tiene un gran cambio en sus API, quiero decir: 'com.google.firebase:firebase-messaging:18.0.0'

en 18.0.0 se eliminaron MyFirebaseInstanceIDServicey necesitas obtener un token, MyFirebaseMessagingServiceasí que solo necesitas escribir:

@Override
public void onNewToken(String token) {
    Log.d(TAG, "Refreshed token: " + token);

}

y también en su AndroidManifest.xml, debe eliminar:

<service android:name=".service.MyFirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_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 apliquen siempre que no se establezcan valores equivalentes en la carga de notificación.

Agregue estas líneas dentro de la etiqueta de la aplicación para establecer el icono predeterminado personalizado y el color personalizado:

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_notification" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/push_channel" />

ahora para manejar los mensajes de notificación en una aplicación en segundo plano, debe definir un Intento en su primera Actividad, incluso si es SplashScreen. Cuando su aplicación está en segundo plano, Android dirige los mensajes de notificación a la bandeja del sistema. Un usuario que toca la notificación abre el iniciador de aplicaciones de forma predeterminada.

por ejemplo, si tu Json es así:

 "data": {
"message": "2",
"title": "1",
"pushType" : "banner",
"bannerLink": "http://www.google.com",
"image" : "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}

solo necesita escribir una intención simple para obtener esos valores:

        Bundle extras = intent.getExtras();
        String bannerLink = extras.getString("bannerLink");
        ...
        String channelId = extras.getString("channelId");
Mohammad Mirzakhani
fuente
0

Además de las respuestas anteriores, si está probando notificaciones push utilizando la consola FCM , la clave y el objeto 'datos' no se agregan al paquete de notificaciones push. Por lo tanto, no recibirá notificaciones push detalladas cuando la aplicación esté en segundo plano o se cierre.

En este caso, debe optar por su consola de administración de back-end para probar el escenario de fondo de la aplicación.

Aquí, habrá agregado la clave 'datos' a su paquete push. entonces, el empuje detallado se mostrará como se esperaba. Espero que esto ayude a pocos.

Max Droid
fuente
0

Usando este código puede obtener la notificación en segundo plano / primer plano y también poner acción:

//Data should come in this format from the notification
{
  "to": "/xyz/Notifications",
  "data": {
      "key1": "title notification",
      "key2": "description notification"
  }
}

En la aplicación, use este código:

  @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
      String key1Data = remoteMessage.getData().get("key1");
      // use key1Data to according to your need
    }
Ashish Kumar
fuente
// Los datos deben venir en este formato de la notificación {"a": "/ xyz / Notificaciones", "data": {"clave1": "notificación de título", "clave2": "notificación de descripción"}} Cómo escribir este código en el servicio php?
Tabish khan
-3

Habrá dos tipos de notificaciones.

  1. Mostrar notificaciones: solo se mostrarán las notificaciones, se mostrará solo la aplicación no está abierta y está en la pila de aplicaciones.
  2. Notificación de datos: la devolución de llamada entrará en el método onMessageReceived de firebasemessagingservice y funciona cuando la aplicación está en segundo plano, en primer plano o en estado inactivo.

Debe usar las notificaciones de datos para manejar la notificación cuando la aplicación está en segundo plano.

abhi.nalavade
fuente
-5

Experimenté el mismo problema y recompilé la biblioteca de Firebase y evité que enviara notificaciones cuando la aplicación está en segundo plano.

* biblioteca https://github.com/erdalceylan/com-google-firebase-messaging

 dependencies {
        compile 'com.google.firebase:firebase-core:11.2.0'
        compile 'com.github.erdalceylan:com-google-firebase-messaging:v1-11.2.0'
    }

* *

@WorkerThread
public void onMessageReceived(RemoteMessage var1) {
  //your app is in background or foreground all time calling
}

La esperanza ayuda. Buena suerte

Erdal CEYLAN
fuente
2
Respuesta no útil
Ankit Patidar
2
Esta es una sugerencia horrible.
vsecades