Firebase onMessageReceived pas appelé lorsque l’application en arrière-plan

Je travaille avec Firebase et je teste l’envoi de notifications à mon application depuis mon serveur pendant que l’application est en arrière-plan. La notification est envoyée avec succès, elle apparaît même dans le centre de notification du périphérique, mais lorsque la notification apparaît ou même si je clique dessus, la méthode onMessageReceived dans mon FCMessagingService n’est jamais appelée.

Lorsque j’ai testé cela alors que mon application était au premier plan, la méthode onMessageReceived a été appelée et tout s’est bien passé. Le problème se produit lorsque l’application s’exécute en arrière-plan.

Ce comportement est-il prévu ou existe-t-il un moyen de résoudre ce problème?

Voici mon service FBMessaging:

import android.util.Log; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; public class FBMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { Log.i("PVL", "MESSAGE RECEIVED!!"); if (remoteMessage.getNotification().getBody() != null) { Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody()); } else { Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message")); } } } 

    Cela fonctionne comme prévu, les messages de notification sont remis à votre rappel onMessageReceived uniquement lorsque votre application est au premier plan. Si votre application est en arrière-plan ou fermée, un message de notification est affiché dans le centre de notification et toutes les données de ce message sont transmises à l’intention qui est lancée suite à un appui de l’utilisateur sur la notification.

    Vous pouvez spécifier une action click_action pour indiquer l’intention qui doit être lancée lorsque l’utilisateur enregistre la notification. L’activité principale est utilisée si aucune action de clic n’est spécifiée.

    Lorsque l’intention est lancée, vous pouvez utiliser le

     getIntent().getExtras(); 

    pour récupérer un ensemble qui inclurait toutes les données envoyées avec le message de notification.

    Pour plus d’informations sur les messages de notification, voir docs .

    J’ai une solution parfaite pour cela:

    Vous devez effectuer 2 étapes simples:

    1. Mettez à niveau votre firebase vers la version comstack com.google.firebase:firebase-messaging:10.2.1
    2. Remplacez la handleIntent(Intent intent) dans votre classe FirebaseMessagingService .

    handleIntent() méthode handleIntent() est appelée à chaque fois, que l’application soit au premier plan, en arrière-plan ou en état mort.

    Supprimez complètement le champ de notification de votre requête de serveur. Envoyez uniquement des data et gérez-les dans onMessageReceived() sinon votre onMessageReceived() ne sera pas déclenché lorsque l’application est en arrière-plan ou tuée.

    N’oubliez pas d’inclure "priority": "high" champ "priority": "high" dans votre demande de notification. Selon la documentation: les messages de données sont envoyés avec une priorité normale, ils n’arriveront donc pas instantanément; cela pourrait aussi être le problème.

    Voici ce que j’envoie du serveur

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

    Ainsi, vous pouvez recevoir vos données dans onMessageReceived(RemoteMessage message) comme ceci … disons que je dois obtenir un identifiant

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

    J’ai eu le même problème. Il est plus facile d’utiliser le «message de données» au lieu de la «notification». Le message de données charge toujours la classe onMessageReceived.

    Dans cette classe, vous pouvez faire votre propre notification avec le constructeur de notifications.

    Exemple:

      @Override public void onMessageReceived(RemoteMessage remoteMessage) { sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body")); } private void sendNotification(Ssortingng messageTitle,Ssortingng messageBody) { Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT); long[] pattern = {500,500,500,500,500}; Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_stat_name) .setContentTitle(messageTitle) .setContentText(messageBody) .setAutoCancel(true) .setVibrate(pattern) .setLights(Color.BLUE,1,1) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); } 

    Voici des concepts plus clairs sur le message Firebase. Je l’ai trouvé de leur équipe de support.

    Firebase a trois types de messages :

    Messages de notification : le message de notification fonctionne en arrière-plan ou au premier plan. Lorsque l’application est en arrière-plan, les messages de notification sont envoyés dans la barre d’état système. Si l’application est au premier plan, les messages sont gérés par les onMessageReceived() ou didReceiveRemoteNotification . Ce sont essentiellement ce que l’on appelle les messages d’affichage.

    Messages de données : sur la plate-forme Android, le message de données peut fonctionner en arrière-plan et au premier plan. Le message de données sera géré par onMessageReceived (). Une note spécifique à la plate-forme serait la suivante: Sur Android, la charge de données peut être récupérée dans l’intention utilisée pour lancer votre activité. Pour élaborer, si vous avez "click_action":"launch_Activity_1" , vous pouvez récupérer cette intention via getIntent() uniquement à partir de Activity_1 .

    Messages contenant à la fois des charges utiles de notification et de données : en arrière-plan, les applications reçoivent la charge utile de notification dans la barre de notification et ne traitent que la charge utile de données lorsque l’utilisateur appuie sur la notification. Au premier plan, votre application reçoit un object de message avec les deux données utiles disponibles. Deuxièmement, le paramètre click_action est souvent utilisé dans les données utiles de notification et non dans les données utiles. S’il est utilisé à l’intérieur de data payload, ce paramètre sera traité comme une paire clé-valeur personnalisée et vous devrez donc implémenter une logique personnalisée pour que cela fonctionne comme prévu.

    Je vous recommande également d’utiliser la méthode onMessageReceived (voir Message de données) pour extraire le regroupement de données. De votre logique, j’ai vérifié l’object du bundle et n’ai pas trouvé le contenu attendu des données. Voici une référence à un cas similaire qui pourrait apporter plus de clarté.

    Pour plus d’infos visitez mon ce fil

    Selon la documentation de Firebase Cloud Messaging-Si l’activité est au premier plan, onMessageReceived sera appelé. Si l’activité est en arrière-plan ou fermée, un message de notification s’affiche dans le centre de notification pour l’activité du lanceur d’application. Vous pouvez appeler votre activité personnalisée en cliquant sur notification si votre application est en arrière-plan en appelant l’API Rest Service pour la messagerie Firebase en tant que:

    URL- https://fcm.googleapis.com/fcm/send

    Type de méthode – POST

     Header- Content-Type:application/json Authorization:key=your api key 

    Corps / Charge utile:

     { "notification": { "title": "Your Title", "text": "Your Text", "click_action": "OPEN_ACTIVITY_1" // should match to your intent filter }, "data": { "keyname": "any value " //you can get this data as extras in your activity and this data is optional }, "to" : "to_id(firebase refreshedToken)" } 

    Et avec cela dans votre application, vous pouvez append le code ci-dessous dans votre activité à appeler:

         

    Si l’application est en mode d’arrière-plan ou inactive (tué) et que vous cliquez sur Notification , vous devez vérifier la charge utile dans LaunchScreen (dans mon cas, l’écran de lancement est MainActivity.java).

    Donc, dans MainActivity.java , onCreate vérifie les extras :

      if (getIntent().getExtras() != null) { for (Ssortingng key : getIntent().getExtras().keySet()) { Object value = getIntent().getExtras().get(key); Log.d("MainActivity: ", "Key: " + key + " Value: " + value); } } 

    Remplacez la méthode handleIntent du travail FirebaseMessageService pour moi.

    ici le code en C # (Xamarin)

     public override void HandleIntent(Intent intent) { try { if (intent.Extras != null) { var builder = new RemoteMessage.Builder("MyFirebaseMessagingService"); foreach (ssortingng key in intent.Extras.KeySet()) { builder.AddData(key, intent.Extras.Get(key).ToSsortingng()); } this.OnMessageReceived(builder.Build()); } else { base.HandleIntent(intent); } } catch (Exception) { base.HandleIntent(intent); } } 

    et c’est le code en Java

     public void handleIntent(Intent intent) { try { if (intent.getExtras() != null) { RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService"); for (Ssortingng key : intent.getExtras().keySet()) { builder.addData(key, intent.getExtras().get(key).toSsortingng()); } onMessageReceived(builder.build()); } else { super.handleIntent(intent); } } catch (Exception e) { super.handleIntent(intent); } } 

    Par défaut, l’ activité de lancement de votre application sera lancée lorsque votre application est en arrière-plan et vous cliquez sur la notification. Si vous avez une partie de données avec votre notification, vous pouvez la gérer de la même manière que ci-dessous.

     if(getIntent().getExtras()! = null){ //do your stuff }else{ //do that you normally do } 

    J’ai implémenté cette méthode simple pour envoyer des messages même si l’application est fermée, en arrière-plan et au premier plan. J’utilisais auparavant la console firebase mais je n’obtiens que des messages, pas des images et des données personnalisées.

    Pour envoyer ces données personnalisées avec l’image, vous pouvez utiliser un outil appelé AdvancedREST Client , c’est une extension chrome et envoyer un message avec les parameters suivants:

     Rest client tool Link: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo 

    utilisez cette url:- https://fcm.googleapis.com/fcm/send Content-Type:application/json Authorization:key=Your Server key From or Authorization key (voir ci-dessous réf.)

     { "data": { "image": "http://soffr.miximages.com/android/red-love-romantic-flowers.jpg", "message": "Firebase Push Message Using API" "AnotherActivity": "True" }, "to" : "device id Or Device token" } 

    La clé d’autorisation peut être obtenue en visitant la console des développeurs Google et en cliquant sur le bouton Informations d’identification dans le menu de gauche pour votre projet. Parmi les clés API répertoriées, la clé du serveur sera votre clé d’autorisation.

    Et vous devez mettre un tokenID du destinataire dans la section to de votre requête POST envoyée à l’aide de l’API.

    Et ce morceau de code // Android message contiendra le message Push

     Ssortingng message = remoteMessage.getData().get("message1"); //imageUri will contain URL of the image to be displayed with Notification Ssortingng imageUri = remoteMessage.getData().get("image"); //If the key AnotherActivity has value as True then when the user taps on notification, in the app AnotherActivity will be opened. //If the key AnotherActivity has value as False then when the user taps on notification, in the app MainActivity2 will be opened. Ssortingng TrueOrFlase = remoteMessage.getData().get("AnotherActivity"); //To get a Bitmap image from the URL received bitmap = getBitmapfromUrl(imageUri); sendNotification(message, bitmap, TrueOrFlase); 

    J’ai le même problème. Si l’application est au premier plan, cela déclenche mon service d’arrière-plan où je peux mettre à jour ma firebase database en fonction du type de notification. Mais, l’application va en arrière-plan – le service de notification par défaut sera chargé d’afficher la notification à l’utilisateur.

    Voici ma solution pour identifier l’application en arrière-plan et déclencher votre service d’arrière-plan,

     public class FirebaseBackgroundService extends WakefulBroadcastReceiver { private static final Ssortingng TAG = "FirebaseService"; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "I'm in!!!"); if (intent.getExtras() != null) { for (Ssortingng key : intent.getExtras().keySet()) { Object value = intent.getExtras().get(key); Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value); if(key.equalsIgnoreCase("gcm.notification.body") && value != null) { Bundle bundle = new Bundle(); Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class); bundle.putSsortingng("push_message", value + ""); backgroundIntent.putExtras(bundle); context.startService(backgroundIntent); } } } } } 

    Dans le fichier manifest.xml

          

    Testé cette solution dans la dernière version Android 8.0. Merci

    Il suffit d’appeler ceci dans la méthode onCreate de votre MainActivity:

     if (getIntent().getExtras() != null) { // Call your NotificationActivity here.. Intent intent = new Intent(MainActivity.this, NotificationActivity.class); startActivity(intent); } 

    selon la solution de t3h Exi je voudrais poster le code propre ici. Il suffit de le mettre dans MyFirebaseMessagingService et tout fonctionne bien si l’application est en mode d’arrière-plan. Vous devez au moins comstackr com.google.firebase: firebase-messaging: 10.2.1

      @Override public void handleIntent(Intent intent) { try { if (intent.getExtras() != null) { RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService"); for (Ssortingng key : intent.getExtras().keySet()) { builder.addData(key, intent.getExtras().get(key).toSsortingng()); } onMessageReceived(builder.build()); } else { super.handleIntent(intent); } } catch (Exception e) { super.handleIntent(intent); } } 

    Si l’application est en arrière-plan Gestion de la base par défaut notification de manipulation Mais si nous voulons notre notification personnalisée que nous devons changer notre côté serveur, qui est responsable d’envoyer nos données personnalisées (données utiles)

    Supprimez complètement la charge de notification de votre requête de serveur. Envoyez uniquement des données et gérez-les dans onMessageReceived () sinon votre onMessageReceived ne sera pas déclenché lorsque l’application est en arrière-plan ou tuée.

    maintenant, votre format de code côté serveur ressemble,

     { "collapse_key": "CHAT_MESSAGE_CONTACT", "data": { "loc_key": "CHAT_MESSAGE_CONTACT", "loc_args": ["John Doe", "Contact Exchange"], "text": "John Doe shared a contact in the group Contact Exchange", "custom": { "chat_id": 241233, "msg_id": 123 }, "badge": 1, "sound": "sound1.mp3", "mute": true } } 

    REMARQUE : voir cette ligne dans le code ci-dessus
    “text”: “John Doe a partagé un contact dans le groupe Contact Exchange” dans Data payload, vous devez utiliser le paramètre “text” au lieu des parameters “body” ou “message” pour la description du message ou le texte.

    onMessageReceived ()

     @Override public void onMessageReceived(RemoteMessage remoteMessage) { Log.e(TAG, "From: " + remoteMessage.getData().toSsortingng()); if (remoteMessage == null) return; // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { /* Log.e(TAG, "Data Payload: " + remoteMessage.getData().toSsortingng());*/ Log.e(TAG, "Data Payload: " + remoteMessage); try { Map params = remoteMessage.getData(); JSONObject json = new JSONObject(params); Log.e("JSON_OBJECT", json.toSsortingng()); Log.e(TAG, "onMessageReceived: " + json.toSsortingng()); handleDataMessage(json); } catch (Exception e) { Log.e(TAG, "Exception: " + e.getMessage()); } } } 

    Essaye ça:

     public void handleIntent(Intent intent) { try { if (intent.getExtras() != null) { RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService"); for (Ssortingng key : intent.getExtras().keySet()) { builder.addData(key, intent.getExtras().get(key).toSsortingng()); } onMessageReceived(builder.build()); } else { super.handleIntent(intent); } } catch (Exception e) { super.handleIntent(intent); } } 

    J’ai eu ce problème (application ne veut pas ouvrir le clic de notification si l’application est en arrière-plan ou fermé), et le problème était un click_action invalide dans le corps de la notification, essayez de le supprimer ou de le changer pour quelque chose de valide.

    J’avais le même problème et j’ai fait plus de recherches à ce sujet. Lorsque l’application est en arrière-plan, un message de notification est envoyé à la barre d’état système, MAIS un message de données est envoyé à onMessageReceived()
    Voir https://firebase.google.com/docs/cloud-messaging/downstream#monitor-token-generation_3
    et https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java.

    Pour vous assurer que le message que vous envoyez, les documents indiquent ” Utiliser votre serveur d’applications et l’API du serveur FCM: définissez uniquement la clé de données. Peut être pliable ou non.
    Voir https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

    Le point qui mérite d’être souligné est que vous devez utiliser le message de données – clé de données uniquement – pour obtenir le gestionnaire onMessageReceived appelé même lorsque l’application est en arrière-plan. Aucune autre clé de message de notification ne doit figurer dans votre charge utile, sinon le gestionnaire ne sera pas déclenché si l’application est en arrière-plan.

    Il est mentionné (mais pas tellement souligné dans la documentation FCM) ici:

    https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

    Utilisez votre serveur d’applications et l’API du serveur FCM: Définissez la clé de données uniquement . Peut être pliable ou non.

    Le backend avec lequel je travaille utilise des messages de notification et non des messages de données. Donc, après avoir lu toutes les réponses, j’ai essayé de récupérer les extras du paquet de l’intention qui vient à l’activité lancée. Mais peu importe les clés que j’ai essayé de récupérer depuis getIntent().getExtras(); , la valeur était toujours nulle.

    Cependant, j’ai finalement trouvé un moyen d’envoyer des données à l’aide de messages de notification et de les récupérer dans l’intention.

    La clé ici est d’append la charge utile de données au message de notification.

    Exemple:

     { "data": { "message": "message_body", "title": "message_title" }, "notification": { "body": "test body", "title": "test title" }, "to": "E4An.." } 

    Après cela, vous pourrez obtenir vos informations de cette manière:

    intent.getExtras().getSsortingng("title") sera message_title

    et intent.getExtras().getSsortingng("message") sera message_body

    Référence

    Si votre problème est lié à l’affichage de Big Image, c’est-à-dire si vous envoyez une notification push avec une image de la console firebase et que celle-ci affiche l’image uniquement si l’application est au premier plan. La solution à ce problème consiste à envoyer un message push avec uniquement un champ de données. Quelque chose comme ça:

     { "data": { "image": "http://soffr.miximages.com/android/red-love-romantic-flowers.jpg", "message": "Firebase Push Message Using API" "AnotherActivity": "True" }, "to" : "device id Or Device token" } 

    Il existe deux types de messages: les messages de notification et les messages de données. Si vous envoyez uniquement un message de données, cela est sans object de notification dans votre chaîne de message. Il serait invoqué lorsque votre application en arrière-plan.

    Lorsque le message est reçu et que votre application est en arrière-plan, la notification est envoyée à l’intention de l’activité principale.

    Vous pouvez vérifier la valeur supplémentaire dans la fonction oncreate () ou onresume () de l’activité principale.

    Vous pouvez vérifier les champs comme les données, la table, etc. (celle spécifiée dans la notification)

    par exemple j’ai envoyé en utilisant des données comme clé

     public void onResume(){ super.onResume(); if (getIntent().getSsortingngExtra("data")!=null){ fromnotification=true; Intent i = new Intent(MainActivity.this, Activity2.class); i.putExtra("notification","notification"); startActivity(i); } } 

    Remplacez simplement la méthode OnCreate de FirebaseMessagingService. Il est appelé lorsque votre application est en arrière-plan:

     public override void OnCreate() { // your code base.OnCreate(); }