Flutter iOS端无法运行FCM:APNS Token未设置问题求助
核心问题
你遇到的错误:
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: [firebase_messaging/apns-token-not-set] APNS token has not been set yet. Please ensure the APNS token is available by calling
getAPNSToken().
本质是Flutter调用getAPNSToken()时,iOS原生端的APNS Token未同步到Firebase Messaging实例,或权限、配置环节存在疏漏。以下是针对性修复方案:
1. 先请求推送权限,再处理Token
iOS要求必须获得用户推送权限授权后,才能获取APNS Token。你的Flutter代码直接调用getAPNSToken(),缺少权限请求逻辑,导致Token获取失败。
修改Flutter的main函数:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // 先请求推送权限 NotificationSettings settings = await FirebaseMessaging.instance.requestPermission( alert: true, badge: true, sound: true, provisional: false, ); // 权限授权后再监听Token if (settings.authorizationStatus == AuthorizationStatus.authorized) { // 通过监听获取Token(异步回调,避免同步调用的时序问题) FirebaseMessaging.instance.onTokenRefresh.listen((String token) { print('APNS Token 更新: $token'); }); // 尝试获取当前Token(仅作辅助,核心依赖onTokenRefresh) String? apnsToken = await FirebaseMessaging.instance.getAPNSToken(); apnsToken != null ? print('当前APNS Token: $apnsToken') : null; } runApp(MyApp(settings: {})); }
2. 调整AppDelegate的初始化与Token绑定逻辑
原生端的didRegisterForRemoteNotificationsWithDeviceToken回调可能未触发,或Firebase初始化顺序有误。修改Swift代码:
import Flutter import UIKit import Firebase import FirebaseMessaging @main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 优先执行Flutter原生初始化 super.application(application, didFinishLaunchingWithOptions: launchOptions) // 初始化Firebase FirebaseApp.configure() // 注册Flutter插件 GeneratedPluginRegistrant.register(with: self) // 主动触发远程通知注册 UNUserNotificationCenter.current().delegate = self application.registerForRemoteNotifications() return true } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { // 绑定APNS Token到Firebase Messaging Messaging.messaging().apnsToken = deviceToken // 打印Token用于验证 let tokenParts = deviceToken.map { String(format: "%02.2hhx", $0) } let token = tokenParts.joined() print("APNS Device Token: \(token)") } override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { // 打印注册失败信息,排查权限问题 print("远程通知注册失败: \(error.localizedDescription)") } }
3. 检查iOS项目Capabilities配置
确保项目开启推送相关核心权限:
- 打开Xcode,进入项目
Target→Signing & Capabilities - 添加
Push Notifications能力 - 添加
Background Modes能力,并勾选Remote notifications - 确认Bundle ID与Firebase控制台配置完全一致
4. 验证APNS证书/密钥有效性
- 确认Firebase控制台上传的APNS证书(或密钥)匹配当前环境:开发环境用Development证书,生产环境用Production证书
- 检查证书有效期,以及是否与项目Bundle ID绑定
- 若使用APNS Auth Key,确认Key ID和Team ID在Firebase配置中填写正确
5. 避免同步调用getAPNSToken()
didRegisterForRemoteNotificationsWithDeviceToken是异步回调,Flutter启动时可能尚未执行完成,此时同步调用getAPNSToken()会返回空值触发错误。核心依赖onTokenRefresh监听Token的获取与更新即可。
内容的提问来源于stack exchange,提问作者lulliezy

