React Native集成Firebase Cloud Messaging如何不点击通知获取数据
解决方案
你目前实现的逻辑仅覆盖了「点击通知唤起应用」的消息处理场景,对于用户忽略通知直接打开应用的情况,需要新增本地持久化存储通知+应用前台激活时拉取未读消息的逻辑,具体实现如下:
核心实现步骤
- 收到推送消息时,无论用户是否点击通知,都先将完整消息存入本地持久化存储(可使用
AsyncStorage、MMKV等本地存储方案),同时标记未读状态 - 监听应用激活状态:包括应用冷启动完成、应用从后台切回前台两个时机,触发后读取本地所有未读通知统一处理
- 消息被用户查看后,更新本地存储的消息状态为已读,避免重复处理
修改后的代码示例
import { AppState } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; // 存储通知到本地的通用方法 const saveNotificationToLocal = async (remoteMessage) => { // 生成消息唯一标识,也可以用推送服务返回的messageId const msgId = remoteMessage.messageId || Date.now().toString(); const existingMsgs = await AsyncStorage.getItem('unreadNotifications'); const msgList = existingMsgs ? JSON.parse(existingMsgs) : []; // 避免重复存储同一条消息 if (!msgList.find(item => item.messageId === msgId)) { msgList.push({ ...remoteMessage, isRead: false, saveTime: Date.now() }); await AsyncStorage.setItem('unreadNotifications', JSON.stringify(msgList)); } } // 处理本地未读通知的通用方法 const handleLocalUnreadMsgs = async () => { const existingMsgs = await AsyncStorage.getItem('unreadNotifications'); const msgList = existingMsgs ? JSON.parse(existingMsgs) : []; const unreadMsgs = msgList.filter(item => !item.isRead); if (unreadMsgs.length > 0) { // 批量处理所有未读消息 unreadMsgs.forEach(msg => handlerMessage(msg)); // 可选:如果需要跳转可以在这里判断,或者统一展示消息列表 // setInitialRoute('Messenger') // 处理后标记为已读,也可以根据业务需求在用户点击查看后再标记 const updatedMsgs = msgList.map(item => ({...item, isRead: true})); await AsyncStorage.setItem('unreadNotifications', JSON.stringify(updatedMsgs)); } } useEffect(() => { // 应用启动时先处理本地未读消息 handleLocalUnreadMsgs(); // 监听应用前后台切换 const appStateListener = AppState.addEventListener('change', nextAppState => { if (nextAppState === 'active') { // 应用切回前台时处理未读消息 handleLocalUnreadMsgs(); } }); messaging().setBackgroundMessageHandler(async remoteMessage => { // 后台收到消息先存本地 await saveNotificationToLocal(remoteMessage); handlerMessage(remoteMessage) setInitialRoute('Messenger') }); messaging().onMessage(async remoteMessage => { // 前台收到消息先存本地 await saveNotificationToLocal(remoteMessage); handlerMessage(remoteMessage); }); messaging() .getInitialNotification() .then(remoteMessage => { if (remoteMessage) { handlerMessage(remoteMessage); setInitialRoute('Messenger') } }); // 卸载时移除监听 return () => { appStateListener.remove(); } }, []);
补充说明:如果你的推送服务端支持未读消息拉取接口,也可以在应用激活时调用接口拉取用户所有未读消息,和本地存储方案搭配使用可靠性更高。
内容的提问来源于stack exchange,提问作者Darya Leushkina
相关产品推荐
相关产品推荐

