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

iOS PWA中FCM通知onMessage未触发,onBackgroundMessage始终触发求助

解决方案:iOS PWA FCM前台消息处理与通知控制

核心问题原因

iOS WebKit对PWA的FCM消息处理有特殊逻辑:即使应用处于前台,带notification字段的通知消息也会直接触发Service Worker的onBackgroundMessage,不会调用页面的onMessage。这是iOS平台的固有行为,和桌面端/安卓Web的处理逻辑不同。

具体解决步骤

1. 发送纯数据消息

推送消息时不要包含notification字段,改用纯data字段传递内容。这样消息会先进入Service Worker,由我们自行控制后续逻辑。

2. 修改Service Worker逻辑,区分前台/后台状态

在Service Worker中通过clients.matchAll检测当前是否有活跃的前台客户端,根据状态决定是转发消息到页面还是显示系统通知:

// 修改后的Service Worker代码
importScripts('./firebase-app-compat.js');
importScripts('./firebase-messaging-compat.js');
importScripts('./init.js');

const messaging = firebase.messaging();

messaging.onBackgroundMessage(async function(payload) {
  console.log('[firebase-messaging-sw.js] Received message ', payload);
  
  // 检测是否有前台活跃的应用实例
  const clientsList = await clients.matchAll({
    type: 'window',
    includeUncontrolled: true
  });
  
  const isAppInForeground = clientsList.some(client => client.focused);
  
  if (isAppInForeground) {
    // 应用在前台,转发消息到页面
    clientsList.forEach(client => {
      client.postMessage({
        type: 'FCM_MESSAGE',
        payload: payload.data
      });
    });
  } else {
    // 应用在后台/未打开,显示系统通知
    const notificationTitle = payload.data.title || '新消息';
    const notificationOptions = {
      body: payload.data.body || '您有一条新消息',
      icon: './firebase-logo.png'
    };
    self.registration.showNotification(notificationTitle, notificationOptions);
  }
});

3. 页面端监听Service Worker消息,更新UI

在页面脚本中添加Service Worker消息监听,接收转发的消息并更新界面:

// 页面脚本新增部分
if ("serviceWorker" in navigator) {
  // 监听Service Worker发来的消息
  navigator.serviceWorker.addEventListener('message', (event) => {
    if (event.data.type === 'FCM_MESSAGE') {
      console.log("Message received from SW: ", event.data.payload);
      appendMessage(event.data.payload); // 调用原有的UI更新方法
    }
  });
  
  // 原有的Service Worker注册和初始化逻辑保持不变
  window.addEventListener("load", function () {
    navigator.serviceWorker.register("./firebase-messaging-sw.js").then(
      function (registration) {
        console.log("SW registration successful with scope: ", registration.scope);
      },
      function (err) {
        console.log("SW registration failed: ", err);
      }
    );
  });
  navigator.serviceWorker.ready.then(registration => {
    reg = registration;
    resetUI();
  });
}

// 原有的messaging.onMessage可以保留(兼容其他平台)
messaging.onMessage((payload) => {
  console.log("Message received. ", payload);
  appendMessage(payload);
});

额外注意事项

  • 确保PWA满足iOS的安装要求:HTTPS协议、正确的manifest.json配置(包含display: standalone或fullscreen)、图标资源齐全。
  • 推送消息的data字段要包含你需要的所有内容(标题、正文、自定义数据等),因为不再依赖notification字段。
  • 测试时需要将PWA添加到主屏幕后再测试,iOS Safari中直接打开的网页和添加到主屏幕的PWA行为不同。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 22:37:49