web-dev-qa-db-fra.com

Comment gérer les notifications avec FCM lorsque l'application est à l'avant-plan ou à l'arrière-plan

J'ai utilisé firebase pour construire mon projet.
Il utilisera également le message FCM (Firebase Cloud Message).
Mais il y a un problème.
Je ne peux pas gérer le FCM (créer ma notification personnalisée) lorsque l'application est en arrière-plan.

Le tutoriel du site officiel dit que 
cas 1: Avant-plan de l'application -> remplacer le "onMessageReceived ()" pour créer votre notification personnalisée. 
cas 2: Fond de l'application -> Le système créera la notification directement. Nous n'avons pas besoin et ne pouvons rien faire. Parce que cela ne déclenche pas le "onMessageReceived ()" dans ce cas.

Toutefois, si je ne peux rien faire lorsque l'application est en arrière-plan, je ne peux pas créer ma notification personnalisée. (Par exemple, après que les utilisateurs cliquent sur la notification, une fenêtre apparaîtra pour afficher des informations détaillées.)

Alors, comment gérer les notifications avec FCM lorsque l'application est en arrière-plan?

4
Leon Chang

Il y a une mauvaise nouvelle.
Google modifie le code source de Firebase dans la version "com.google.firebase: firebase-messaging: 11.6.0".
handelIntent est maintenant une "méthode de suppression finale publique". ce qui signifie que nous ne pouvons pas le remplacer.
Si vous souhaitez utiliser la solution, remplacez la version par "com.google.firebase: firebase-messaging: 11.4.2"



Essaie ma voie. Il peut parfaitement fonctionner sur la version de construction du projet est Android 6.0 ci-dessus (api niveau 23) et je l’ai déjà essayé.

Il existe un meilleur moyen que tutoriel du site officiel

Le site officiel a déclaré que la notification sera créée par le système lorsque l'application est en arrière-plan. Donc, vous ne pouvez pas le gérer en remplaçant "onMessageReceived ()". Parce que "onMessageReceived ()" n'est déclenché que lorsque l'application est au premier plan .

Mais la vérité n'est pas. En fait, les notifications (lorsque l'application est en arrière-plan) sont créées par Firebase Library.

Après avoir tracé le code de la bibliothèque de base de feu. Je trouve un meilleur moyen.

Étape 1. Remplacez le "handleIntent ()" au lieu de "onMessageReceived ()" dans FirebaseMessagingService.
Pourquoi:
Parce que la méthode sera déclenchée, l'application est au premier plan ou à l'arrière-plan. Nous pouvons donc gérer le message FCM et créer nos notifications personnalisées dans les deux cas.

@Override
public void handleIntent(Intent intent) {
    Log.d( "FCM", "handleIntent ");
}


Étape 2. Analyser le message du FCM
Comment:
Si vous ne connaissez pas le format du message que vous avez défini. Imprimez-le et essayez de l'analyser.
Voici l'illustration de base

Bundle bundle = intent.getExtras();
if (bundle != null) {
    for (String key : bundle.keySet()) {
        Object value = bundle.get(key);
        Log.d("FCM", "Key: " + key + " Value: " + value);
    }
}


Étape 2. Supprimez les notifications créées par la bibliothèque Firebase lorsque l'application est en arrière-plan.
Pourquoi:
Nous pouvons créer notre notification personnalisée. Mais la notification créée par Firebase Library sera toujours là (en réalité, elle a été créée par "" super.handleIntent (intent) "". Vous trouverez une explication détaillée ci-dessous.). Ensuite, nous aurons deux notifcations. C'est plutôt bizarre. Nous devons donc supprimer la notification créée par Firebase Library.

comment (le niveau de construction du projet est Android 6.0 ci-dessus):
Reconnaître les notifications que nous voulons supprimer et obtenir les informaions. Et utilisez le "notificationManager.cancel ()" pour les supprimer.

private void removeFirebaseOrigianlNotificaitons() {

    //check notificationManager is available
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (notificationManager == null )
        return;

    //check api level for getActiveNotifications()
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        //if your Build version is less than Android 6.0
        //we can remove all notifications instead. 
        //notificationManager.cancelAll();
        return;
    }


    //check there are notifications
    StatusBarNotification[] activeNotifications = 
        notificationManager.getActiveNotifications();
    if (activeNotifications == null)
        return;

    //remove all notification created by library(super.handleIntent(intent))
    for (StatusBarNotification tmp : activeNotifications) {
        Log.d("FCM StatusBarNotification", 
            "StatusBarNotification tag/id: " + tmp.getTag() + " / " + tmp.getId());
        String tag = tmp.getTag();
        int id = tmp.getId();

        //trace the library source code, follow the rule to remove it.
        if (tag != null && tag.contains("FCM-Notification"))
            notificationManager.cancel(tag, id);
    }
}

Le tout mon exemple de code:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

private static int notificationCount=0;

@Override
public void handleIntent(Intent intent) {
    //add a log, and you'll see the method will be triggered all the time (both foreground and background).
    Log.d( "FCM", "handleIntent");

    //if you don't know the format of your FCM message,
    //just print it out, and you'll know how to parse it
    Bundle bundle = intent.getExtras();
    if (bundle != null) {
        for (String key : bundle.keySet()) {
            Object value = bundle.get(key);
            Log.d("FCM", "Key: " + key + " Value: " + value);
        }
    }

    //the background notification is created by super method
    //but you can't remove the super method. 
    //the super method do other things, not just creating the notification
    super.handleIntent(intent);

    //remove the Notificaitons
    removeFirebaseOrigianlNotificaitons();

    if (bundle ==null)
        return;

    //pares the message
    CloudMsg cloudMsg = parseCloudMsg(bundle);

    //if you want take the data to Activity, set it
    Bundle myBundle = new Bundle();
    myBundle.putSerializable(TYPE_FCM_PLATFORM, cloudMsg);
    Intent myIntent = new Intent(this, NotificationActivity.class);
    myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    myIntent.putExtras(myBundle);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationCount, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    //set the Notification
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.icon)
            .setContentTitle(cloudMsg.getTitle())
            .setContentText(cloudMsg.getMessage())
            .setAutoCancel(true)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(notificationCount++, notificationBuilder.build());
}



/**
 * parse the message which is from FCM
 * @param bundle
 */
private CloudMsg parseCloudMsg(Bundle bundle) {
    String title = null, msg=null;

    //if the message is sent from Firebase platform, the key will be that
    msg = (String) bundle.get("gcm.notification.body");

    if(bundle.containsKey("gcm.notification.title"))
    title = (String) bundle.get("gcm.notification.title");

    //parse your custom message
    String testValue=null;
    testValue =  (String) bundle.get("testKey");

    //package them into a object(CloudMsg is your own structure), it is easy to send to Activity.
    CloudMsg cloudMsg = new CloudMsg(title, msg, testValue);
    return cloudMsg;
}


/**
 * remove the notification created by "super.handleIntent(intent)"
 */
    private void removeFirebaseOrigianlNotificaitons() {

    //check notificationManager is available
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (notificationManager == null )
        return;

    //check api level for getActiveNotifications()
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        //if your Build version is less than Android 6.0
        //we can remove all notifications instead. 
        //notificationManager.cancelAll();
        return;
     }

    //check there are notifications
    StatusBarNotification[] activeNotifications = 
        notificationManager.getActiveNotifications();
    if (activeNotifications == null)
        return;

    //remove all notification created by library(super.handleIntent(intent))
    for (StatusBarNotification tmp : activeNotifications) {
        Log.d("FCM StatusBarNotification", 
            "tag/id: " + tmp.getTag() + " / " + tmp.getId());
        String tag = tmp.getTag();
        int id = tmp.getId();

        //trace the library source code, follow the rule to remove it.
        if (tag != null && tag.contains("FCM-Notification"))
            notificationManager.cancel(tag, id);
    }
}
}
7
Leon Chang

Toutefois, si je ne peux rien faire lorsque l'application est en arrière-plan, je ne peux pas créer ma notification personnalisée. (Par exemple, après que les utilisateurs cliquent sur la notification, une fenêtre apparaîtra pour afficher des informations détaillées.)

Alors, comment gérer les notifications avec FCM lorsque l'application est en arrière-plan?

Tout d’abord, vous devez créer la charge utile de messages correcte que vous envoyez au serveur fcm. Exemple:

{
  "to": "topic_name",
  "priority": "high",
  "data": {
    "field1": "field1 value" 
    "field2": "field2 value" 
  }

  "notification" : {
      "body" : "Lorem ipsum",
      "title" : "sampke title" 
      "click_action": "SHOW_DETAILS" 
    }
}

La charge data correspond aux données réelles que vous souhaitez afficher en tant que détails du message une fois que l'utilisateur a cliqué sur la notification. La charge notification représente l'apparence que devrait avoir la notification générée (il y a beaucoup plus d'attributs possibles à définir), vous n'avez pas besoin de créer la notification vous-même. besoin de définir les propriétés ici.

Pour afficher votre activité après que l'utilisateur ait appuyé sur la notification, vous devez définir un filtre d'intention correspondant à click_action:

<intent-filter>
     <action Android:name="SHOW_DETAILS"/>
     <category Android:name="Android.intent.category.DEFAULT"/>
 </intent-filter>

ainsi, les activités dont le filtre d'intention est supérieur seront lancées automatiquement lorsque l'utilisateur appuiera sur notification . La dernière étape consiste à extraire les données lorsque l'activité est lancée après avoir cliqué sur Notification. C'est assez facile. Les données personnalisées sont transmises à l'activité via bundle. Dans la méthode onCreate de votre activité, procédez comme suit:

Bundle bundle = getIntent().getExtras();
if(bundle.getString("action").equals("SHOW_DETAILS")) /*This indicates activity is launched from notification, not directly*/
{
 //Data retrieved from notification payload send 
 String filed1 = bundle.getString("field1");
 String filed2 = bundle.getString("field2");
}

Tout ce qui précède est valable si l'application n'est pas en cours d'exécution ou si elle est en arrière-plan. Si votre application est au premier plan, aucune notification ne sera créée. Au lieu de cela, vous recevrez un événement onMessageReceived() afin que vous puissiez gérer les mêmes données ici (je suppose que vous savez comment). 

Référence:

https://firebase.google.com/docs/cloud-messaging/http-server-refhttps://github.com/firebase/quickstart-Android/tree/master/messaging

1
user1209216

Vous devez utiliser les messages de données FCM afin de créer une notification personnalisée dans une application Android. Même si votre application est en arrière-plan, onMessageReceived sera appelé afin que vous puissiez traiter les données et afficher la notification personnalisée.

https://firebase.google.com/docs/cloud-messaging/Android/receive

Format du message de données à envoyer du serveur:

{"message":{
"token":"Your Device Token",
"data":{
  "Nick" : "Mario",
  "body" : "great match!",
  "Room" : "PortugalVSDenmark"
}
}
}
1
Rajesh.k

FCM n'enverra pas de notification d'arrière-plan si votre application est supprimée et, comme vous l'avez décrit dans votre réponse à propos de la solution handleIntent(), elle peut fonctionner pour certains appareils et pour une ancienne version. de la FCM, également si vous utilisez la méthode @override qui n’est pas décrite dans la documentation officielle de firebase, vous risquez de rencontrer quelques problèmes ici, et vous l’utilisez sur votre risque propre !.

Quelle est la solution?

Vous devez utiliser votre propre service de notification Push à côté de FCM, comme Telegram.

OU en utilisant SYNCADAPTER à côté de GCM comme Gmail.

Donc, si vous en avez besoin pour fonctionner correctement avec ces applications, vous devez utiliser votre propre piratage.

0
user6490462