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

如何在Firebase中先获取APNs再获取FCM Token?报错求助

问题排查:APNS Device Token未设置时获取FCM Token错误

问题描述

APNS device token not set before retrieving FCM Token for Sender ID 'XXXX'. Be sure to re-retrieve the FCM token once the APNS device token is set.

今日12点前未出现该错误,调试9小时未找到问题根源。

当前环境

  • Xcode 16
  • Firebase 10.27
  • 运行设备:iPhone 15 Pro Max

现有配置

  • 已开启后台模式(后台获取、处理、远程通知)
  • Firebase控制台Cloud Messaging已配置APNs密钥
  • 应用已添加至Firebase服务器
  • 项目包含Google Info.plist
  • 已注册App Attest(AppCheck)和DeviceCheck

相关代码(AppDelegate)

// This method gets called when the app successfully registers for remote notifications and receives a device token from APNs
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().apnsToken = deviceToken
        print("APNs Device Token: \(deviceToken)")

       // Fetch the FCM registration token (this token is used to send push notifications through Firebase)
       Messaging.messaging().token { token, error in
           if let error = error {
               print("Error fetching FCM registration token: \(error)")
           } else if let token = token {
               print("FCM registration token: \(token)")
           }
       }
   }

   // This method is called when the app finishes launching
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Initialize Firebase
    FirebaseApp.configure()
    
    // Log app open event (for Firebase Analytics)
    FirebaseAnalytics.Analytics.logEvent(AnalyticsEventAppOpen, parameters: nil)
    
    // Set the delegate for Firebase Messaging
    Messaging.messaging().delegate = self
    
    // Register for remote notifications
    application.registerForRemoteNotifications()
    
    // Request notification authorization from the user
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
        if granted {
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    
    // Set UNUserNotificationCenter delegate
    UNUserNotificationCenter.current().delegate = self
    
    return true
}


func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    if let fcm = Messaging.messaging().fcmToken {
        print("fcm", fcm)
    }
}

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    handleDailyReportTrigger()
    completionHandler([.banner, .sound, .badge])
}

排查与解决步骤

1. 修复重复注册远程通知的逻辑

在didFinishLaunchingWithOptions中,两次调用registerForRemoteNotifications()会导致APNs注册流程混乱,可能引发时序问题。修改为仅在授权成功后注册:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    FirebaseApp.configure()
    FirebaseAnalytics.Analytics.logEvent(AnalyticsEventAppOpen, parameters: nil)
    Messaging.messaging().delegate = self
    UNUserNotificationCenter.current().delegate = self
    
    // 先请求用户授权,再注册远程通知
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
        if granted {
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    
    return true
}

2. 让FCM自动处理Token生成

Firebase的Messaging代理方法didReceiveRegistrationToken会在APNs Token设置完成后自动刷新FCM Token,无需手动调用Messaging.messaging().token,避免时序冲突:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().apnsToken = deviceToken
    print("APNs Device Token: \(deviceToken)")
}

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    guard let fcmToken = fcmToken else {
        print("FCM Token获取失败")
        return
    }
    print("FCM registration token: \(fcmToken)")
    // 此处可添加将Token上传至自有服务器的逻辑
}

3. 检查配置与环境

  • 验证APNs密钥有效性:登录Apple开发者后台,确认APNs密钥未过期,若过期重新生成并更新到Firebase控制台。
  • 清理Xcode缓存:执行Cmd+Shift+K清理项目缓存,删除DerivedData后重新编译运行。
  • 确认App Check状态:检查Firebase控制台中App Attest/DeviceCheck的配置是否正常,Info.plist中相关配置项无误。
  • 测试网络状态:确保测试设备网络稳定,FCM Token获取依赖网络连接,波动可能导致时序异常。

4. 验证冷启动场景

修改后冷启动应用,会先完成用户授权,再注册APNs,设置Token后由Firebase自动生成FCM Token,可有效避免提前获取Token的问题。

内容的提问来源于stack exchange,提问作者user25626237

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 06:22:37