Firebase云消息传递:setBackgroundMessageHandler未被调用

28
我正在使用FCM原型化浏览器推送通知。我刚从快速入门中复制了示例代码(https://github.com/firebase/quickstart-js/tree/master/messaging)。消息能够按预期收到并显示。但是当我尝试在Service Worker中修改消息(messaging.setBackgroundMessageHandler),什么也没有发生。Service Worker被调用了,并且如果我在该Service Worker中实现一个用于推送通知的事件监听器,则会捕获该事件。但是setBackgroundMessageHandler方法从未被调用。 我正在Chrome 54上尝试这个操作。
你有什么想法,我需要怎样自定义服务工作者中的消息?
非常感谢!
6个回答

51

2
这救了我的命。我真的快疯了,试图理解为什么我的处理程序没有被调用。 - Phillip Stack
https://github.com/firebase/firebase-js-sdk/blob/master/packages/messaging/src/controllers/sw-controller.ts - Henry
8
如果我删除“通知”,则它支持Web应用程序。但它不支持移动Android和IOS。有什么解决办法吗? - acmsohail
@acmsohail,你找到任何解决方案了吗? - Adnan
@Adnan 还没有。 - acmsohail
显示剩余3条评论

10

这是我在一个Web应用中使用的解决方案。它显示带有标题和正文文本以及图像的通知,并处理用户的单击。

firebase-messaging-sw.js

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

// Initialize Firebase
var config = {
  apiKey: 'YOUR_API_KEY',
  authDomain: 'YOUR_AUTH_DOMAIN',
  databaseURL: 'YOUR_DB_URL',
  projectId: 'YOUR_PROJ_ID',
  storageBucket: 'YOUR_STORAGE_BUCKET',
  messagingSenderId: 'YOUR_SENDER_ID',
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
  console.log('Handling background message ', payload);

  return self.registration.showNotification(payload.data.title, {
    body: payload.data.body,
    icon: payload.data.icon,
    tag: payload.data.tag,
    data: payload.data.link,
  });
});

self.addEventListener('notificationclick', function (event) {
  event.notification.close();
  event.waitUntil(self.clients.openWindow(event.notification.data));
});

JSON 消息

{
  "message": {
    "token": "YOUR_TARGET_APP_TOKEN",
    "data": {
      "title": "FCM Message",
      "body": "This is an FCM Message",
      "icon": "https://shortcut-test2.s3.amazonaws.com/uploads/role_image/attachment/10461/thumb_image.jpg",
      "link": "https://yourapp.com/somewhere"
    }
  }
}

1
两年后,它仍然保持这种行为,你救了我的命。 - SRR
这样的JSON消息对于Legacy HTTP API无效。 - andreszs

3

正如其他人所提到的,将通知包含在负载中会使其在Web JS SDK上无法工作,但是您需要它存在才能在原生应用程序中使用。

我发现Web的解决方法是使用Web浏览器本地EH push手动处理事件:

https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onpush

  self.addEventListener('notificationclick', function(event) {
    console.log('SW: Clicked notification', event)

    let data = event.notification.data

    event.notification.close()

    self.clients.openWindow(event.notification.data.link)
  })

  self.addEventListener('push', event => {
    let data = {}

    if (event.data) {
      data = event.data.json()
    }

    console.log('SW: Push received', data)

    if (data.notification && data.notification.title) {
      self.registration.showNotification(data.notification.title, {
        body: data.notification.body,
        icon: 'https://example.com/img/icons/icon-144x144.png',
        data
      })
    } else {
      console.log('SW: No notification payload, not showing notification')
    }
  })

对我来说,无论是 messaging.setBackgroundMessageHandler() 还是 messaging.onMessage() 都没有被调用。通过你的解决方法,我终于在接收通知时得到了控制台消息。 - kapil pandey

1
当您尝试发送推送消息时,您是在应用程序处于焦点状态还是非焦点状态下进行的?因为根据文档,它说Web应用程序关闭或不在浏览器焦点时才会调用setBackgroundMessageHandler。
基于快速入门的示例代码(https://github.com/firebase/quickstart-js/tree/master/messaging)。
如果您的应用程序处于焦点状态:推送消息将通过messaging.onMessage()在index.html上接收。 如果您的应用程序没有焦点:推送消息将通过setBackgroundMessageHandler()在服务工作者文件中接收。

抱歉,忘了提到这一点:在焦点上它运行良好,并且可以调用onMessage方法,我可以对消息进行操作。当页面没有焦点时,通知会显示,但是我无法在setBackgroundMessageHandler方法中自定义它,因为该方法从未被调用。 - Mathias

1

无论是在 iOS 还是 Android 中,都将始终调用 setBackgroundMessageHandler。在 iOS 中,如果应用程序状态为退出或被杀死,则会在几分钟后刷新。请确保在负载中发送 content_available:true。

{
     "registration_ids":["token"],
     "collapse_key" : "packageName",
     "notification" : {
         "body" : "Body of Your Notification",
         "title": "Title of Your Notification",
         "sound": "default"
     },
     "priority": "high",
     "content_available": true, // This is compulsory for background handler
     "data" : {
         "body" : "Body of Your Notification in Data",
         "title": "Title of Your Notification in Title",
         "badge": 89
     }
}

你救了我的一天。非常感谢。content_available 真的起到了很大的作用。 - undefined

0
messaging().setBackgroundMessageHandler(async remoteMessage => {
       console.log('Message handled in the background!', remoteMessage);
          });

这个解决了我的问题。


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