563 votes

Comment gérer les notifications lorsque l'application est en arrière-plan dans Firebase ?

Voici mon manifeste

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

Quand l'application est en arrière-plan et qu'une notification arrive, la notification par défaut arrive et n'exécute pas mon code de onMessageReceived .

Voici mon onMessageReceived code. Ce code est invoqué si mon application est en avant-plan, mais pas lorsque l'application est en arrière-plan. Comment exécuter ce code lorsque l'application est en arrière-plan également ?

// [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]

3 votes

C'est écrit dans le exemple de surcharge de onMessageReceived() la deuxième ligne de commentaires dit Not getting messages here? See why this may be: goo.gl/39bRNJ . La solution, comme les réponses ci-dessous, peut être trouvée dans la documentation en Messages contenant à la fois des notifications et des données

6 votes

En bref, pour réveiller votre application tuée, vous devez toujours envoyer une notification avec un objet de données pour appeler le gestionnaire de classe de votre service de notification FirebaseMessagingService.onMessageReceived() dans votre application. Essayez également de l'envoyer non pas à partir de la console Firebase, mais à partir d'un autre endroit (par exemple, un service de post-test en ligne).

3 votes

Cette solution a fonctionné pour moi stackoverflow.com/a/44150822/6632278 J'espère que cela vous aidera. Bonne chance

859voto

Antonio Points 6182

1. Pourquoi cela se produit-il ?

Il existe deux types de messages dans FCM (Firebase Cloud Messaging) :

  1. Messages d'affichage : Ces messages déclenchent le onMessageReceived() uniquement lorsque votre application est en Premier plan
  2. Messages de données : Ces messages déclenchent le onMessageReceived() rappel même si votre application est en avant-plan/arrière-plan/tué

NOTE : L'équipe de Firebase n'a pas développé une interface utilisateur pour envoyer data-messages à vos appareils, pour le moment. Vous devez utiliser votre serveur pour envoyer ce type de message !

2. Comment ?

Pour ce faire, vous devez effectuer un POST à l'URL suivante :

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

En-têtes

  • Clé : Content-Type , Valeur : application/json
  • Clé : Authorization , Valeur : key=<your-server-key>

Corps utilisant des sujets

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

Ou si vous voulez l'envoyer à des appareils spécifiques

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

NOTE : Assurez-vous que vous êtes ne pas ajouter Clé JSON notification
NOTE : Pour obtenir votre clé de serveur, vous pouvez la trouver dans la console firebase : Your project -> settings -> Project settings -> Cloud messaging -> Server Key

3. Comment gérer le message de notification push ?

C'est ainsi que vous traitez le message reçu :

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

     // Manage data
}

0 votes

Bonjour, apparemment, si je fournis le to clé, ça marche. Mais lorsque je remplace cette liste par une liste de jetons de périphériques que je souhaite envoyer, c'est-à-dire registration_ids mais la notification n'est pas transmise. Avez-vous une idée ? EDIT : J'ai résolu le problème. Pour une raison quelconque, si je supprime la clé sender-id de mes en-têtes, tout fonctionne normalement. C'est étrange.

9 votes

Vous pouvez envoyer les touches "données" et "notification" dans la même notification en suivant les étapes suivantes stackoverflow.com/a/42279260/2734021 :)

1 votes

Si vous envoyez des messages à un sujet, assurez-vous d'avoir souscrit à ce sujet sur votre service.

215voto

Pour que la bibliothèque de firebase appelle votre onMessageReceived() dans les cas suivants

  1. Application au premier plan
  2. Application en arrière-plan
  3. L'application a été tuée

vous ne devez pas mettre la clé JSON 'notification' dans votre requête à l'API firebase mais plutôt utiliser 'data', voir ci-dessous.

Le message suivant n'appellera pas votre onMessageReceived() lorsque votre application est en arrière-plan ou tuée, et vous ne pouvez pas personnaliser votre notification.

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

mais à la place, utiliser ceci fonctionnera

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

Fondamentalement, le message est envoyé dans l'argument RemoteMessage avec votre objet de données en tant que Map<String, String>, puis vous pouvez gérer la notification dans onMessageReceived comme dans le snippet ici

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

1 votes

Est-il possible de réaliser cela à partir de la console Firebase ?

0 votes

@koder, malheureusement la console Firebase ne supporte pas cela, vous devez utiliser un outil pour envoyer une demande de message à firebase comme curl ou postman (plugin chrome), firebase messaging api s'il vous plaît se référer au document ici - firebase.google.com/docs/cloud-messaging/http-server-ref

0 votes

L'objet de notification ne doit pas contenir de texte plutôt que de corps

159voto

Daniel S. Points 71

J'ai l'impression que toutes les réponses sont incomplètes mais elles ont toutes quelque chose à voir avec le traitement d'une notification qui contient des données lorsque votre application est en arrière-plan.

Suivez ces étapes et vous serez en mesure de traiter vos notifications lorsque votre application est en arrière-plan.

1. ajouter un filtre d'intention comme celui-ci :

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

à une activité qui doit traiter les données de la notification.

  1. Envoyez des notifications avec le format suivant :

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

La clé ici est d'ajouter

"click_action" : ".MainActivity"

où .MainActivity est l'activité avec le filtre d'intention que vous avez ajouté à l'étape 1.

  1. Obtenir l'information "data" de la notification dans le 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
        }
    }

Et ça devrait être tout ce que vous avez à faire. J'espère que cela aidera quelqu'un :)

9 votes

Cela devrait être la bonne réponse. Aucune des documentations ne mentionne la nécessité d'une action de clic ET d'un filtre d'intention pour que la notification s'affiche dans la zone de notification. Les deux sont nécessaires.

0 votes

@airowe ils ne sont pas nécessaires pour que la notification apparaisse.

1 votes

J'ai des blocs de données et de notification mais je ne suis pas en mesure de recevoir des données dans l'activité ?

60voto

Hendy Evan Points 234

Selon la documentation de firebase dans envoyer en aval en utilisant firebase il y a deux types de charge utile :

  1. données

    Ce paramètre spécifie les paires clé-valeur personnalisées de la charge utile du message. L'application cliente est responsable du traitement des messages de données. Les messages de données ne comportent que des paires clé-valeur personnalisées.

  2. notification

    Ce paramètre spécifie les paires clé-valeur prédéfinies et visibles par l'utilisateur des données utiles de la notification. Le FCM affiche automatiquement le message sur les appareils des utilisateurs finaux pour le compte de l'application cliente. Les messages de notification ont un ensemble prédéfini de clés visibles par l'utilisateur.

Lorsque vous êtes au premier plan, vous pouvez obtenir les données à l'intérieur du FCM en utilisant onMessageReceived() vous pouvez obtenir vos données à partir de données la charge utile.

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

Lorsque vous êtes en arrière-plan, le FCM affichera une notification dans la barre d'état système en fonction des informations fournies par le système. notification charge utile. Le titre, le message et l'icône qui sont utilisés pour la notification dans la barre d'état système sont obtenus à partir de la base de données de l'utilisateur. notification la charge utile.

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

Este notification sont utilisés lorsque vous souhaitez afficher automatiquement une notification dans la barre d'état système lorsque votre application est en arrière-plan. Pour obtenir les données de notification lorsque votre application est en arrière-plan, vous devez ajouter click_action à l'intérieur de notification la charge utile.

Si vous souhaitez ouvrir votre application et effectuer une action spécifique [en arrière-plan], définissez click_action dans les données utiles de la notification et associez-le à un filtre d'intention dans l'activité que vous souhaitez lancer. Par exemple, définissez click_action sur OPEN_ACTIVITY_1 pour déclencher un filtre d'intention comme le suivant :

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

Placez ce filtre d'intention dans votre manifeste, à l'intérieur de l'une de vos balises d'activité. Lorsque vous cliquez sur la notification, elle ouvrira l'application et ira directement à l'activité que vous avez définie dans click_action, dans ce cas "OPEN_ACTIVTY_1". Et dans cette activité, vous pouvez obtenir les données par :

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

J'utilise FCM pour mon application Android et j'utilise les deux charges utiles. Voici l'exemple JSON que j'utilise :

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

0 votes

"Mettez ce filtre d'intention dans votre manifeste, à l'intérieur de la balise d'application." Vous ne pouvez pas mettre le filtre d'intention à l'intérieur de la balise d'application.

0 votes

Votre JSON ne montre pas où va la clé click_action.

0 votes

Ce n'est pas la bonne réponse ? qu'est-ce que l'action de clic et où va-t-elle ? quelqu'un devrait voter moins ou nettoyer ceci

38voto

Shubhank Points 11083

Selon docs

Traiter les messages dans une application en arrière-plan

Lorsque votre application est en arrière-plan, Android dirige la notification dans la barre d'état système. Si l'utilisateur appuie sur la notification, le lanceur d'applications par défaut.

Cela inclut les messages qui contiennent à la fois une notification et des données données. Dans ce cas, la notification est envoyée dans la barre d'état système de l'appareil. de l'appareil et les données utiles sont livrées dans les extras de l'activité de lancement. de votre lanceur Activity.

Si vous souhaitez ouvrir votre application et effectuer une action spécifique, définissez les paramètres suivants click_action dans les données utiles de la notification et mappez-la à un filtre d'intention dans le système Actif. dans l'activité que vous souhaitez lancer. Par exemple, définissez click_action à OPEN_ACTIVITY_1 pour déclencher un filtre d'intention du type suivant suivant :

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

Edit :

Sur cette base filetage :

Vous ne pouvez pas définir la charge utile click_action en utilisant la console Firebase. Vous pouvez essayer de tester avec une commande curl ou un serveur http personnalisé.

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

1 votes

Vous avez raison. j'ai lu la docs. mais je ne sais pas où mettre cela dans mon manifeste ? je dois exécuter le code sur le onMessageReceived sur ce fichier java donc pour cela que dois-je faire monsieur ?

0 votes

Vous ne pouvez pas faire en sorte que l'application appelle automatiquement onMessageReveiced lorsqu'elle est en arrière-plan. Vous devez plutôt gérer l'intention reçue et faire en sorte que le gestionnaire l'appelle. Ou probablement, il est préférable d'implémenter une classe/méthode séparée qui est appelée à la fois par onMessageReveiced et par votre gestionnaire d'intention. J'ai ajouté le gestionnaire à onNewIntent de l'activité principale et cela fonctionne bien pour moi.

0 votes

Il est trop tard pour répondre aux questions de @Parath Patel mais peut-être que cela aidera quelqu'un d'autre avec les mêmes problèmes, jetez un coup d'œil à ma réponse ici. stackoverflow.com/a/42279260/2734021

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X