React Native中react-native-push-notification后台推送问题求助
解决React Native后台/未运行状态下推送通知接收与点击跳转问题
你已经搞定了前台接收通知的逻辑,接下来咱们把后台和未运行状态的推送问题也解决掉,同时确保点击通知能正常打开APP。结合你用的react-native-push-notification和Firebase云函数,我给你梳理几个关键调整点:
1. 先搞懂FCM的两种消息类型
FCM推送分通知消息和数据消息,不同APP状态下的处理逻辑完全不一样:
- 通知消息:由FCM SDK直接展示,APP未运行时不会触发
onNotification回调,只有用户点击通知才会启动APP并传递数据。 - 数据消息:不管APP处于前台、后台还是未运行状态,都会把数据传递到
onNotification,需要你自己处理通知展示逻辑。
你的Firebase payload同时包含了notification和data字段,这会导致后台/未运行时FCM优先处理notification字段,和你预期的逻辑冲突,咱们先调整payload格式。
2. 调整Firebase云函数的Payload
删掉notification字段,只用data字段(这样无论APP状态如何,数据都会传递到你的回调里),同时补全必要参数:
export const sendNotificationTest = functions.https.onRequest(async (req, res) => { try { const { token } = req.body; let targetToken = "coeC4T6tmeU:APA91bGEQs4MRQXq4C09SKpyK2Oxz7gIKS-QdoGGKeCcxQj2CXGpCD7qe763WnFVgQRer81iZGscASVq-QP7_I81xtCM9vfiPitQJ4P6HFSH3QiGQQljiLPBixsVcCtbDNCZX4z4u8n-" let payload = { data: { title: "Alarm", body: "First Alarm", subtitle: "First Alarm", color: "#00ACD4", priority: "high", icon: "ic_notif", show_in_foreground: 'true', channelId:'sqtrivia-channel', click_action: "OPEN_APP_ACTION" // 自定义action,后续Android配置要对应 } }; // 发送推送(补全你的发送逻辑) await admin.messaging().sendToDevice(targetToken, payload); res.status(200).send("Notification sent successfully"); } catch (error) { console.error(error); res.status(500).send("Error sending notification"); } });
3. 优化react-native-push-notification配置
你的初始化逻辑有些冗余,咱们简化并调整关键配置:
修改initPushNotification方法
initPushNotification() { console.log('Initializing push notification') // 先创建Android通知渠道(8.0+必须) PushNotification.createChannel( { channelId: "sqtrivia-channel", // 和payload里的channelId保持一致 channelName: "SQ Trivia Notifications", channelDescription: "Notifications for SQ Trivia app", soundName: "default", importance: 4, vibrate: true, }, (created) => console.log(`Notification channel created: ${created}`) ); PushNotification.configure({ onRegister: function (token) { AppStore.setFCMToken(token.token) FirebaseService.setTokenData(token.token) }, onNotification: function (notification) { console.log('Received notification data:', notification); // 统一处理通知展示:不管前台后台,都调用localNotification弹出 if (notification.data) { const { title, body, subtitle, color, channelId } = notification.data; PushNotification.localNotification({ id: '0', autoCancel: true, largeIcon: "ic_launcher", smallIcon: "ic_notification", bigText: body, subText: subtitle, color: color, vibrate: true, vibration: 300, // iOS专属配置 title: title, message: body, playSound: false, // Android专属配置 channelId: channelId, actions: '["Yes", "No"]', }); } // 处理用户点击通知的逻辑:比如跳转到指定页面 if (notification.userInteraction) { // 示例:navigation.navigate('NotificationDetail'); } // iOS必须调用finish方法 if (notification.finish) { notification.finish(PushNotificationIOS.FetchResult.NoData); } }, senderID: "XXXXXXXXXX1", permissions: { alert: true, badge: true, sound: true }, popInitialNotification: true, // 冷启动时自动处理初始通知 requestPermissions: true, }); }
简化initEventPushNotification方法
原来的AppState监听里重复调用popInitialNotification没必要,因为配置里已经开启了自动处理,只保留必要的badge清零逻辑即可:
initEventPushNotification() { AppState.addEventListener('change', (state) => { console.log('App state changed:', state); if (state === 'background') { PushNotification.setApplicationIconBadgeNumber(0); } }); }
4. 平台专属配置(重中之重!)
Android配置
修改AndroidManifest.xml,确保点击通知能打开APP且不重复启动:
<activity android:name=".MainActivity" android:launchMode="singleTop" <!-- 关键:避免重复打开APP实例 --> ...> <intent-filter> <action android:name="OPEN_APP_ACTION" /> <!-- 和payload里的click_action一致 --> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
iOS配置
- 在Xcode中开启
Capabilities里的Push Notifications。 - 开启
Background Modes下的Remote notifications选项,确保后台能接收推送数据。
5. 测试要点
- 后台测试:把APP退到后台,发送推送,检查通知是否展示,点击是否能打开APP。
- 冷启动测试:完全杀死APP,发送推送,检查通知是否弹出,点击是否能启动APP并触发
onNotification。 - 日志排查:用
adb logcat(Android)或Xcode控制台(iOS)查看推送相关日志,定位可能的错误。
内容的提问来源于stack exchange,提问作者Manspof
相关产品推荐
相关产品推荐

