如何在前台和后台处理Firebase通知?

8

我希望在应用程序的前台和后台都能够处理 firebase 通知消息。开发者将发送一条包含 YouTube 链接的消息,当用户点击通知栏时,它必须直接打开链接。有谁知道这是如何完成的吗?

 public void onMessageReceived(RemoteMessage remoteMessage) {
    // [START_EXCLUDE]
    // There are two types of messages data messages and notification messages. Data messages are handled
    // here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
    // traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
    // is in the foreground. When the app is in the background an automatically generated notification is displayed.
    // When the user taps on the notification they are returned to the app. Messages containing both notification
    // and data payloads are treated as notification messages. The Firebase console always sends notification

    // [END_EXCLUDE]

    // TODO(developer): Handle FCM messages here.
    // Not getting messages here? See why this may be:
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    }

    // 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.
}

下一步该怎么做才能达到我的目标?提前感谢:)

发布的代码只是示例中的一个。所以我假设你已经看过它们了。有什么让你感到困惑的地方吗?你也看过文档了吗?现在,这就像一个“给我代码”的问题。 - AL.
尝试我的解决方案吗?<br> 我已经尝试过了。<br> 而且它有效。<br>https://dev59.com/36nka4cB1Zd3GeqPKjir#48899186 - Leon Chang
7个回答

5
你应该在 FCM 消息中发送数据负载。无论你的应用程序处于前台还是后台,在 on message 方法中都会接收到数据负载。在那里处理操作,例如始终通过读取数据负载来显示通知,或者如果你想在应用程序打开或在前台时显示警报对话框,则可以这样做。
以下是一个示例有效负载:
{
  "to": "registration_id_or_topic",
  "data": {
        "message": "This is a Firebase Cloud Messaging Topic Message!",
        "youtubeURL": "https://youtu.be/A1SDBIViRtE"
   }
}

然后,在您的onMessageReceived()方法中:

public void onMessageReceived(RemoteMessage remoteMessage) {
   if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        Map<String, String> receivedMap = remoteMessage.getData();
        String youtubeURL = receivedMap.get("youtubeURL");
        showNotificationWithURLAction(youtubeURL);
   }
   .....
}

您可以通过搜索“showNotificationWithURLAction(...)方法”轻松实现该功能。这里有一个示例链接

如何在负载中发送链接以及当用户单击时如何处理该链接?请帮忙。 - vishal gupta
请查看Lindani Masinga的下面回答。我也会更新我的回答。 - drulabs
要从控制台发送数据有效载荷,请参见@Drake29a的下面的答案。 - drulabs

4
这是一个可能的重复问题,参考这个问题。在推送消息中不要发送“通知”。 因此,我基本上将推送通知请求的正文从原来的内容更改为:
{
   "data": {
       "type" : "mytype"
    },
    "notification": {
        "title": "My Title",
        "body": "My Notification Message"
    },
    "to": "/topics/all"
}

收件人:
{
   "data": {
       "type" : "mytype",
       "title": "My Title",
       "body": "My Notification Message"
    },
    "to": "/topics/all"
}

现在,即使在后台,我的应用程序也会每次调用 onMessageReceived() 方法,我刚刚更改了方法,以便使用推送数据中获得的通知标题和消息。

嗨,我的应用程序在后台没有调用onMessageReceived()方法。 - Avinash
谢谢!这是最重要和可接受的消息。我已经不停地奋斗了8个小时,终于!就像你说的一样...它在两种情况下都能正常工作。 - Emre Kilinc Arslan
@SagarPanwala 背景指的是当应用程序当前不可见于用户时。 - Alvin Rusli
@SagarPanwala,即使应用程序被杀死,它仍应接收推送消息,我不明白问题出在哪里。 - Alvin Rusli
有许多设备在应用程序被杀死时无法接收通知,例如小米、Oppo、Vivo、一些三星设备、联想和HTC。 只有关闭电池优化,我们才能接收到通知。 - Sagar Panwala
显示剩余3条评论

2
当您的应用程序被杀死或置于后台时,onMessageReceive永远不会触发。
您应该怎么做?
当推送发送时,只需添加以下数据项;您可以使用Postman。

首先需要此网址:https://fcm.googleapis.com/fcm/send 当您发送时,可以选择 POST

然后,您应该添加如下标头:

Content-Type: application/json

Authorization: key="您的服务器密钥"

  {
        "to": "/topics/yourTopics",


        "data": {
            "title": "BlaBla",
            "body":"BlaBla"
         }
    }

如何处理;
class PushService : FirebaseMessagingService() {

     override fun onMessageReceived(remoteMessage: RemoteMessage?) {
    for (i in remoteMessage!!.data.keys) {
    //Your maps here you can do something..
    }


        val contentIntent = PendingIntent.getActivity(this,
                0, intent, PendingIntent.FLAG_UPDATE_CURRENT)

        val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
// Your notification set here!! 
        val b = NotificationCompat.Builder(this, "1")
        val n = b.setTicker(remoteMessage!!.data["title"])
                .setWhen(0)
                .setAutoCancel(true)
                .setContentTitle(remoteMessage.data["title"])
                .setContentText(remoteMessage.data["body"])
                .setShowWhen(true)
                .setContentIntent(contentIntent)
                .setSound(uri)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .setStyle(NotificationCompat.BigTextStyle().bigText(remoteMessage.data["body"]))


        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            b.setSmallIcon(R.drawable.ic_push_notification_transparent)
            b.color = ContextCompat.getColor(this, R.color.colorAccent)
        } else {
            b.setSmallIcon(R.mipmap.ic_launcher)
        }

        val notificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel("1",
                    "ic_notification",
                    NotificationManager.IMPORTANCE_DEFAULT)
            notificationManager.createNotificationChannel(channel)
        }

        if (notificationManager != null) {
            notificationManager.cancel(1)
            notificationManager.notify(1, n.build())
        }
    }


}

0

0

这是一个使用nodejs编写的工作示例,用于处理所有类型的条件前台后台应用程序被杀死,这将在所有三种类型中起作用。

let message = {
        "data": {
            "callerName": "callerName",
            "notifyType": "notifyType",
            "channelName": "channelName",
            "tragetuid": "tragetuid",
            "msg": "msg"
        },

        token: "cq4KgPelQ_ukmAL1NmNs0l:APA91bG0l2uS1djSsD181cgtgFSd8......",
    };

    let response = await admin.messaging().send(message).catch((error) => {
        console.log('Error sending message:', error);
    });
    if (!response) {
        ctx.status = 404;
        ctx.body = "Error";
    } else {
        ctx.status = 200;
        ctx.body = {
            response, message
        };
    }

基本上,我们需要在OnReceived()函数中使用类型数据而不是通知来获取FCM消息。

{
        "data": {
            "callerName": "callerName",
            "notifyType": "notifyType",
            "channelName": "channelName",
            "tragetuid": "tragetuid",
            "msg": "msg"
        },

        token: "cq4KgPelQ_ukmAL1NmNs0l:APA91bG0l2uS1djSsD181cgtgFSd8......",
    }

0

如果您想将用户重定向到应用程序中的内容,请使用deepLink, 以下是如何在单击通知时仅打开链接:

Intent notificationIntent = new Intent(Intent.ACTION_VIEW);
        notificationIntent.setData(Uri.parse(remoteMessage.getData().getString("url")); 
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
         // Resources r = getResources();
          Notification notification = new NotificationCompat.Builder(context)
                  .setTicker("yortext")
                  .setSmallIcon(android.R.drawable.ic_menu_report_image)
                  .setContentTitle("title")
                  .setContentText("content")
                  .setContentIntent(pendingIntent)
                  .build();

          NotificationManager notificationManager =  (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
          notificationManager.notify(0, notification);

要发送有效载荷,请进入Firebase控制台,创建新消息,在此处您将拥有高级选项,可以将数据放入键/值对中,将URL放置在下面的照片中。

Adding payload to Firebase message


Drake在FB上接受了我的好友请求,我想询问一些有关Firebase的疑问。@Drake29a - vishal gupta
在这里提问,请勿在 Facebook 上发送好友请求。 - Drake29a

0

嗨,我的应用在后台没有调用onMessageReceived()方法。 - Avinash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接