Expo通知监听器在iOS设备上无响应问题求助
问题:Expo Notifications 监听器未触发(含静默推送场景)
我正在开发一款基于Expo和React Native的iOS网页视图即时通讯应用,出于安全考虑,希望通过带有content-available字段的加密自定义参数接收推送(此时推送的body和title为空)。根据Expo通知文档,已配置addNotificationReceivedListener和addNotificationResponseReceivedListener两个监听器,但无论应用处于被杀、后台还是前台状态,addNotificationReceivedListener均未触发。测试带title/body和不带title/body(含content-available:1)的推送均无效。
相关代码
package.json
"dependencies": { "@expo/webpack-config": "^18.1.3", "@react-native-async-storage/async-storage": "^1.19.8", "@react-native-community/netinfo": "^11.1.0", "expo": "~49.0.15", "expo-constants": "~14.4.2", "expo-contacts": "~12.4.0", "expo-dev-client": "~2.4.12", "expo-device": "~5.6.0", "expo-file-system": "^15.6.0", "expo-media-library": "^15.6.0", "expo-network": "~5.6.0", "expo-notifications": "~0.20.1", "expo-splash-screen": "~0.20.5", "expo-status-bar": "~1.6.0", "react": "18.2.0", "react-dom": "^18.2.0", "react-native": "0.72.6", "react-native-fs": "^2.20.0", "react-native-share": "^10.0.1", "react-native-web": "~0.19.9", "react-native-webview": "^13.6.3", "rn-fetch-blob": "^0.12.0", "expo-background-fetch": "~11.3.0" }, "devDependencies": { "@babel/core": "^7.23.3" }
App.js
Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true, shouldPlaySound: true, shouldSetBadge: true, }), }); async function registerForPushNotificationsAsync() { let token; /*await AsyncStorage.getItem('token')*/ if (Device.isDevice && !token) { const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== 'granted') { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } if (finalStatus !== 'granted') { //alert('Failed to get push token for push notification!'); return; } token = await Notifications.getDevicePushTokenAsync(); token = token.data; } return token; } useEffect(() => { registerForPushNotificationsAsync().then((token) => { setTimeout(() => { sendPushTokenToWebView(token); }, 1000); }); notificationListener.current = Notifications.addNotificationReceivedListener((notification) => { console.log(notification) }); responseListener.current = Notifications.addNotificationResponseReceivedListener((response) => { console.log(response) }); return () => { Notifications.removeNotificationSubscription(notificationListener.current); Notifications.removeNotificationSubscription(responseListener.current); }; }, []);
解决方案
1. 修正推送Payload格式
针对iOS静默推送(带content-available),Payload必须满足Expo的严格要求:
- APS部分必须包含
"content-available": 1和"mutable-content": 1(允许Expo处理通知内容) - 必须携带Expo的
pushNotificationId字段(用于推送服务跟踪) - 若无需显示通知,需在
setNotificationHandler中将shouldShowAlert设为false
示例合规Payload:
{ "to": "你的设备推送Token", "content-available": true, "mutable-content": true, "data": { "自定义加密参数": "xxx" }, "expo": { "pushNotificationId": "uuid-xxxx-xxxx" }, "aps": { "content-available": 1, "mutable-content": 1 } }
2. 配置iOS后台推送权限
在app.json或app.config.js中添加后台模式配置,允许应用在后台接收推送:
{ "ios": { "infoPlist": { "UIBackgroundModes": ["remote-notifications"] } } }
3. 优化权限请求逻辑
确保请求完整的推送权限,包括后台权限:
const { status } = await Notifications.requestPermissionsAsync({ ios: { allowAlert: true, allowBadge: true, allowSound: true, allowAnnouncements: true, providesAppNotificationSettings: true, }, });
4. 调整监听器与Token传递逻辑
移除sendPushTokenToWebView的setTimeout,避免延迟导致的WebView接收Token不及时;监听器注册已在App启动时执行,无需调整,但可以在监听器中直接处理自定义参数并传递给WebView。
5. 规范测试方式
- 必须使用物理iOS设备测试(模拟器不支持推送)
- 应用需通过Expo Dev Client或正式打包(Expo Go限制静默推送功能)
- 若使用Expo推送服务,必须通过Expo官方API发送推送,不能直接调用APNs接口
6. 排查版本兼容问题
当前expo-notifications@0.20.1与expo@49兼容,但可尝试升级至该版本的最新补丁包,修复潜在的已知bug。
内容的提问来源于stack exchange,提问作者mostafagit
相关产品推荐
相关产品推荐

