如果浏览器在后台,FCM 推送通知会到达两次

Szá*_*tán 5 javascript google-chrome firebase-cloud-messaging

我已经建立了一个简单的推送通知站点,如果浏览器在前台,通知就可以到达。

如果浏览器在后台,问题就开始了:通知到达两次,一个带有图像和其他设置的样式,另一个只有标题和正文消息。

服务工作者的内容:

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

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
    'messagingSenderId': '...'
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
    console.log('[firebase-messaging-sw.js] Received background message ', 
    return null;
});

self.addEventListener('install', function (event) {
    event.waitUntil(skipWaiting());
});

self.addEventListener('activate', function (event) {
    event.waitUntil(clients.claim());
});

self.addEventListener('push', function (event) {
    var pushData = event.data.json();
    try {
        var notificationData = pushData.data;
        notificationData.data = JSON.parse(notificationData.data);
        console.log(notificationData);
        self.registration.showNotification(pushData.notification.title, notificationData);
    }
    catch (err) {
        console.log('Push error happened: ', err);
    }
});
Run Code Online (Sandbox Code Playgroud)

客户端js:

firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();

messaging.onMessage(function (payload) {
    console.log("notification recieved");
    return null;
});

self.addEventListener('push', function (event) {
    console.log("window push stuff");
    return null;
});
Run Code Online (Sandbox Code Playgroud)

谢谢!

Mar*_*rík 6

100% 避免多个通知的最简单方法是添加“标签”,例如:

var options = {
    body: "text",
    tag: "notification-1"
};
self.registration.showNotification("title", options)
Run Code Online (Sandbox Code Playgroud)

  • @judasane 它唯一标识该消息,因此它仅弹出一次,而不是多次。 (2认同)

Szá*_*tán 5

通过将这一行添加到事件中可以解决该问题messaging.setBackgroundMessageHandler

self.registration.hideNotification();
Run Code Online (Sandbox Code Playgroud)

这样,默认通知将不会显示,您必须在self.addEventListener事件中显示您的通知。


Dmi*_*ind 5

我花了大约两周的时间才理解并解决这个问题。希望这能为其他人节省时间:

Firebase 支持两种类型的推送通知:

  1. 显示 FCM SDK 自动处理数据的通知
  2. 数据消息,由客户端应用程序处理

Firebase 云消息传递 UI 具有许多优势,例如按国家/地区、设备、语言等进行高级定位。但它只允许在数据自定义字段内发送 URL。

从 Firebase 控制台 UI 发送的消息如下所示:

 {
    notification: {
      title: "New Test",
      body: "This is test",
    },
    data: {
      url: 'someurl.com',
    },
  };
Run Code Online (Sandbox Code Playgroud)

当 Service Worker 处理通知时,通知会出现两次,当 FCM SDK 自动执行通知时,通知会出现第二次。

我没有找到一种方法来禁用通知的自动处理,并在前端使用 Firebase 函数仅将其作为数据消息发送:

 {
    data: {
      title: "New Test",
      body: "This is test",
      url: 'someurl.com',
    },
  };
Run Code Online (Sandbox Code Playgroud)

因此,如果您想传递自定义 URL 来推送通知,则需要从您自己的服务器或使用 firebase 函数发送它。