Flutter iOS真机调用FirebaseMessaging.getAPNSToken()返回null
Flutter iOS真机无法获取APNS Token,模拟器正常的问题
问题现象
调用FirebaseMessaging.instance.getToken()时触发firebase_messaging/apns-token-not-set错误,转而调用FirebaseMessaging.instance.getAPNSToken():
- iPhone 15模拟器能正常获取APNS Token
- 有线连接Mac的真机、TestFlight安装的同一真机均返回null
代码实现
初始化通知的核心代码:
Future<void> initNotifications() async { await FirebaseMessaging.instance.setAutoInitEnabled(true); final permissionRequest = await FirebaseMessaging.instance.requestPermission( alert: true, announcement: false, badge: true, carPlay: false, criticalAlert: false, provisional: false, sound: true, ); if (permissionRequest.authorizationStatus == AuthorizationStatus.authorized) { String? fcmToken; if (Platform.isIOS) { String? apnsToken = await FirebaseMessaging.instance.getAPNSToken(); if (apnsToken != null) { debugPrint("APNS Token: $apnsToken"); fcmToken = await FirebaseMessaging.instance.getToken(); debugPrint("FCM Token: $fcmToken"); } else { debugPrint("APNS Token not available, waiting ..."); await Future<void>.delayed( const Duration( seconds: 3, ), ); apnsToken = await FirebaseMessaging.instance.getAPNSToken(); if (apnsToken != null) { debugPrint("APNS Token: $apnsToken"); fcmToken = await FirebaseMessaging.instance.getToken(); debugPrint("FCM Token: $fcmToken"); } else { debugPrint("APNS Token not available, trying to get FCM token anyway ..."); try { fcmToken = await FirebaseMessaging.instance.getToken(); } catch (err) { debugPrint("FCM Token not available ($err)"); } } } } else { fcmToken = await FirebaseMessaging.instance.getToken(); debugPrint("FCM Token: $fcmToken"); } } else { debugPrint("Notifications not authorized"); } }
main.dart中的调用逻辑:
WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); await FireBaseNotifications().initNotifications();
已完成的配置
- Xcode:启用Push Notifications;Background Modes勾选Background fetch、Remote notifications
- Firebase控制台:已上传开发、生产环境的APNs证书
- 依赖版本:
firebase_core: ^2.20.0 firebase_messaging: ^14.7.2
排查与解决建议
1. 证书与Provisioning Profile校验
- 确认真机使用的Provisioning Profile包含Push Notifications权限,且对应证书与Firebase控制台上传的完全一致(开发环境用开发证书,TestFlight/生产用生产证书)
- 检查Xcode中Signing & Capabilities的Provisioning Profile是否有效、未过期,Bundle ID与Firebase控制台的iOS应用完全匹配(大小写一致)
2. 系统权限检查
- 真机端进入「设置→通知→你的应用」,确认通知权限已完全开启(包括允许通知、横幅/声音等选项)
- 若用户首次弹窗时拒绝了权限,代码中未处理重新请求逻辑,需手动开启权限后重试
3. APNs环境匹配
- Debug调试(有线连接)对应开发APNs环境,TestFlight/Release对应生产环境,确保Firebase控制台中对应环境的证书已正确上传并激活
- 检查
DefaultFirebaseOptions中的iOS配置,apnsEnvironment是否与当前运行环境匹配(开发环境设为APNSEnvironment.development,生产设为APNSEnvironment.production)
4. 代码逻辑优化
- 无需手动获取APNS Token再请求FCM Token,FCM SDK会自动处理APNS Token的绑定,改用监听
onTokenRefresh事件更可靠:// 监听Token刷新 FirebaseMessaging.instance.onTokenRefresh.listen((newToken) { debugPrint("FCM Token refreshed: $newToken"); // 将Token同步到服务器 }); // 首次获取Token String? initialToken = await FirebaseMessaging.instance.getToken(); if (initialToken != null) { debugPrint("Initial FCM Token: $initialToken"); } - 固定延迟重试的逻辑不可靠,APNS Token由系统异步返回,监听回调是更合理的方式
5. Xcode深层配置检查
- 手动确认
Info.plist中已添加UIBackgroundModes并包含remote-notification(勾选Background Modes后Xcode会自动添加,可右键Info.plist→Open As→Source Code查看) - 确保Xcode项目的Build Settings中,
ENABLE_BITCODE设为NO(部分旧版本Firebase SDK对此有要求)
6. 网络与系统环境
- 真机需正常连接苹果APNS服务器,避免使用代理或处于受限网络环境
- 确保iOS系统版本在13.0以上,尽量使用较新版本系统,避免SDK与系统兼容性问题
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

