web-dev-qa-db-fra.com

Notifications FCM Firebase click_action, charge utile

J'essaie d'ouvrir une activité particulière lorsque l'utilisateur clique sur la notification lorsque l'application est en arrière-plan. D'après les documents, j'ai click_action qui doit être ajouté dans la charge utile et un filtre d'intention dans l'application pour le gérer. Mais comment ajouter click_action dans les notifications Firebase via la console Firebase? Je suis ouvert à tout autre Work Around. Merci d'avance.

45
Hariharan B

Si votre application est en arrière-plan, Firebase ne déclenchera pas onMessageReceived (). Pourquoi.....? Je n'ai aucune idée. Dans cette situation, je ne vois aucun intérêt à implémenter FirebaseMessagingService.

Selon la documentation, si vous souhaitez traiter l'arrivée du message en arrière-plan, vous devez envoyer "click_action" avec votre message. Mais ce n'est pas possible si vous envoyez un message à partir de la console Firebase, uniquement via l'API Firebase. Cela signifie que vous devrez créer votre propre "console" afin de permettre aux professionnels du marketing de l'utiliser. Cela rend donc la console Firebase tout aussi inutile!

Il y a vraiment une bonne idée prometteuse derrière ce nouvel outil, mais mal exécuté.

Je suppose que nous devrons attendre de nouvelles versions et améliorations/corrections!

51
Bozic Nebojsa

Autant que je sache, il n’est pas possible à présent de définir click_action dans la console.

Bien que ce ne soit pas une réponse stricte à la façon d'obtenir le click_action défini dans la console, vous pouvez utiliser curl comme alternative:

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

C'est un moyen facile de tester le mappage click_action. Il nécessite un filtre d'intention similaire à celui spécifié dans la documentation FCM:

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

Cela utilise également des sujets pour définir le public. Pour que cela fonctionne, vous devez vous abonner à un sujet appelé "nouvelles".

FirebaseMessaging.getInstance().subscribeToTopic("news");

Même s'il faut plusieurs heures pour voir un sujet nouvellement créé dans la console, vous pouvez toujours lui envoyer des messages via l'API FCM.

Aussi, gardez à l'esprit, cela ne fonctionnera que si l'application est en arrière-plan. Si c'est au premier plan, vous devrez implémenter une extension de FirebaseMessagingService. Dans la méthode onMessageReceived, vous devez accéder manuellement à votre cible click_action:

    @Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    //This will give you the topic string from curl request (/topics/news)
    Log.d(TAG, "From: " + remoteMessage.getFrom());
    //This will give you the Text property in the curl request(Sample Message): 
    Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
    //This is where you get your click_action 
    Log.d(TAG, "Notification Click Action: " + remoteMessage.getNotification().getClickAction());
    //put code here to navigate based on click_action
}

Comme je l'ai dit, pour le moment, je ne trouve aucun moyen d'accéder aux propriétés de charge de notification via la console, mais je pensais que cette solution pourrait être utile.

49
maddesa

Vous pouvez gérer toutes vos actions en fonction de votre message dans onMessageReceived () dans votre service qui étend FirebaseMessagingService. Pour ce faire, vous devez envoyer un message contenant exclusivement des données, en utilisant par exemple client avancé REST dans Chrome . Ensuite, vous envoyez un POST à https://fcm.googleapis.com/fcm/send en utilisant "les en-têtes bruts":

Content-Type: application/json Autorisation: clé = YOUR_PERSONAL_FIREBASE_WEB_API_KEY

Et un message JSON dans le champ "Charge utile brute".

Attention, s'il y a le champ "notification" dans votre json, votre message ne sera jamais reçu quand une application en arrière-plan dans onMessageReceived (), même s'il y a un champ de données! Par exemple, pour ce faire, le message fonctionne uniquement si l'application est au premier plan:

{
    "condition": " 'Symulti' in topics || 'SymultiLite' in topics",
    "priority" : "normal",
    "time_to_live" : 0,
    "notification" : {
        "body" : "new Symulti update !",
        "title" : "new Symulti update !",
        "icon" : "ic_notif_symulti"
    },
    "data" : {
        "id" : 1,
        "text" : "new Symulti update !"
    }
}

Afin de recevoir votre message dans tous les cas dans onMessageReceived (), supprimez simplement le champ "notification" de votre json!

Exemple:

{
    "condition": " 'Symulti' in topics || 'SymultiLite' in topics",
    "priority" : "normal",
    "time_to_live" : 0,,
    "data" : {
        "id" : 1,
        "text" : "new Symulti update !",
        "link" : "href://www.symulti.com"
    }
}

et dans votre FirebaseMessagingService:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
      String message = "";
      obj = remoteMessage.getData().get("text");
      if (obj != null) {
        try {
          message = obj.toString();
        } catch (Exception e) {
          message = "";
          e.printStackTrace();
        }
      }

      String link = "";
      obj = remoteMessage.getData().get("link");
      if (obj != null) {
        try {
          link = (String) obj;
        } catch (Exception e) {
          link = "";
          e.printStackTrace();
        }
      }

      Intent intent;
      PendingIntent pendingIntent;
      if (link.equals("")) { // Simply run your activity
        intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      } else { // open a link
        String url = "";
        if (!link.equals("")) {
          intent = new Intent(Intent.ACTION_VIEW);
          intent.setData(Uri.parse(link));
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        }
      }
      pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
          PendingIntent.FLAG_ONE_SHOT);


      NotificationCompat.Builder notificationBuilder = null;

      try {
        notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_notif_symulti)          // don't need to pass icon with your message if it's already in your app !
            .setContentTitle(URLDecoder.decode(getString(R.string.app_name), "UTF-8"))
            .setContentText(URLDecoder.decode(message, "UTF-8"))
            .setAutoCancel(true)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setContentIntent(pendingIntent);
        } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
        }

        if (notificationBuilder != null) {
          NotificationManager notificationManager =
              (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
          notificationManager.notify(id, notificationBuilder.build());
        } else {
          Log.d(TAG, "error NotificationManager");
        }
      }
    }
}

Prendre plaisir !

25
Maxime Ancelin

Cela entre dans la catégorie des solutions de contournement, contenant quelques informations supplémentaires:

Étant donné que les notifications sont gérées différemment en fonction de l'état de l'application (avant-plan/arrière-plan/non lancé), j'ai trouvé le meilleur moyen d'implémenter une classe d'assistance dans laquelle l'activité sélectionnée est lancée en fonction des données personnalisées envoyées dans le message de notification.

  • lorsque l'application est au premier plan, utilisez la classe d'assistance dans onMessageReceived
  • lorsque l'application est en arrière-plan, utilisez la classe d'assistance pour gérer l'intention dans onNewIntent de l'activité principale (recherchez des données personnalisées spécifiques)
  • lorsque l'application n'est pas en cours d'exécution, utilisez la classe d'assistance pour gérer l'intention dans onCreate de l'activité principale (appelez getIntent pour l'intention).

De cette façon, vous n'avez pas besoin du filtre click_action ou intent spécifique. En outre, vous écrivez le code une seule fois et vous pouvez facilement démarrer n'importe quelle activité.

Ainsi, les données personnalisées minimales ressembleraient à ceci:

Key: run_activity
Value: com.mypackage.myactivity

Et le code pour le manipuler:

if (intent.hasExtra("run_activity")) {
    handleFirebaseNotificationIntent(intent);
}


private void handleFirebaseNotificationIntent(Intent intent){
    String className = intent.getStringExtra("run_activity");
    startSelectedActivity(className, intent.getExtras());
}

private void startSelectedActivity(String className, Bundle extras){
    Class cls;
    try {
        cls = Class.forName(className);
    }catch(ClassNotFoundException e){
        ...
    }
    Intent i = new Intent(context, cls);

    if (i != null) {
        i.putExtras(extras);
        this.startActivity(i);
    } 
}

C'est le code pour les deux derniers cas, startSelectedActivity serait également appelé à partir de onMessageReceived (premier cas).

La limitation est que toutes les données des extras d'intention sont des chaînes, vous devrez donc peut-être gérer cela d'une manière ou d'une autre dans l'activité elle-même. En outre, ceci est simplifié, vous n'avez probablement pas de quoi changer l'activité/vue sur une application qui est au premier plan sans prévenir votre utilisateur.

16
diidu

Eh bien, il est clair dans les documents firebase que votre onMessageReceived ne fonctionnera pas si l'application est en arrière-plan.

Lorsque votre application est en arrière-plan et que vous cliquez sur votre notification, votre lanceur par défaut sera lancé. Pour lancer l'activité souhaitée, vous devez spécifier click_action dans la charge de notification.

$noti = array
    (
    'icon' => 'new',
    'title' => 'title',
    'body' => 'new msg',
    'click_action' => 'your activity name comes here'
); 

Et dans votre fichier Android.manifest

Ajoutez le code suivant où vous avez enregistré votre activité

     <activity
                Android:name="your activity name">
                <intent-filter>
                    <action Android:name="your activity name" />
                   <category Android:name="Android.intent.category.DEFAULT"/>
               </intent-filter>
   </activity>
13
gagan bhutani

Si votre application est en arrière-plan, Firebase ne déclenchera pas onMessageReceived (). onMessageReceived () est appelé lorsque l'application est au premier plan. Lorsque l'application est en arrière-plan, la méthode onMessageReceived () n'est appelée que si le corps de https://fcm.googleapis.com/fcm/send ne contient que des données utiles. Ici, je viens de créer une méthode. pour créer une notification personnalisée avec l'intention d'avoir votre activité requise. et a appelé cette méthode dans onMessageRecevied ().

Dans PostMan:

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

en-tête: Autorisation: clé = clé

corps --- >>

{  "data" : {
      "Nick" : "Mario",
      "Room" : "PoSDenmark",

    },

  "to" : "xxxxxxxxx"

}

dans votre application.

class MyFirebaseMessagingService  extends FirebaseMessagingService {

 public void onMessageReceived(RemoteMessage remoteMessage) {
       if (remoteMessage.getData().size() > 0) {
           sendNotification("ur message body") ;
        }
    }
private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, Main2Activity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .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());
    }

 }

lorsque la charge de données arrive sur le mobile, la méthode onMessageReceived () sera appelée. Dans cette méthode, je viens de créer une notification personnalisée. cela fonctionnera même si votre application est à l'arrière-plan ou à l'avant-plan.

5
chandan raj

Mise à jour:

Donc, juste pour vérifier, il n’est pas actuellement possible de définir le paramètre click_action via la console Firebase.


J'ai donc essayé de le faire dans la console de notifications Firebase sans succès. Comme je n'arrive pas à trouver où placer la valeur click_action dans la console, je l'ai principalement testée pour ajouter une paire clé/valeur personnalisée dans la notification (Options avancées> Données personnalisées):

Key: click_action
Value: <your_preferred_value>

puis essayé d'appeler RemoteMessage.getNotification (). getClickAction () dans onMessageReceived() pour voir s'il récupérait la valeur correcte, mais renvoie toujours null. J'ai ensuite essayé d'appeler RemoteMessage.getData (). Get (<clé_clé>) et j'ai pu récupérer la valeur que j'ai ajoutée.

NOTE: Je ne suis pas tout à fait sûr de pouvoir utiliser cette solution de contournement ou si cela va à l'encontre des meilleures pratiques. Je suggérerais d'utiliser votre propre serveur d'applications, mais votre message est spécifique à la console Firebase.

Le comportement de l'application client et de la notification dépend toujours de la façon dont vous la programmez. Cela dit, je pense que vous pouvez utiliser ce qui précède comme solution de contournement, en utilisant la valeur extraite de la getData(), puis en demandant à Notification d’appeler ceci ou cela. J'espère que cela aide d'une certaine manière. À votre santé! :RÉ

3
AL.

Il est maintenant possible de définir click_action dans la console Firebase. Vous devez simplement aller à l'option notifications-send message-advanced et vous aurez deux champs pour la clé et la valeur. Dans le premier champ, vous mettez click_action et dans le second, du texte représentant la valeur de cette action. Et vous ajoutez un filtre d'intention dans votre manifeste et lui donnez la même valeur que celle que vous avez écrite dans la console. Et c'est la simulation de click_action réel.

1
Atenica