无法让 click_action 使用 Web 应用程序/PWA 处理 FCM 通知

Joh*_*n M 7 action click progressive-web-apps firebase-cloud-messaging

我试图让我的“click_action”将用户带到我发送给客户端的通知上的特定 URL,但无论我做什么,它要么不执行任何操作(桌面),要么只是打开 PWA(android)。消息传输正常(在 Chrome 控制台中检查),但点击似乎不起作用。

\n\n

我的服务人员中有以下内容,是从各个地方抄来的,包括本网站上提供的其他答案:

\n\n
importScripts(\'https://www.gstatic.com/firebasejs/7.14.3/firebase-app.js\');\nimportScripts(\'https://www.gstatic.com/firebasejs/7.14.3/firebase-messaging.js\');\n// importScripts(\'/__/firebase/init.js\');\n\n/* An empty service worker!  */\nself.addEventListener(\'fetch\', function(event) {\n  /* An empty fetch handler! */\n});\n\n   var firebaseConfig = {\n//REDACTED\n  };\n  // Initialize Firebase\n  firebase.initializeApp(firebaseConfig);\n\n const messaging = firebase.messaging();\n\nmessaging.setBackgroundMessageHandler(function(payload) {\n  console.log(\'[firebase-messaging-sw.js] Received background message \', payload);\n  // Customize notification here\n\n\n  notificationTitle = payload.notification.title;\n  notificationOptions = {\n    body: payload.notification.body,\n    icon: payload.notification.icon,\n    click_action: payload.notification.click_action\n  };\n\n  return self.registration.showNotification(notificationTitle,\n    notificationOptions);\n});\n\nself.addEventListener(\'notificationclick\', function(event) {\n    let url = event.notification.click_action;\n// I\'ve also added a data.click_action field in my JSON notification, and have tried using that\n// instead, but that didn\'t work either\n\n    console.log(\'On notification click: \', event.notification.tag); \n    event.notification.close(); // Android needs explicit close.\n    event.waitUntil(\n        clients.matchAll({ includeUncontrolled: true, type: \'window\' }).then( windowClients => {\n            // Check if there is already a window/tab open with the target URL\n            for (var i = 0; i < windowClients.length; i++) {\n                var client = windowClients[i];\n                // If so, just focus it.\n                if (client.url === url && \'focus\' in client) {\n                    return client.focus();\n                }\n            }\n            // If not, then open the target URL in a new window/tab.\n            if (clients.openWindow) {\n                return clients.openWindow(url);\n            }\n        })\n    );\n});\n\n\nself.onnotificationclick = function(event) {\n  let url = event.notification.click_action;\n  console.log(\'On notification click: \', event.notification.tag);\n  event.notification.close();\n\n  // This looks to see if the current is already open and\n  // focuses if it is\n  event.waitUntil(clients.matchAll({ includeUncontrolled: true, type: \'window\' }).then(function(clientList) {\n    for (var i = 0; i < clientList.length; i++) {\n      var client = clientList[i];\n      if (client.url == url && \'focus\' in client)\n        return client.focus();\n    }\n    if (clients.openWindow)\n      return clients.openWindow(url);\n  }));\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

通知在 Android(已安装 PWA)和 chrome 上都可以正常发送,并且开发人员控制台中的消息有效负载格式良好且接收良好。在我从服务器发送的消息中,我有一个末尾带有自定义参数的 URL(例如https://[domain]/list.php?userid=123),但是,如上所述,单击通知不会在 windows/chrome 上不执行任何操作,在 android 上它会成功打开 PWA,但不会转到有效负载中的 URL,它只会转到上次打开 PWA 时所在的位置。“userid”根据消息触发而变化。

\n\n

消息负载的 JSON 示例:

\n\n
{data: {\xe2\x80\xa6}, from: "xxx", priority: "high", notification: {\xe2\x80\xa6}, collapse_key: "do_not_collapse"}\ncollapse_key: "do_not_collapse"\ndata: {gcm.notification.badge: "[logo URL]", click_action: "https://[URL]/list.php?userid=33"}\nfrom: "xxx"\nnotification:\nbody: "\'5\' has just been added"\nclick_action: "https://[URL]/list.php?userid=33"\nicon: "https://[logo URL]"\ntitle: "alert "\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还在https://firebase.google.com/docs/cloud-messaging/js/receive上看到了有关 "webpush": { "fcm_options": { "link": " https://dummypage.com "}}的内容但无法弄清楚这是否相关或是否需要。

\n\n

令我感到非常惊讶的是,仅在 click_action 中提供 URL 似乎并不只是在您单击通知时执行该操作!Service Worker 中到底需要什么吗?!?!

\n\n

问题之一可能是 PWA 不会定期更新软件,所以如果我上面的代码应该可以工作(一个很大的如果!)那么我只需要等待软件在已安装的 Android 应用程序上更新?如果是这样,有没有办法加快更新速度?!?

\n\n

预先非常感谢您的帮助。我把自己绑在这儿了!

\n

ant*_*ron 6

我花了很多时间寻找同一问题的解决方案。也许这可以帮助:

如果您使用 firebase 消息发送通知,则可以使用webpushfield. firebase 消息传递客户端库执行...您的 Service Workerself.registration.showNotification()不再需要。messaging.onBackgroundMessage

// firebabse-coud-function.js

app.messaging().send({
    webpush: {
        notification: {
            title: notification?.title || "Default title",
            icon: notification?.icon || "/icon.png",
            badge: notification?.icon || "/icon.png",
        },
        fcmOptions: {
            link: `${BASE_URL || ""}${notification?.clickAction || "/"}`,
        }
    },
    data: {
        userID: notification.userID,
        link: notification?.clickAction || "/",
    },
    topic
});
Run Code Online (Sandbox Code Playgroud)

最重要的是,在调用之前在您的服务工作人员中添加一个“notificationclick”事件侦听器firebase.messaging()

所以我的服务人员看起来像:

// firebase-messaging-sw.js

// ...

self.addEventListener('notificationclick', function (event) {
    console.debug('SW notification click event', event)
    const url = event.notification?.data?.FCM_MSG?.data?.link;
    // ...
})

const messaging = firebase.messaging();

messaging.onBackgroundMessage(function (payload) {
    // received others messages
})

Run Code Online (Sandbox Code Playgroud)

对我来说,点击事件不会转到正确的网址。所以我添加这个:

// background client - service worker
const channel = new BroadcastChannel('sw-messages');

self.addEventListener('notificationclick', function (event) {
  console.debug('SW notification click event', event)
  const url = event.notification?.data?.FCM_MSG?.data?.link;

  channel.postMessage({
    type: 'notification_clicked',
    data: {
      title: event.notification.title,
      clickAction: url
    }
  });

})
Run Code Online (Sandbox Code Playgroud)
// foreground client
const channel = new BroadcastChannel('sw-messages');
channel.addEventListener("message", function (event) {
    // go the page
})
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助别人。


Hug*_*sse 6

这个问题和其他答案似乎与旧版 FCM API 有关,而不是与 v1.1 相关。在这种情况下,我需要软件打开FCM 发送的任何url,默认情况下这是不可能的,因为主机不同(请参见此处)。此外,通知对象已更改,并且 webpush 配置的 url 现在已存在:event.notification.data.FCM_MSG.notification.click_action

因此,调整其他答案以获得正确的字段并通过仅编辑以下内容来打开网址firebase-messaging-sw.js

importScripts('https://www.gstatic.com/firebasejs/8.2.10/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.10/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
   ...
})

self.addEventListener('notificationclick', function(event) {
    event.notification.close();
    // fcp_options.link field from the FCM backend service goes there, but as the host differ, it not handled by Firebase JS Client sdk, so custom handling
    if (event.notification && event.notification.data && event.notification.data.FCM_MSG && event.notification.data.FCM_MSG.notification) {
        const url = event.notification.data.FCM_MSG.notification.click_action;
        event.waitUntil(
            self.clients.matchAll({type: 'window'}).then( windowClients => {
                // Check if there is already a window/tab open with the target URL
                for (var i = 0; i < windowClients.length; i++) {
                    var client = windowClients[i];
                    // If so, just focus it.
                    if (client.url === url && 'focus' in client) {
                        return client.focus();
                    }
                }
                // If not, then open the target URL in a new window/tab.
                if (self.clients.openWindow) {
                    console.log("open window")
                    return self.clients.openWindow(url);
                }
            })
        )
    }
}, false);

const messaging = firebase.messaging();

Run Code Online (Sandbox Code Playgroud)

(在初始化消息之前注册addEventListener