Expo推送通知在独立APK中失效,Expo Go环境下正常运行
Expo 独立APK中通知权限请求失败问题
我从Expo官方文档复制了完整的推送通知代码(如下),但遇到了权限请求的问题:Notifications.requestPermissionsAsync()在Expo Go环境中能正常工作(通知功能激活时),但打包成独立APK后,权限状态始终返回denied,无法完成权限请求流程。
import { useState, useEffect, useRef } from 'react'; import { Text, View, Button, Platform } from 'react-native'; import * as Device from 'expo-device'; import * as Notifications from 'expo-notifications'; import Constants from 'expo-constants'; Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true, shouldPlaySound: false, shouldSetBadge: false, }), }); // 可使用下方函数或Expo推送通知工具 async function sendPushNotification(expoPushToken) { const message = { to: expoPushToken, sound: 'default', title: 'Original Title', body: 'And here is the body!', data: { someData: 'goes here' }, }; await fetch('https://exp.host/--/api/v2/push/send', { method: 'POST', headers: { Accept: 'application/json', 'Accept-encoding': 'gzip, deflate', 'Content-Type': 'application/json', }, body: JSON.stringify(message), }); } async function registerForPushNotificationsAsync() { let token; if (Device.isDevice) { 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.getExpoPushTokenAsync({ projectId: Constants.expoConfig.extra.eas.projectId, }); console.log(token); } else { alert('Must use physical device for Push Notifications'); } if (Platform.OS === 'android') { Notifications.setNotificationChannelAsync('default', { name: 'default', importance: Notifications.AndroidImportance.MAX, vibrationPattern: [0, 250, 250, 250], lightColor: '#FF231F7C', }); } return token; } export default function App() { const [expoPushToken, setExpoPushToken] = useState(''); const [notification, setNotification] = useState(false); const notificationListener = useRef(); const responseListener = useRef(); useEffect(() => { registerForPushNotificationsAsync().then(token => setExpoPushToken(token)); notificationListener.current = Notifications.addNotificationReceivedListener(notification => { setNotification(notification); }); responseListener.current = Notifications.addNotificationResponseReceivedListener(response => { console.log(response); }); return () => { Notifications.removeNotificationSubscription(notificationListener.current); Notifications.removeNotificationSubscription(responseListener.current); }; }, []); return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'space-around' }}> <Text>Your expo push token: {expoPushToken}</Text> <View style={{ alignItems: 'center', justifyContent: 'center' }}> <Text>Title: {notification && notification.request.content.title} </Text> <Text>Body: {notification && notification.request.content.body}</Text> <Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text> </View> <Button title="Press to Send Notification" onPress={async () => { await sendPushNotification(expoPushToken); }} /> </View> ); }
解决方法
1. 完善app.json中的权限配置
确保你的app.json(或app.config.js)中已经声明了必要的通知权限,尤其是Android 13及以上版本需要的POST_NOTIFICATIONS权限:
{ "expo": { "android": { "permissions": [ "POST_NOTIFICATIONS", "VIBRATE" ] }, "notifications": { "icon": "./assets/notification-icon.png", "color": "#ffffff", "androidMode": "default", "androidCollapsedTitle": "# Your notification title" } } }
2. 升级expo-notifications依赖
Android 13+的通知权限属于运行时权限,旧版本的expo-notifications可能存在适配问题,升级到最新稳定版:
npx expo install expo-notifications@latest
3. 优化权限失败后的引导逻辑
当权限请求被拒绝后,引导用户手动跳转到应用设置页开启权限,修改registerForPushNotificationsAsync中的失败处理部分:
// 导入Alert和Linking import { Alert, Linking } from 'react-native'; // ... if (finalStatus !== 'granted') { Alert.alert( '通知权限未开启', '请前往应用设置开启通知权限,否则无法接收推送通知', [ { text: '取消' }, { text: '去设置', onPress: () => Linking.openSettings() } ] ); return; }
4. 检查EAS构建配置
如果使用EAS Build打包,确保eas.json中未禁用通知相关服务(默认已开启,可确认配置完整性)。
内容的提问来源于stack exchange,提问作者Spargens
相关产品推荐
相关产品推荐

