una studio segundo plano notificación mensajes mantener maneja app android firebase firebase-cloud-messaging

android - studio - maneja mensajes de notificación en una app en segundo plano



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

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 código onMessageReceived . 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]


1. ¿Por qué está pasando esto?

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

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

El equipo de Firebase aún no ha desarrollado una interfaz de usuario para enviar data-messages a sus dispositivos.

2. ¿Cómo?

Para lograr esto, debe realizar una solicitud POST 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 notification clave JSON
NOTA: Para obtener su clave de 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 }


Respuesta actualizada 2017

Aquí hay una respuesta clara de los docs respecto a esto:


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á una notificación push detallada cuando la aplicación esté en segundo plano o sea eliminada.

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.


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 MyFirebaseInstanceIDService y necesitas obtener un token, MyFirebaseMessagingService así que solo necesitas escribir:

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 también en su AndroidManifest.xml, debe eliminar:

@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(); }

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:

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); } }

ahora para manejar los mensajes de notificación en una aplicación de fondo, debe definir una intención 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í:

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(); }

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

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


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


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

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

Y capturó los datos en onMessageReceived

Key: Content-Type, Value: application/json


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.


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

utilice 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)

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); }); }); }

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.


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:

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

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

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


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

// Place this code on your MainActivity,then you will get your payload // Handle possible data accompanying notification message. // [START handle_data_extras] if (getIntent().getExtras() != null) { for (String key : getIntent().getExtras().keySet()) { Object value = getIntent().getExtras().get(key); Log.d(TAG, "Key: " + key + " Value: " + value); } }

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

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


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

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

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

Por esto onMessageRecivied es el fondo de la llamada y el 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:

Bundle extras = intent.getExtras(); String bannerLink = extras.getString("bannerLink"); ... String channelId = extras.getString("channelId");


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() o didReceiveRemoteNotification callbacks. 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 a través de getIntent() de solo 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, el parámetro click_action 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 use el método onMessageReceived (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


Dado que los display-messages que se envían desde la interfaz de usuario de notificación de Firebase solo funcionan si su aplicación está en primer plano. Para data-messages , es necesario hacer una llamada POST a https://fcm.googleapis.com/fcm/send

Pasos

  1. Instale la extensión de Google Chrome Advanced Rest Client

  2. Agregue los siguientes encabezados

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

    Clave : Autorización, Valor : clave = "la clave de su servidor"

  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 devolución de llamada onMessageReceived 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"); }


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

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

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 .

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

Esta carga útil de notificaciones 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], establezca 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:

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

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:

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

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

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


De acuerdo con los docs

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:

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

Editar:

Basado en este thread :

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

{ "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" } }


Descubrí los escenarios,

Cuando la aplicación está en primer plano , se llama al método onMessageReceived () desde el FirebaseService . Por lo tanto, se llamará al pendienteIntent definido en la clase de servicio.

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

Ahora, si utiliza una actividad de bienvenida , debe tener en cuenta que se llamará a la actividad de salpicadura , de lo contrario, si no hay actividad de salpicadura, se llamará a la primera actividad.

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(); } } }


Para capturar el mensaje en segundo plano, debe usar 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>


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 */ }


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 =))

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 =)


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


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 :)


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;

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

Encabezados

@Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); String key1Data = remoteMessage.getData().get("key1"); // use key1Data to according to your need }

Autenticación

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

Cuerpo de ejemplo

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

En la URL hay un Id. De base de datos que puedes encontrar en tu 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;

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


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:

Bearer YOUR_TOKEN

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

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

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


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 , 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 es recibida por 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:

<?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; ?>

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

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()); } }

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

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

3- crea la clase MyFirebase así:

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

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

{ "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" }

}

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

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 });

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

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.

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: (mismo texto aquí que en el campo Título de la sección Notificación) clave: valor del cuerpo: (mismo texto aquí que en el campo Mensaje de la sección Notificación) clave: clic_acción valor: .MainActivity Sound = Desactivado
Caduca = 4 semanas

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

¡Feliz codificación!


@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, sin importar 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 notificación, se abrirá la actividad predeterminada, 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


// 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)); }