独立Apple tvOS应用无法通过FCM展示通知的技术问题
tvOS应用集成Firebase Messaging后无法展示通知的排查方案
问题背景
开发独立tvOS应用,已完成FCM与APNS配置,但集成Firebase Messaging后无法展示通知,相关代码、控制台输出及环境信息如下:
集成代码
import SwiftUI import Firebase class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate { @AppStorage("fcmToken") var fToken = "" let gcmMessageIDKey = "gcm.message_id" func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.banner, .badge, .sound]) } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FirebaseApp.configure() // Register for remote notifications let notificationCenter = UNUserNotificationCenter.current() notificationCenter.delegate = self notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } } Messaging.messaging().delegate = self return true } // MARK: - Push Notifications func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken let deviceTokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() print("APNS device token: \(deviceTokenString)") } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("Failed to register for remote notifications with error: \(error.localizedDescription)") } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { if userInfo[gcmMessageIDKey] != nil { print("Received data message: \(userInfo)") completionHandler(.newData) } } // MARK: - Messaging func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { guard let fcmToken = fcmToken else { return } fToken = fcmToken print("FCM token: \(fcmToken)") } } @main struct SomeExampleApp_TVApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } }
控制台输出
2023-04-24 20:04:46.212321+0530 SomeExampleApp[1262:39696] void * _Nullable NSMapGet(NSMapTable * _Nonnull, const void * _Nullable): map table argument is NULL 2023-04-24 20:04:46.221547+0530 SomeExampleApp[1262:39865] 9.6.0 - [FirebaseMessaging][I-FCM002022] APNS device token not set before retrieving FCM Token for Sender ID '012849237482'. Notifications to this FCM Token will not be delivered over APNS.Be sure to re-retrieve the FCM token once the APNS device token is set. FCM token: someFcmToken 2023-04-24 20:04:48.650580+0530 SomeExampleApp[1262:39858] [] nw_path_necp_check_for_updates Failed to copy updated result (22) FCM token: someFcmToken APNS device token: someApnToken Received data message: [AnyHashable("aps"): { alert = { body = "Entry Lights turned on as you entered Office"; title = "Location Automation"; }; "content-available" = 1; }, AnyHashable("google.c.a.e"): 1, AnyHashable("google.c.sender.id"): 984386421852, AnyHashable("google.c.fid"): citAzVs8zUeFtNaj_EZJmN, AnyHashable("gcm.message_id"): 1682346907169586] Received data message: [AnyHashable("google.c.a.e"): 1, AnyHashable("gcm.message_id"): 1682347026515009, AnyHashable("aps"): { alert = { body = "Entry Lights turned on as you entered Office"; title = "Location Automation"; }; "content-available" = 1; }, AnyHashable("google.c.fid"): citAzVs8zUeFtNaj_EZJmN, AnyHashable("google.c.sender.id"): 012849237482] Received data message: [AnyHashable("aps"): { alert = { body = "Entry Lights turned on as you entered Office"; title = "Location Automation"; }; "content-available" = 1; }, AnyHashable("google.c.sender.id"): 984386421852, AnyHashable("gcm.message_id"): 1682347042989389, AnyHashable("google.c.a.e"): 1, AnyHashable("google.c.fid"): citAzVs8zUeFtNaj_EZJmN]
环境信息
- Firebase SDK版本:9.6.0
- Xcode版本:14.2 (14C18)
- 安装方式:Swift Package Manager
- 使用的Firebase产品:Messaging
- 目标平台:tvOS
排查与解决方案
- 修复FCM Token与APNS Token同步问题
控制台提示APNS device token not set before retrieving FCM Token,说明FCM Token先于APNS Token获取,导致该Token无法通过APNS推送通知。在didRegisterForRemoteNotificationsWithDeviceToken方法中添加主动刷新FCM Token的逻辑:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken let deviceTokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() print("APNS device token: \(deviceTokenString)") // 主动刷新FCM Token Messaging.messaging().token { token, error in if let error = error { print("Error fetching FCM registration token: \(error)") } else if let token = token { print("Refreshed FCM token: \(token)") self.fToken = token } } }
- 补充后台通知处理代理方法
当前仅实现了前台展示通知的willPresent方法,缺少后台/未启动状态下的通知处理方法,添加以下代码:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 可添加通知点击后的业务逻辑 completionHandler() }
- 调整通知负载格式
tvOS对通知负载有特定要求:
- 确保
aps字典中alert的title和body字段非空 - 若仅需展示通知而非静默更新,移除
content-available=1字段;保留则需确保应用开启后台刷新权限 - 确认FCM发送的是通知消息而非数据消息,数据消息不会自动触发系统通知弹窗
- 验证配置一致性
- 检查Firebase控制台的APNS证书环境(开发/生产)与Xcode打包配置匹配
- 确认Xcode项目的
Bundle Identifier与Firebase应用的Bundle ID完全一致 - 核实控制台中出现的两个Sender ID均已正确配置关联
- 升级Firebase SDK版本
当前9.6.0版本存在部分tvOS适配问题,建议升级至最新稳定版,修复已知的推送同步bug。
内容的提问来源于stack exchange,提问作者Sayan Chakraborty
相关产品推荐
相关产品推荐

