Android 13设备OneSignal通知权限异常:无弹窗且无法获取pushToken
解决Android 13设备上OneSignal推送异常问题
问题现象
- Android 13设备启动App后,未弹出通知权限请求弹窗
- 调用
getIds方法仅能获取userId,pushToken为空,导致无法触发通知 - Android 12及以下设备可正常获取
pushToken,通知功能正常
原因分析
- Android 13权限规则变更:Android 13新增
POST_NOTIFICATIONS权限,应用必须显式请求该权限才能发送通知,旧版本OneSignal插件未适配此规则,无法自动触发权限弹窗。 - OneSignal插件版本过旧:当前使用的
onesignal-cordova-plugin@2.11.4发布于Android 13正式版之前,不支持新的通知权限机制。 - 初始化流程时序问题:
getIds在OneSignal初始化完成前调用,此时推送Token尚未生成,导致获取结果为空。 - Cordova Android平台版本不足:
cordova-android@10.1.1对Android 13的兼容性有限,需升级到支持Android 13的版本。
解决方案
1. 升级OneSignal Cordova插件
卸载旧版本并安装适配Android 13的最新稳定版(3.x及以上版本已支持):
cordova plugin remove onesignal-cordova-plugin cordova plugin add onesignal-cordova-plugin@latest
2. 升级Cordova Android平台
Android 13需要cordova-android@11.0.0及以上版本支持:
cordova platform remove android cordova platform add android@11.0.0
3. 显式请求Android 13通知权限
使用@awesome-cordova-plugins/android-permissions在OneSignal初始化前主动请求POST_NOTIFICATIONS权限,修改onesignal.service.ts:
import { AndroidPermissions } from '@awesome-cordova-plugins/android-permissions/ngx'; // 在构造函数中注入AndroidPermissions constructor( private oneSignal: OneSignal, private platform: Platform, private globalVar: GlobalvariableService, private loadingController: LoadingController, private storage: AppStorageService, private navCtrl: NavController, private popoverCtrl: PopoverController, public alrtCrtl: AlertController, private router: Router, private androidPermissions: AndroidPermissions // 新增注入 ) {} async OneSignalNotification() { await this.platform.ready().then(async () => { if (this.platform.is('cordova') && this.platform.is('android')) { // 检查并请求Android 13通知权限 const permissionStatus = await this.androidPermissions.checkPermission( this.androidPermissions.PERMISSION.POST_NOTIFICATIONS ); if (!permissionStatus.hasPermission) { const requestResult = await this.androidPermissions.requestPermission( this.androidPermissions.PERMISSION.POST_NOTIFICATIONS ); if (!requestResult.hasPermission) { console.log('通知权限被拒绝,请手动开启'); return; } } } if (this.platform.is('cordova')) { await this.oneSignal.startInit(this.globalVar.oneSignalAppId, this.globalVar.oneSignalSenderId); this.oneSignal.handleNotificationReceived().subscribe((msg) => { console.log('Notification received'); console.dir(msg); }); this.oneSignal.handleNotificationOpened().subscribe((msg) => { console.log('Notification opened'); let notification_obj = msg.notification.payload.additionalData; if (notification_obj) { this.globalVar.loginInfo !== '' ? this.fnOpenNotification(notification_obj) : this.navCtrl.navigateRoot('login'); } }); this.oneSignal.inFocusDisplaying(this.oneSignal.OSInFocusDisplayOption.Notification); // 初始化完成后再获取ID this.oneSignal.endInit().then(() => { this.OneSignalPlayerID(); }); } else { this.globalVar.playerId = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX'; } }); }
4. 优化getIds调用时机与监听逻辑
将OneSignalPlayerID移到endInit()回调中,确保插件完全初始化后再获取Token;同时添加订阅变更监听,实时获取Token更新:
// 修改OneSignalNotification中的endInit部分 this.oneSignal.endInit().then(() => { this.OneSignalPlayerID(); // 添加订阅变更监听 this.oneSignal.addSubscriptionObserver().subscribe((state) => { if (state.subscription.status === 'subscribed') { console.log('更新Push Token:', state.subscription.userId); this.globalVar.playerId = state.subscription.userId; this.storage.set('player_id', this.globalVar.playerId); } }); });
验证步骤
- 重新编译并安装App到Android 13设备
- 启动App,确认通知权限请求弹窗正常弹出
- 授权后查看日志,确认
getIds输出中pushToken已正常获取 - 测试推送通知,确认可正常接收
内容的提问来源于stack exchange,提问作者AziDev
相关产品推荐
相关产品推荐

