React Native Firebase消息:后台/杀死状态下处理通知与角标更新
针对你使用@react-native-firebase/messaging@7.8.4遇到的两个问题,我会一步步给出具体的解决方案:
1. 收到通知横幅时立即唤醒应用执行处理逻辑
你推测的原因完全正确:Payload中缺少content-available: 1(iOS aps字段)会导致应用无法在后台/杀死状态下被唤醒,setBackgroundMessageHandler自然不会触发。要实现后台静默处理,需要同时满足后端配置、iOS原生配置和RN代码设置三个条件:
步骤1:修改后端推送Payload
必须在iOS的aps字段中添加content-available: 1,同时确保FCM推送的优先级设为high(iOS要求高优先级才能触发后台唤醒)。调整后的Payload示例:
{ "aps": { "alert": { "body": "msg", "title": "iOS" }, "sound": "default", "content-available": 1, // 核心:开启后台唤醒 "mutable-content": 1 // 处理富媒体时可选,非必须 }, "deeplink": "myapp://profile", "mediaType": "image", "notificationid": "maskedData" }
注意:如果通过FCM API发送,要在请求体中设置
priority: "high",否则iOS可能会延迟或忽略后台唤醒请求。
步骤2:配置iOS原生项目的Background Modes
打开Xcode,进入你的项目target:
- 切换到
Signing & Capabilities标签 - 点击
+ Capability,添加Background Modes - 勾选
Remote notifications选项
这一步是iOS允许应用在后台接收远程通知并唤醒的必要配置,缺一不可。
步骤3:正确注册setBackgroundMessageHandler
在@react-native-firebase/messaging@7.x版本中,setBackgroundMessageHandler必须在App组件挂载之前注册(比如在index.js的最顶部),否则无法在杀死状态下触发。示例代码:
// index.js import { AppRegistry } from 'react-native'; import messaging from '@react-native-firebase/messaging'; import App from './App'; import AsyncStorage from '@react-native-async-storage/async-storage'; // 后台消息处理函数,必须在App注册前定义 messaging().setBackgroundMessageHandler(async remoteMessage => { console.log('后台收到通知,开始处理:', remoteMessage); // 示例:将通知存储到本地(可根据notificationid去重) try { const storedNotifications = await AsyncStorage.getItem('app_notifications') || '[]'; const notifications = JSON.parse(storedNotifications); const isDuplicate = notifications.some(n => n.data.notificationid === remoteMessage.data.notificationid); if (!isDuplicate) { notifications.push(remoteMessage); await AsyncStorage.setItem('app_notifications', JSON.stringify(notifications)); } } catch (error) { console.error('存储通知失败:', error); } }); AppRegistry.registerComponent('YourAppName', () => App);
这样,当通知到达时,即使应用在后台或被杀死,系统也会短暂唤醒应用执行这个handler,你就可以在其中完成存储通知等逻辑。
2. 后台/杀死状态下更新应用角标数字
角标更新有两种实现方式,根据你的需求选择:
方式1:后端直接指定角标数字(最简单)
如果角标数字可以由后端计算好,直接在Payload的aps字段中添加badge值即可,iOS会自动更新角标,不需要应用唤醒:
{ "aps": { // ...其他字段 "badge": 3 // 直接设置角标数字,设为0可清除角标 } }
方式2:前端动态计算角标(需要后台唤醒)
如果需要基于本地存储的通知数量动态更新角标,就需要在setBackgroundMessageHandler中调用messaging().setBadgeNumber()方法,前提是已经完成了上面第一个问题的所有配置(确保handler能被触发)。示例代码:
// 在setBackgroundMessageHandler中添加角标更新逻辑 messaging().setBackgroundMessageHandler(async remoteMessage => { // ...存储通知的逻辑 // 计算当前通知数量并更新角标 const storedNotifications = await AsyncStorage.getItem('app_notifications') || '[]'; const notificationsCount = JSON.parse(storedNotifications).length; await messaging().setBadgeNumber(notificationsCount); });
注意:iOS系统对后台唤醒的时间有限制,所以这个逻辑要尽量简洁,避免耗时操作,否则系统会终止进程导致角标更新失败。
额外注意事项
- 确保用户已经授予应用通知权限(只需“允许通知”,不需要额外后台权限,只要开启了Background Modes的Remote notifications即可)。
- 在
@react-native-firebase/messaging@7.x中,setBackgroundMessageHandler的回调函数必须是异步的,且要尽量快速完成。 - 测试杀死状态下的后台处理时,不要用Xcode调试(Xcode附加调试会让应用处于特殊状态),应该直接在真机上卸载重装后测试。
内容的提问来源于stack exchange,提问作者Tommy Leong

