添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Firebase FCM通知的click_action有效载荷

73 人关注

我试图在应用程序处于后台时,当用户点击通知时打开一个特定的活动。从文档中,我了解到click_action必须被添加到payload和App中的intent filter来处理。但是,如何通过Firebase控制台在Firebase通知中添加click_action?我也愿意接受任何其他的工作方法。

android
firebase-cloud-messaging
android-notifications
Hariharan B
Hariharan B
发布于 2016-05-24
13 个回答
Bozic Nebojsa
Bozic Nebojsa
发布于 2016-11-02
已采纳
0 人赞同

如果你的应用程序是在后台,Firebase将不会触发onMessageReceived()。为什么.....?我也不知道。在这种情况下,我觉得实现FirebaseMessagingService没有任何意义。

根据文档,如果你想处理后台消息的到来,你必须在消息中发送 "click_action"。 但是如果你从Firebase控制台发送消息,这是不可能的,只能通过Firebase API。 这意味着你必须建立你自己的 "控制台",以使营销人员能够使用它。所以,这使得Firebase控制台也变得非常无用。

这个新工具背后有一个非常好的、有前途的想法,但执行得很糟糕。

我想我们将不得不等待新的版本和改进/修复!

希望Firebase通知很快就能获得Payload功能,否则就像你说的那样,转到Firebase控制台是没有用的。
使用类似@diidu的方法来实现。谢谢大家的回答。
在服务器端推送的情况下,我们如何处理这个有效载荷?
@Bozic Nebojsa 有时我无法得到意向性的额外费用。
在后台接收消息的方法是使用 "数据 "消息,而不是其 "通知 "消息。通过使用 "数据 "消息,即使你的应用程序在后台,onMessageReceived方法也会被调用(在安卓客户端)。详见这里 firebase.google.com/docs/cloud-messaging/... .click_action不是用来设置在后台发生的事情,而是当应用程序从通知中启动时,哪个Intent过滤器处理这个意图。
maddesa
maddesa
发布于 2016-11-02
0 人赞同

就我所知,在这一点上,不可能在控制台设置click_action。

虽然没有严格回答如何在控制台获得click_action的设置,但你可以使用curl作为替代。

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

这是测试click_action映射的一个简单方法。 它需要一个类似FCM文档中指定的意图过滤器。

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

这也是利用话题来设置受众。为了使其发挥作用,你将需要订阅一个名为 "新闻 "的主题。

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

即使需要几个小时才能在控制台看到一个新创建的主题,你仍然可以通过FCM apis向它发送信息。

另外,请记住,这只在应用程序处于后台的情况下才会起作用。 如果是在前台,你将需要实现FirebaseMessagingService的扩展。 在onMessageReceived方法中,你将需要手动导航到你的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

正如我所说,目前我找不到通过控制台访问通知有效载荷属性的方法,但我认为这个工作方法可能会有帮助。

目前,不可能通过控制台设置通知的有效载荷属性。如果这对你很重要,请写信给Firebase支持部门。 firebase.google.com/support/contact/bugs-features
@Diego Giorgini 向Firebase提交了一个功能请求。谢谢你的链接。
替换代码0- 是否可以有一个通配符。例如,所有以 "my_firebase_event_"开头的信息都有资格成为我的启动器意图。
+1 解释了关于 intent-filter 设置与 action category 的工作 click_action 。这对我帮助很大。
Maxime Ancelin
Maxime Ancelin
发布于 2016-11-02
0 人赞同

你可以在扩展FirebaseMessagingService的服务中的onMessageReceived()函数中处理你的消息的所有动作。 为了做到这一点,你必须发送一个完全包含数据的消息,例如,使用 Chrome中的高级REST客户端 . 然后你发送一个POST到 https://fcm.googleapis.com/fcm/send 在 "原始头文件 "中使用。

Content-Type: application/json 授权: key=YOUR_PERSONAL_FIREBASE_WEB_API_KEY

而在 "Raw payload "字段里有一个json信息。

警告,如果你的json中存在 "notification "字段,当应用程序在后台的onMessageReceived()中,即使有一个数据字段,你的消息也不会被接收到! 例如,这样做,如果应用程序在前台,信息就会工作。

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

为了在onMessageReceived()的所有情况下都能收到你的消息,只需从你的json中删除 "notification "字段即可 !

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

而在你的FirebaseMessagingService .NET中,你可以看到,在你的网站上,你可以看到,在你的网站上,你可以看到。

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");

Enjoy !

这应该是公认的答案,onMessageReceived在前台和后台都被调用。谢谢!
DJphy
将该应用程序从Recents中删除,没有回调,我们也不会在系统托盘上收到通知。
你救了我的命。这些答案都没有这个解释得好,干得好。
如果你只用FCM向安卓设备发送,这个方法很有效。如果你使用FCM同时针对安卓和iOS,你会发现这种技术会破坏iOS。
是的!@ChrisSobolewski.我也面临同样的问题。不幸的是,确保它在Android和iOS上完美运行的唯一方法是为iOS发送一个既有数据又有正文的推送通知,为Android发送一个只有数据的通知。这在传统的Firebase API中是很难实现的,因为我们需要根据操作系统来区分和发送不同的有效载荷。然而,使用新的Firebase HTTP v1 API,这就容易多了。
diidu
diidu
发布于 2016-11-02
0 人赞同

这属于解决方法的范畴,也包含一些额外的信息。

由于通知根据应用程序的状态(前台/后台/未启动)进行不同的处理,我看到最好的方法是实现一个辅助类,根据通知消息中发送的自定义数据启动选定的活动。

  • when the app is on foreground use the helper class in onMessageReceived
  • when the app is on background use the helper class for handling the intent in main activity's onNewIntent (check for specific custom data)
  • when the app is not running use the helper class for handling the intent in main activity's onCreate (call getIntent for the intent).
  • 这样,你就不需要特定的click_action或intent过滤器。另外,你只需写一次代码,就可以合理地轻松启动任何活动。

    因此,最小的自定义数据将看起来像这样。

    Key: run_activity
    Value: com.mypackage.myactivity
    

    以及处理它的代码。

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

    这就是后两种情况的代码,startSelectedActivity也会从onMessageReceived(第一种情况)中调用。

    限制是intent extras中的所有数据都是字符串,所以你可能需要在活动本身中以某种方式处理这些数据。另外,这是简化的,你可能不需要在不警告用户的情况下改变前台的应用程序的活动/视图。

    Tar
    我不明白第3项中的句子。" when the app is not launched use the helper class for handling the intent in main activity's onCreate (call getIntent for the intent). "。我的意思是,如果应用程序不活跃,你怎么能回应它?
    意图将启动应用程序,onCreate被调用。也许它应该说 "当应用程序未运行时"。改变了它。
    请注意,在你的版本中启用Proguard后,类的名称将被混淆。因此,最好是使用关键活动映射。即: if (className == "someName") { lunchSomeActivity() }
    gagan bhutani
    gagan bhutani
    发布于 2016-11-02
    0 人赞同

    从Firebase的文档中可以看出,当应用程序在后台时,你的 onMessageReceived 将无法工作。

    当你的应用程序在后台,点击你的通知,你的默认启动器将被启动。 为了启动你想要的活动,你需要在你的通知有效载荷中指定 click_action

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

    并在你的android.manifest文件中

    在你注册活动的地方添加以下代码

         <activity
                    android:name="your activity name">
                    <intent-filter>
                        <action android:name="your activity name" />
                       <category android:name="android.intent.category.DEFAULT"/>
                   </intent-filter>
       </activity>
        
    现在,当我点击推送通知时,我可以打开我的应用程序,一个默认页面被打开。但现在我想在点击推送通知时打开一个特定的页面。 请看我的问题 stackoverflow.com/questions/44797486/...
    你可以随心所欲地命名你的行动,不需要是你的活动名称。
    这不是一个活动名称,而是意图过滤器中的行动名称。
    这很酷,但是,呃....,处理点击动作的实际代码在哪里?
    chandan raj
    chandan raj
    发布于 2016-11-02
    0 人赞同

    如果你的应用程序在后台,Firebase将不会触发onMessageReceived()。 onMessageReceived()在应用程序处于前台时被调用。 当应用程序处于后台时,onMessageReceived()方法将被调用,只有当应用程序的主体是 https://fcm.googleapis.com/fcm/send 在这里,我只是创建了一个方法来建立自定义的通知与意图有你所需要的活动。

    在PostMan。

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

    header:Authorization:key=ur key

    body --->>

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

    在你的应用程序中。

    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());
    

    当数据载荷到达手机时,onMessageReceived()方法将被调用。在该方法中,我只是做了一个自定义的通知。这将工作,即使你的应用程序是后台或前台。

    AL.
    AL.
    发布于 2016-11-02
    0 人赞同

    所以只是为了验证,目前不可能通过Firebase控制台设置 click_action 参数。

    So I've been trying to do this in the Firebase Notifications Console with no luck. Since I can't seem to find anywhere to place the click_action value in the console, what I mainly did to test this out is to add a custom key/value pair in the Notification (Advance Options > Custom Data):

    Key: click_action
    Value: <your_preferred_value>
    

    然后尝试调用RemoteMessage.getNotification().getClickAction()中的onMessageReceived(),看看它是否检索到了正确的值,但它总是返回null。所以接下来我试着调用RemoteMessage.getData().get(< specified_key >)并能够检索到我添加的值。

    NOTE:我不完全确定这是否可以作为一种变通方法,或者是否违反了最佳实践。我建议使用你自己的应用服务器,但你的帖子是针对Firebase控制台的。

    客户端应用程序和通知的行为方式仍然取决于你如何编程。说到这里,我想你可以用上面的方法作为一种变通,使用从getData()中获取的值,然后让通知书调用这个或那个。希望这对你有一些帮助。干杯!:D

    @McAwesomeville 谢谢你的回答。当应用程序处于后台时,Firebase通知没有调用onMessageReceived()。我已经按照你说的实现了,在OnMessageReceived()中调用RemoteMessage.getData(),然后调用目标Intent来处理前台状态。而在启动器活动中的getIntent().getExtras()则是为了处理目前的背景状态。我不确定这是否是一个最佳做法。欢迎任何其他建议。也许我必须设置我自己的应用程序服务器 :(
    AL.
    关于你的 onMessageReceived() 在后台不被调用的问题,你是否尝试过将通知的优先级设置为高?请在你自己的应用服务器上试一下,让我知道它是否有效。谢谢!:)
    没有。onMessageReceived()没有被调用。我正在尝试实现App Server Now...
    @AL.:使用Firebase控制台无法做到这一点。用Postman代替(Chrome扩展)。而且要记住: click_action 需要定位在 notification 。例子。 "notification": { "title" : "New follower!", "body": "{name} is following you", "sound": "default", "click_action" : "FollowActivity" }
    AL.
    @TranDucHuy 谢谢你的评论。我已经知道 click_action 的参数不能通过Firebase控制台设置。谢谢你的提醒,我将更新我的答案,并将其纳入其中。干杯!:)
    Atenica
    Atenica
    发布于 2016-11-02
    0 人赞同

    现在可以在Firebase控制台设置click_action了。你只需要进入通知-发送消息-高级选项,在那里你会有两个字段,分别是key和value。在第一个字段中,你要写上click_action,在第二个字段中,你要写上一些代表该动作值的文本。然后你在你的Manifest中添加intent-filter,并给他与你在控制台中写的一样的值。 这就是对真实的click_action的模拟。

    Groovee60
    听起来你肯定知道怎么做。但两端的实际例子会更有帮助......
    AL.
    这和我的答案基本相同。但我想说的是,就目前而言,没有办法通过Firebase控制台设置 click_action 参数。替换代码0】的参数应该是在通知的有效载荷中。预先选项中的可选键值对是为数据有效载荷准备的。
    Robert Benyi
    Robert Benyi
    发布于 2016-11-02
    0 人赞同

    在Web中,只需添加你想打开的网址。

    "condition": "'test-topic' in topics || 'test-topic-2' in topics", "notification": { "title": "FCM Message with condition and link", "body": "This is a Firebase Cloud Messaging Topic Message!", "click_action": "https://yoururl.here"
    我如何将其发送到特定的设备上,因为这是要发送给所有的用户?
    @RonakShethia使用FCM注册令牌。
    إياد الفواز
    إياد الفواز
    发布于 2016-11-02
    0 人赞同

    FCM有两种方法 fcm消息通知和应用程序通知 在第一种情况下,你的应用程序只收到带有正文和标题的消息通知,你可以添加颜色,振动不工作,声音默认。 在第二种情况下,你可以完全控制当你收到信息时发生的事情。 替换代码0 你会收到带有(你的钥匙)的数据。 但这不是来自FCM信息 而是来自FCM的云功能

    pavithra ramasamy
    pavithra ramasamy
    发布于 2016-11-02
    0 人赞同

    一个简单的解决方法是,在fcm选项中--添加 / 作为链接值,后台通知点击将被重定向到应用程序。

    这应该是一个评论。
    Stones
    Stones
    发布于 2016-11-02
    0 人赞同

    比方说,我想导航到 www.aaa.com/news/post/41

    在你的通知键上添加 "click_action":"/news/post/41" 。 比如说

    "notification":{
        "title":"   Greetings",
        "body":"This is okay",
        "click_action":"/news/post/41"
    

    它甚至在后台工作。如果你有一个PWA应用,它也能工作;我没有在iOS或本地Android应用中测试过。

    Odin Wages
    Odin Wages
    发布于 2016-11-02
    0 人赞同

    我在看这个Firebase是,发展从 谷歌云信息推送通知的根本 所以我们可以使用gcm的教程,功能和在Firebase中的实现。 我使用gcm推送通知函数的功能来解决这个点击_动作的问题 我使用gcm函数**

    'notificationclick'

    试试这个保存网址 点击_动作 在变量中 url this is in server-worker.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();