如何检测真正的 iOS/APNS 推送令牌何时向 Firebase Cloud Messaging (FCM) 注册?

Posted

技术标签:

【中文标题】如何检测真正的 iOS/APNS 推送令牌何时向 Firebase Cloud Messaging (FCM) 注册?【英文标题】:How can I detect when the real iOS/APNS push token is registered with Firebase Cloud Messaging (FCM)? 【发布时间】:2020-07-23 00:25:34 【问题描述】:

Firebase 的didReceiveRegistrationToken 如下所示,即使用户未授予推送通知权限,也会被调用。我需要确保正在注册 APNS 推送令牌以进行分析,并将其保存在我的服务器上,但即使用户未授予推送权限,也会调用此函数。 ????‍♂️

/**
 * Requirement for Firebase push notifications.
 * See documentation here: https://firebase.google.com/docs/cloud-messaging/ios/client
 */
extension AppDelegate: MessagingDelegate 
    // Note: This callback is fired at each app startup and whenever a new token is generated.
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) 
        print("Firebase registration token: \(fcmToken)")
        let dataDict: [String: String] = ["token": fcmToken]
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        print("Getting called even if the user hasn't opted in for push notifications!")
    

【问题讨论】:

【参考方案1】:

TL;DR:FCM 令牌不是检测 APNS 令牌是否已注册的可靠方法。 Disable method swizzling in firebase and listen to APNS registration manually.

    FCM 令牌: FCM 令牌也称为设备实例 ID;它标识该特定设备上的特定应用程序。换句话说,FCM 令牌不等于 APNS 令牌。这是一种解释:APNs, FCM or GCM token。

    FCM 令牌自动生成:令人惊讶的是,即使没有 iOS 用户授予权限,Firebase 也会在应用启动时生成 FCM 令牌。我猜它想找到一种方法来识别应用程序和设备对,所以一旦你启动,你就会有一个 FCM 令牌。如果您愿意,您可以disable auto-generation 并等待用户选择加入。

默认情况下,FCM SDK 在应用启动时为客户端应用实例生成一个注册令牌。如果您想在使用实例 ID 之前获得明确的选择加入,您可以通过禁用 FCM 来防止在配置时生成。为此,请将元数据值添加到您的 Info.plist(而不是您的 GoogleService-Info.plist):

这就是问题之一! 即使用户禁用了 FCM 令牌的自动生成,当提示用户启用推送通知时也会生成一个,而不是在用户接受推送通知权限时。这看起来很奇怪,我结束了向上报告这个 Firebase。

    APNS Token Swizzling:所以默认情况下 Firebase 会接管 AppDelegate 的 didRegisterForRemoteNotificationsWithDeviceToken(称为“swizzling”)。您可以禁用它并自己覆盖委托方法。 这将使您能够访问 APNS 令牌和 FCM 令牌。
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 
    print("Successfully registered for notifications!")
    // Required to make FCM work since we disabled swizzling!
    Messaging.messaging().apnsToken = deviceToken
    // String version of APNS so we can use save it/use it later/do analytics.
    let apnsToken = deviceToken.map  String(format: "%02.2hhx", $0) .joined()

【讨论】:

【参考方案2】:

获取设备 ID 令牌的回调和获取实际推送消息的回调是两件不同的事情。设备 ID 令牌回调只是为您提供一个标识设备的令牌,以便稍后推送通知。它实际上并不是推送通知本身。这只是一个 ID。

也就是说,如果您从安全角度不同意客户端 SDK 的行为,您可以随时 contact Firebase support directly 提供反馈。

【讨论】:

可能我的问题不清楚,我不是在寻找设备 ID,我想知道 APNS 推送令牌何时注册。 您能否编辑问题以说明为什么重要?在实际发送消息时,是否有一些事情没有按照您期望的方式工作?您是否遇到了潜在的安全漏洞? 已更新,如果更清楚请告诉我;在这一点上,安全不是问题。 好吧,我已经解释了为什么它会被调用。如果这对您来说不是问题,那么我会将其排除在问题描述之外。现在您还说它经常被调用?你认为它应该多久被调用一次?我无法解决您的真正问题。 也许我们在这里使用了两种不同的术语。您相当于“设备 ID 令牌”的是我的“APNS 推送令牌”;这实际上是我关心的,但是即使用户没有接受 iOS 上的推送通知权限,didReceiveRegistrationToken 也会给我这个 ID?为了确保我们在同一个页面上,我不关心推送消息或实际通知。

以上是关于如何检测真正的 iOS/APNS 推送令牌何时向 Firebase Cloud Messaging (FCM) 注册?的主要内容,如果未能解决你的问题,请参考以下文章

通过 FCM 发送推送通知时何时使用 iOS 设备令牌?

iOS 开发/生产推送证书:何时以及如何?

何时分配设备令牌?

iOS apns推送

iOS APNS 的 Expo 推送通知

解析,如何向目标用户发送推送通知