React-Native Firebase Cloud Messaging:点击通知唤醒无事件求助
解决React Native FCM后台唤醒时无法捕获通知数据的问题
我之前也碰到过一模一样的问题,核心原因是你在页面组件的componentDidMount里注册FCM通知监听太晚了——当点击通知把App从后台(或杀死状态)唤醒时,通知事件在App启动初期就已经触发了,等你的News_Screen挂载完成、监听注册好的时候,事件早就过去了。下面是具体的解决步骤:
1. 把FCM监听移到App根组件,提前注册
你需要在App启动的最早期(比如app/index.js这个根组件里)就完成FCM的初始化和监听注册,而不是等到页面挂载。这样无论App是前台运行、后台唤醒还是冷启动,监听都能及时捕获事件。
根组件示例代码
import React, { Component } from 'react'; import { Platform } from 'react-native'; import FCM, { FCMEvent } from 'react-native-fcm'; import { NavigationContainer } from '@react-navigation/native'; import StackNavigator from './your-path-to/StackNavigator'; class App extends Component { navigationRef = null; componentDidMount() { // 关键:获取App冷启动/后台唤醒时的初始通知数据 FCM.getInitialNotification().then(notif => { if (notif && notif.opened_from_tray) { console.log('初始通知数据:', notif); // 处理页面跳转 if (notif.data?.screen) { this.navigationRef.navigate(notif.data.screen); } } }); // 监听常规通知事件(前台/后台唤醒的热启动场景) this.notificationListener = FCM.on(FCMEvent.Notification, notif => { console.log('收到通知:', notif); if (notif.opened_from_tray && notif.data?.screen) { this.navigationRef.navigate(notif.data.screen); } }); // 权限请求、Token获取可以统一放在这里 FCM.requestPermissions({ badge: false, sound: true, alert: true }) .catch(e => console.error('FCM权限请求失败:', e)); FCM.getFCMToken().then(token => { console.log('FCM Token:', token); // 把Token上传到你的服务器 }); if (Platform.OS === 'ios') { FCM.getAPNSToken().then(token => console.log('APNS Token:', token)); } // 监听Token刷新 this.refreshTokenListener = FCM.on(FCMEvent.RefreshToken, token => { console.log('Token刷新:', token); // 更新服务器上的Token }); } componentWillUnmount() { // 移除监听,避免内存泄漏 this.notificationListener?.remove(); this.refreshTokenListener?.remove(); } render() { return ( <NavigationContainer ref={ref => this.navigationRef = ref}> <StackNavigator /> </NavigationContainer> ); } } export default App;
2. 配置AndroidManifest(仅Android平台)
Android系统需要明确的click_action配置,才能把通知点击事件正确传递给App。
打开android/app/src/main/AndroidManifest.xml,在你的MainActivity的<intent-filter>里添加以下内容:
<intent-filter> <!-- 保留你原有的action和category,比如下面这两行 --> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <!-- 添加这两行 --> <action android:name="OPEN_ACTIVITY_1" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
然后在你发送FCM通知的payload里,必须在data字段中包含click_action,值要和上面配置的一致:
{ "to": "你的设备FCM Token", "notification": { "title": "测试通知", "body": "点击跳转页面" }, "data": { "screen": "Menu_Screen", "click_action": "OPEN_ACTIVITY_1" // 和AndroidManifest里的action名称一致 } }
3. 为什么之前的代码不行?
你之前把监听放在News_Screen的componentDidMount里,当App从后台被通知唤醒时:
- App先启动,加载根组件
- 然后加载
News_Screen,执行componentDidMount注册监听 - 但通知事件在App启动的第一步就已经触发了,此时监听还没注册,所以完全捕获不到
而FCM.getInitialNotification()就是专门用来解决这个问题的——它会返回App冷启动或后台唤醒时触发的那个初始通知数据,不管监听注册时间早晚,只要在App启动后调用就能拿到。
内容的提问来源于stack exchange,提问作者suther
相关产品推荐
相关产品推荐

