You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter iOS端无法运行FCM:APNS Token未设置问题求助

Flutter FCM iOS端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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:07:22