Firebase FCM notifications sur l'action de la charge utile

j'essaie d'ouvrir une activité particulière lorsque l'utilisateur clique sur la notification lorsque l'application est à l'arrière-plan. D'après les Docs, j'ai que click_action 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 Travail Autour de trop. Merci à l'Avance.

41
demandé sur AL. 2016-05-24 10:47:12

9 réponses

si votre application est en arrière-plan, Firebase ne se déclenchera pas onMessageReceived(). Pourquoi.....? Je n'ai aucune idée. Dans cette situation, Je ne vois pas l'intérêt de mettre en œuvre FirebaseMessagingService.

selon docs, si vous voulez traiter l'arrivée du message d'arrière-plan, vous devez envoyer 'click_action' avec votre message. Mais ce n'est pas possible si vous envoyez un message depuis la console Firebase, uniquement via L'API Firebase. Cela signifie que vous devrez construire votre propre "console" afin de permettre la commercialisation de gens à l'utiliser. Donc, cela rend 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!

45
répondu Bozic Nebojsa 2017-06-27 15:39:29

autant que je puisse dire, à ce point il n'est pas possible de définir click_action dans la console.

bien que ce ne soit pas une réponse stricte à la question de savoir comment obtenir le paramètre click_action 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 click_action mapping. Il nécessite un filtre d'intention comme celui spécifié dans le FCM docs:

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

Cela fait aussi utilisation de sujets pour définir le public. Pour que cela fonctionne, vous devez vous abonner à un sujet appelé "news".

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 les API FCM.

Aussi, gardez à l'esprit, cela ne fonctionnera que si l'application est en arrière-plan. S'il est au premier plan, vous devrez implémenter une extension de FirebaseMessagingService. Dans le une fois la méthode reçue, vous devrez naviguer manuellement vers 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, à ce moment je ne peux pas trouver un moyen d'accéder aux propriétés de notification de charge utile par la console, mais j'ai pensé que ce travail pourrait être utile.

43
répondu maddesa 2016-05-30 18:15:53

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

Content-Type: application/json Autorisation: key=YOUR_PERSONAL_FIREBASE_WEB_API_KEY

et un message json dans le champ"charge brute".

attention, si il y a le champ "notification" dans votre json, votre message ne sera jamais reçu lors de l'application en arrière-plan dans onMessageReceived(), même si il y a un champ de données ! Par exemple, faire cela, le travail de message juste si app en 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");
        }
      }
    }
}

Profitez-en !

21
répondu Maxime Ancelin 2016-09-27 10:44:31

il s'agit d'une catégorie de contournement, contenant également des informations supplémentaires:

étant donné que les notifications sont traitées différemment selon l'état de l'application (premier plan/arrière-plan/Non lancé), j'ai vu la meilleure façon de mettre en œuvre une classe helper où l'activité sélectionnée est lancée sur la base des données personnalisées envoyées dans le message de notification.

  • lorsque l'application est à l'avant-plan, utilisez la classe helper dans la catégorie onMessageReceived
  • lorsque l'application est en arrière-plan, utilisez la classe helper pour traiter l'intention dans l'onNewIntent de l'activité principale (vérifiez les données spécifiques sur mesure)
  • lorsque l'application n'est pas en cours d'exécution, utilisez la classe helper pour gérer l'intention dans l'onCreate de l'activité principale (appelez getIntent pour l'intention).

de cette façon, vous n'avez pas besoin du filtre click_action ou intention spécifique. Aussi vous écrivez le code juste une fois et peut raisonnablement facilement commencer toute activité.

ainsi les données personnalisées minimales ressembleraient quelque chose comme ceci:

Key: run_activity
Value: com.mypackage.myactivity

et le code de manipulation:

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-à-dire le code pour les deux derniers cas, l'activitédépart serait appelée aussi de onmessagereception (premier cas).

la limitation est que toutes les données dans les extras d'intention sont des chaînes, donc vous pouvez avoir besoin de gérer cela d'une manière ou d'une autre dans le l'activité elle-même. En outre, cela est simplifié, vous ne savez probablement pas quoi changer L'activité/Vue sur une application qui est au premier plan sans prévenir votre utilisateur.

13
répondu diidu 2016-10-31 07:57:10

Ceci est clair d'après firebase docs que votre onMessageReceived ne fonctionnera pas quand app est en arrière-plan.

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

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

et dans votre android.manifest fichier

ajouter 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>
11
répondu gagan bhutani 2016-12-17 07:18:44

si votre application est en arrière-plan, Firebase ne déclenchera pas onMessageReceived(). onMessageReceived () est appelé quand app est en premier plan . Quand app est en arrière-plan, la méthode onMessageReceived () ne sera appelée que si le corps de https://fcm.googleapis.com/fcm/send contain only data payload.Ici, je viens de créer une méthode pour construire notification personnalisée avec l'intention d'ur votre activité requise . et a appelé cette méthode dans onMessageRecevied() .

En Facteur:

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

en-tête: autorisation: clé=ur clé

corps - - - > >

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

    },

  "to" : "xxxxxxxxx"

}

dans votre demande.

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 utile de données arrive au mobile, alors la méthode onMessageReceived() sera appelée.. dans cette méthode ,je viens de faire une notification personnalisée. cela fonctionnera même si ur app l'arrière-plan ou au premier plan.

4
répondu chandan raj 2016-12-14 07:39:33

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.


alors j'ai essayé de le faire dans la Console de notification Firebase sans succès. Comme je ne trouve nulle part où placer la valeur click_action dans la console, ce que j'ai principalement fait pour tester ceci est d'ajouter une paire clé/valeur personnalisée dans la Notification (Options Avancées > Données Personnalisées):

Key: click_action
Value: <your_preferred_value>

a alors essayé D'appeler RemoteMessage.getNotification ().getClickAction () dans onMessageReceived() pour voir si elle récupérait la bonne valeur, mais elle renvoie toujours null . Ensuite j'ai essayé D'appeler RemoteMessage.getData ().get(< specified_key >) et a été en mesure de récupérer la valeur ai-je ajouté.

NOTE : Je ne suis pas tout à fait sûr si cela peut être utilisé comme solution de contournement, ou si cela va à l'encontre des meilleures pratiques. Je suggère d'utiliser votre propre serveur d'app, mais votre message est spécifique à la Console Firebase.

La façon dont l'application cliente et la notification se comporte dépend toujours de la façon dont vous programme. Cela dit, je pense que vous pouvez utiliser ce qui précède comme une solution de rechange, en utilisant la valeur extraite du getData() , puis avoir la Notification appeler ceci ou cela. Espérons que cela aide en quelque sorte. Acclamations! : D

2
répondu AL. 2016-11-09 01:52:38

maintenant il est possible de définir click_action dans la Console Firebase. Vous allez juste à notifications-send message - option avancée et là vous aurez deux champs pour la clé et la valeur. Dans le premier champ vous mettez click_action et dans le second vous mettez un texte qui représente la valeur de cette action. Et vous ajoutez intention-filtre dans votre manifeste et lui donner la même valeur que vous avez écrit dans la console. Et c'est une simulation d'action réelle.

1
répondu Atenica 2016-07-05 13:32:59

je regarde cette base de données Firebase is, développement à partir de Google cloud messaging push notification fundamental afin que nous puissions utiliser le tutoriel gcm, la fonction et la mise en œuvre dans firebase , j'utilise la fonction de notification push GCM pour résoudre ce problème click_action j'utilise la fonction gcm **

'notificationclick '

** essayez cette sauvegarde url click_action dans la variable url c'est dans server-travailleur.js

var url =  "";

messaging.setBackgroundMessageHandler(function(payload) {

  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  url = payload.data.click_action;

  const notificationTitle = payload.data.title;
  const notificationOptions = {
    body: payload.data.body , 
    icon: 'firebase-logo.png'
  };

  return self.registration.showNotification(notificationTitle,
      notificationOptions);

});


   //i got this in google cloud messaging push notification


self.addEventListener('notificationclick', function (event) {
  event.notification.close();

  var clickResponsePromise = Promise.resolve();
    clickResponsePromise = clients.openWindow(url);

  event.waitUntil(Promise.all([clickResponsePromise, self.analytics.trackEvent('notification-click')]));
});
-2
répondu Odin Wages 2016-11-04 09:28:49