Flutter Web应用 - 当应用不在当前标签页时,FCM消息未被接收
我想把Firebase消息推送加入我的Flutter Web应用。
当网页应用处于活动标签时,一切正常工作。但是如果它不是活动标签,我就什么也接收不到。
下面,我附上用于捕获FCM的 JavaScript代码
我在某处看到过关于service worker未注册或相互冲突导致问题的说法。
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: 'cccccccc',
appId: 'ccccc',
messagingSenderId: 'cccc',
projectId: 'cccc',
authDomain: 'cccc',
storageBucket: 'cccc',
measurementId: 'cccc',
});
const messaging = firebase.messaging();
/**
* 🔥 CRITICAL: ensure SW becomes active immediately
*/
self.addEventListener('install', () => {
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
messaging.onBackgroundMessage((payload) => {
const title = payload.notification?.title ?? "Notification";
const body = payload.notification?.body ?? "";
const route = payload.data?.route ?? "/";
self.registration.showNotification(title, {
body: body,
icon: "/icons/Icon-192.png",
data: {
route: route
}
});
});
self.addEventListener("notificationclick", function(event) {
event.notification.close();
const route = event.notification.data?.route || "/";
event.waitUntil(
clients.matchAll({ type: "window", includeUncontrolled: true })
.then((clientList) => {
for (const client of clientList) {
if (client.url.includes(self.location.origin) && "focus" in client) {
client.focus();
client.navigate("/#" + route);
return;
}
}
return clients.openWindow("/#" + route);
})
);
});
解决方案
很可能是因为你使用了payload.notification,而不是一个基于数据的Web推送有效载荷。在Flutter Web中,Firebase的后台消息由service worker处理,浏览器在标签页处于非活动状态时,往往会压制或以不同的方式处理仅包含通知的消息。尝试从后端发送一个包含数据字段的有效载荷,然后在onBackgroundMessage() 中从payload.data读取这些值。你的service worker设置在其他方面是正确的,包括skipWaiting() 和clients.claim()。
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: 'cccccccc',
appId: 'cccc',
messagingSenderId: 'cccc',
projectId: 'cccc',
authDomain: 'cccc',
storageBucket: 'cccc',
measurementId: 'cccc',
});
const messaging = firebase.messaging();
/**
* Ensure service worker activates immediately
*/
self.addEventListener('install', () => {
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
/**
* Handle background FCM messages
*/
messaging.onBackgroundMessage((payload) => {
console.log('Received background message:', payload);
const title = payload.data?.title || "Notification";
const body = payload.data?.body || "";
const route = payload.data?.route || "/";
self.registration.showNotification(title, {
body: body,
icon: "/icons/Icon-192.png",
data: {
route: route
}
});
});
/**
* Handle notification click
*/
self.addEventListener("notificationclick", function(event) {
event.notification.close();
const route = event.notification.data?.route || "/";
event.waitUntil(
clients.matchAll({
type: "window",
includeUncontrolled: true
}).then((clientList) => {
for (const client of clientList) {
if (client.url.includes(self.location.origin) && "focus" in client) {
client.focus();
client.navigate("/#" + route);
return;
}
}
return clients.openWindow("/#" + route);
})
);
});
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。