Web firebase.messaging().onMessage未触发,但后台通知已完美触发。

11

如果使用firebase.messaging().onMessage推送消息时未触发事件,我想在前台重新加载或触发某些事件。我正在使用带有后台通知的firebase.mesaging.sw.js,并且它可以正常工作,我的代码有什么问题?

firebase.js

const config = {
  apiKey: "x",
  projectId: "x",
  storageBucket: "x",
  messagingSenderId: "x"
};

firebase.initializeApp(config);

const msg = firebase.messaging()
msg.requestPermission()
  .then(() => {
    return msg.getToken()
  })
  .then((token) => {
  })
  .catch((err) => {
  })

msg.onMessage(function(payload) {
  alert("Foreground message fired!")
  console.log(payload)
});

firebase.messaging.sw.js

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

const config = {
  apiKey: "x",
  projectId: "x",
  storageBucket: 'x',
  messagingSenderId: "x"
};

firebase.initializeApp(config);
const msg = firebase.messaging()

msg.setBackgroundMessageHandler(function(payload) {
  let options = {
    body: payload.data.body,
    icon: payload.data.icon
  }

  return self.registration.showNotification(payload.data.title, options);

});

我不知道我的代码哪里出了问题

5个回答

11

解决这个问题的简单方法是将您的Firebse更新到最新版本。

例如。

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

注意: 一旦您更新了firebase库的版本,messagingSenderId将无法在firebase-messaging-sw.js文件中正常工作。 您必须提供所有其他参数,例如apiKey,projectId,appId以及messagingSenderId

  • 如果仍然无法正常工作,请清除浏览器缓存并重新注册服务工作者。

有关更多详细信息,请参阅此解决方案


抱歉,但似乎这两个语句都是错误的。在 SW 中只使用 messagingSenderId 仍会收到后台通知,并且 Firebase API 的升级似乎也没有解决任何问题。onMessage 事件就是不会触发。 - andreszs
1
@andreszs 遇到了与firebasejs/7.0.0版本相同的问题。无法触发onMessage事件。我已将我的firebase版本更新到最新版本。然后,我遇到了SW中缺少项目ID的问题。所以我传递了所有其他详细信息。然后一切都正常工作了。 - Maheshvirus
谢谢,我承认按照你所说的在SW中将整个firebaseConfig添加到initializeApp方法中,再清除Chrome数据和缓存以及重新注册通知最终解决了问题。你可以将缓存清理和重新注册建议添加到你的答案中。 - andreszs

5

2020年我仍然有同样的问题。在我的情况下,是这样的:

  • 您需要在后台消息的importScripts和前台应用程序的版本中使用相同的版本。
  • 在获取后台服务的令牌后调用它。
firebaseApp.messaging().getToken().then((currentToken) => {
  if (currentToken) {
    console.log(currentToken)
  } else {
    // Show permission request.
    console.log(
      'No Instance ID token available. Request permission to generate one.')
  }
  /** When app is active */
  firebase.messaging().onMessage((payload) => {
    console.log(payload)
  }, e => {
    console.log(e)
  })
})

感谢在 getToken 后运行 onMessage 对我有帮助。 - Huiting

3
对于其他遇到此问题的人,我最终是通过以下方法解决的:
  1. 将JS文件中包含的头部Firebase SDK版本和SW JS文件的Firebase SDK版本升级到最新版本(目前为7.8.1)。
  2. 按照之前的答案所建议的,在SW中的firebase.initializeApp()中添加整个firebaseConfig数组。
  3. 从开发工具的应用程序 > 清除存储部分清除Chrome缓存。
  4. 从我的数据库中删除以前的注册令牌。
  5. 阻止并取消阻止来自浏览器的通知,强制生成新的令牌。
基本上,使用更新的Firebase SDK进行全新启动似乎可以解决此类问题。

1

我遇到了同样的问题。在我的情况下,"package.json""firebase-messaging-sw.js"中的firebase版本不同。在"firebase-messaging-sw.js"中设置与"package.json"相同的版本后,我的问题得到了解决。

更改之前

 **"package.json"**
 
 "firebase": "^8.2.1",
 
  **"firebase-messaging-sw.js"**

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

更改后

 **"package.json"**

 "firebase": "^8.2.1",

 **"firebase-messaging-sw.js"**

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

我目前使用的版本是8.9.1,但我无法使通知在控制台中打印出来。尽管我成功地从FCM控制台直接发送了该通知后,我设法调用了默认弹出窗口以进行推送通知...有什么建议吗?我可以在任何地方分享代码... - Wrapper

1
你缺少很多东西,只有在调用它之前初始化firebase,onMessage才能起作用。请按照以下步骤操作。我已经这样做了,它可以正常工作。
初始化firebase并获取令牌。
export class BrowserFcmProvider {
export const FIREBASE_CONFIG = {
 apiKey: "****",
 authDomain: "****",
 databaseURL: "****",
 projectId: "****",
 storageBucket: "****",
 messagingSenderId: "****",
 appId: "****"
}

firebase.initializeApp(FIREBASE_CONFIG);

async webGetToken() {
 try {
   const messaging = firebase.messaging();
   await messaging.requestPermission();
   const token = await messaging.getToken();
   let uuidTemp = new DeviceUUID().get();
   return this.saveTokenToFireStoreFromWeb(token, uuidTemp)

 } catch (e) {
   console.log(e);
 }
}

saveTokenToFireStoreFromWeb(token, uuid) {
  try {
     const docData = {
     token: token,
     device_type: 'web',
     uuid: uuid
     }
    const devicesRef = this.db.collection('devices')
    return devicesRef.doc(uuid).set(docData);
  } catch (e) {
    console.log(e, 'saveTokenError');
  }
}

showMessage() {
  try {
    const messaging = firebase.messaging();
    messaging.onMessage((payload) => {
    console.log(payload);
    })
  } catch (e) {
    console.log(e)
  }
}
}

在应用程序加载时像这样调用方法。
  async configureFirebaseForBrowser(res) {
      await this.bfcm.webGetToken();
      this.bfcm.showMessage();
  }

Firebase函数和负载类型
    const payloadWeb = {
            title: title,
            body: body,
            data: {
                title: title,
                body: body
            },
            tokens: uniqueDevicesTokenArrayWeb,
        }

  const responseWeb = await admin.messaging().sendMulticast(payloadWeb);
  console.log(responseWeb.successCount + ' notifications has been sent to Web successfully');

我已经使用了async和await,因为我们需要异步地处理firebase/firestore操作。

在隐身模式和Safari浏览器中,fcm无法工作。


$scope.init = (startDate, endDate, role, moderation) => { webGetToken(); showMessage(); }我已经使用了你的例子,但它仍然没有起作用,requestPermission已被授予,但onMessage函数没有被触发。 - Kuro Neko
你有收到任何错误吗?你在使用哪个框架?你能正确初始化 Firebase 吗?const firebaseIntialise = firebase.initializeApp(FIREBASE_CONFIG); console.log(firebaseIntialise); 你得到了什么? - sibabrat swain
我使用 Laravel 和 Node.js,我的 firebaseInitialize 正常工作。如果我将它放在一个变量中并控制台输出,你会看到一个对象,其中包含 INTERNAL、firebase、isDeleted、options 等等。 - Kuro Neko
Laravel和Node.js都可以用于服务器端。为什么要同时使用两个呢?你能把它放到GitHub上,这样我就可以查看并修复它。 - sibabrat swain
您需要在Service Worker中更改SDK版本为"7.1.0"importScripts('https://www.gstatic.com/firebasejs/7.1.0/firebase-app.js') importScripts('https://www.gstatic.com/firebasejs/7.1.0/firebase-messaging.js') - Albert Hidalgo
实际上,@KuroNeko 正确地初始化了 Firebase,就像 Firebase 文档 中所示。问题出在其他地方。 - andreszs

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