You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web应用在非活跃标签页无法接收FCM消息的问题

Flutter Web后台无法接收FCM消息的排查与修复方案

核心问题定位

前台能正常接收消息说明FCM基础配置无问题,但后台(非活跃标签)无响应,大概率是Service Worker(SW)未正确激活/运行,或消息格式不满足后台触发条件。以下是分步排查和修复方案:

1. 确认Service Worker的注册与状态

  • 检查SW文件位置:firebase-messaging-sw.js必须放在网站根目录(如https://your-domain.com/firebase-messaging-sw.js),不能放在子文件夹(如/assets/),否则FCM无法定位到文件。
  • 验证SW激活状态:打开Chrome DevTools → Application → Service Workers,确认:
    • SW处于Activated状态且Status显示Running;
    • 无重复注册的SW(避免冲突);
    • 刷新页面后SW未被卸载。
  • Flutter端注册代码检查:确保注册路径正确,示例:
import 'package:firebase_messaging/firebase_messaging.dart';

void setupFCM() async {
  await FirebaseMessaging.instance.setAutoInitEnabled(true);
  // 必须指向根目录的SW文件
  await FirebaseMessaging.instance.registerServiceWorker(
    serviceWorkerUrl: '/firebase-messaging-sw.js',
  );
}

2. 修正FCM消息格式

后台接收消息需满足特定格式要求:

  • 通知消息需携带data字段:如果发送的是通知消息,必须同时附带data字段,否则浏览器会直接显示系统通知,不会触发SW的onBackgroundMessage;
  • 纯数据消息需配置content_available:若仅发送数据消息,需在payload中添加content_available: true,并在webpush配置中设置Urgency: high(避免浏览器节流拦截)。

示例FCM API请求payload:

{
  "message": {
    "token": "用户设备的FCM令牌",
    "notification": {
      "title": "测试通知",
      "body": "后台消息测试"
    },
    "data": {
      "route": "/home"
    },
    "webpush": {
      "headers": {
        "Urgency": "high"
      }
    }
  }
}

3. 优化Service Worker代码

你的SW已有基础配置,可调整以下点提升稳定性:

  • 确保skipWaiting在安装完成后执行;
  • 添加fetch事件避免SW被浏览器回收;
  • 优化客户端匹配逻辑(兼容更多场景)。

修改后的完整SW代码:

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();

// 确保SW安装完成后立即激活
self.addEventListener('install', (event) => {
    event.waitUntil(
        Promise.resolve().then(() => {
            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 ?? "/";

    return self.registration.showNotification(title, {
        body: body,
        icon: "/icons/Icon-192.png",
        data: { route },
        // 添加通知属性确保浏览器正常显示
        vibrate: [200, 100, 200],
        tag: 'fcm-notification'
    });
});

// 通知点击处理
self.addEventListener("notificationclick", function(event) {
    event.notification.close();
    const route = event.notification.data?.route || "/";
    const targetUrl = `${self.location.origin}/#${route}`;

    event.waitUntil(
        clients.matchAll({ type: "window", includeUncontrolled: true })
            .then((clientList) => {
                // 优先聚焦已打开的同源窗口
                for (const client of clientList) {
                    if (client.url.startsWith(self.location.origin) && "focus" in client) {
                        return client.focus().then(() => {
                            client.navigate(targetUrl);
                        });
                    }
                }
                // 无窗口则打开新窗口
                return clients.openWindow(targetUrl);
            })
    );
});

// 添加fetch事件,避免SW被浏览器回收
self.addEventListener('fetch', (event) => {
    event.respondWith(fetch(event.request).catch(() => {
        // 可选:离线时返回缓存内容
        return caches.match(event.request);
    }));
});

4. 浏览器权限与环境检查

  • 确认通知权限已授权:在Flutter端主动请求权限:
final permissionStatus = await FirebaseMessaging.instance.requestPermission();
if (permissionStatus.authorizationStatus != AuthorizationStatus.authorized) {
  // 提示用户开启通知权限
}
  • 排除浏览器限制:检查浏览器是否开启"请勿打扰"、禁用通知,或安装了屏蔽通知的插件;
  • 环境要求:必须使用HTTPS(localhost除外),否则Service Worker无法正常运行。

5. 调试技巧

  • 打开SW控制台:在Chrome DevTools的Service Workers面板,点击SW右侧的Inspect,查看onBackgroundMessage的日志输出;
  • 模拟后台状态:切换到其他标签或最小化浏览器窗口,用Firebase控制台发送测试消息,观察SW是否触发;
  • 查看FCM送达报告:在Firebase控制台 → Cloud Messaging → 消息记录,确认消息是否标记为"已送达"。

内容的提问来源于stack exchange,提问作者Davout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 01:07:27