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

时间:2017-10-11 13:57:55

标签: 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);
    }
});

客户端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;
});

谢谢!

4 个答案:

答案 0 :(得分:3)

将此行添加到messaging.setBackgroundMessageHandler事件可以解决此问题:

self.registration.hideNotification();

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

答案 1 :(得分:1)

100%避免多次通知的最简单方法是添加"标记",例如:

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

答案 2 :(得分:0)

这就是我如何让 Firebase 云消息通知在具有这些要求的 Android 设备上的 Progresse Web Apps 中工作:

  1. 推送通知也应该只出现一次在状态栏中
  2. 在 PWA 应用图标上突出显示通知数量
  3. 状态栏中的通知应包含:
  • 带有应用图标的小徽章
  • 实际的应用图标
  • 通知标题
  • 通知正文
  • 点击打开 PWA

Push Notification in Status Bar Badge on App Icon

firebase-messaging.sw.js

不要向该文件添加任何 cdoe 或 onBackgroundMessage() 处理程序。我的文件不过是

//Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.3.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.3.0/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({
  apiKey: 'api-key',
  authDomain: 'project-id.firebaseapp.com',
  databaseURL: 'https://project-id.firebaseio.com',
  projectId: 'project-id',
  storageBucket: 'project-id.appspot.com',
  messagingSenderId: 'sender-id',
  appId: 'app-id',
  measurementId: 'G-measurement-id',
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
if (firebase.messaging.isSupported()) {
  const messaging = !firebase.apps.length
    ? firebase.initializeApp(firebaseConfig).messaging()
    : firebase.app().messaging();

发送通知的服务器端作业

消息有效载荷的内容和结构是关键。将您的通知对象放入 webpush 对象中。请勿添加数据对象,以避免内容不完整的重复通知。

确保您的徽章是 24x24px png,在透明背景上仅包含白色内容。

  var message = {
    webpush: {
      notification: {
        title: "Let's Join App",                          // Your message title
        body: messageBody,                                // Your message body
        icon: "./img/icons/android-chrome-192x192.png",   // Your App icon, up to 512x512px, any color
        badge: "./img/icons/badge.png",                   // Your app badge, 24x24px, white content on transparent background
      },
      fcmOptions: {
        link: "https://www.letsjoin.app",                 // Your Link
      },
    },
    token,
  };

  // Send a message to the device corresponding to the provided
  // registration token.
  await admin
    .messaging()
    .send(message)
    .then((response) => {
      // Response is a message ID string.
      console.log("Successfully sent message");
    })
    .catch((error) => {
      console.log("Error sending message:", error.errorInfo.message);
    });
};

答案 3 :(得分:0)

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

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

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

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

从 Firebase 控制台用户界面发送的消息如下所示:

 {
    notification: {
      title: "New Test",
      body: "This is test",
    },
    data: {
      url: 'someurl.com',
    },
  };

通知在 Service Worker 处理时出现两次,在 FCM SDK 自动处理时出现第二次。

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

 {
    data: {
      title: "New Test",
      body: "This is test",
      url: 'someurl.com',
    },
  };

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