单个iOS应用程序安装是否可以同时具有两个有效的APNS令牌?

huangapple go评论65阅读模式
英文:

Can a single iOS app installation have two valid apns tokens simultaneously?

问题

这条评论说:

静默推送是你的服务器在需要时唯一能够让你的应用发送一些数据的方式。但这仅在你已经有一个有效的令牌时才有效。

这意味着要定期获取最新的有效 APNS 令牌,一旦用户停止启动应用程序:(1)远程服务器使用它在先前的应用启动中获取的令牌 X 发送一个静默推送,然后(2)静默推送导致应用程序的代码运行,从 APNS 库获取令牌 Y 并将其发送到远程服务器。

如果令牌 X != 令牌 Y,以下哪种情况是正确的:

  • 令牌 X 和令牌 Y 在同一时间都是有效的
  • 一旦应用程序获取到令牌 Y,令牌 X 就会变为无效
  • 上述描述的情况(步骤 1 和步骤 2)不可能发生
英文:

This comment says:
> silent push is the only way that your server can make your app send some data whenever it needs. But this works only when you already have a valid token.

This implies that to periodically get the latest valid apns token once the user stops launching the app: (1) The remote server sends a silent push using token X it got from an earlier app launch, then (2) the silent push causes the app's code to run which gets the token Y from apns library and sends it to the remote server.

If token X != token Y, which of these is true:

  • token X and token Y are both valid at the same time
  • as soon as the app gets token Y, token X becomes invalid
  • the scenario described above (Steps 1 and 2) is not possible

答案1

得分: 1

每当应用程序启动时,您必须发送更新的令牌以对应用户,以确保一个用户只有一个 FCM 令牌的方式,一旦您实现了静默通知,有一些非常重要的要点。

  1. 即使应用程序在前台运行,application(_:didReceiveRemoteNotification:fetchCompletionHandler:) 代理方法仍会触发。

  2. 静默推送通知会唤醒已终止的应用程序。因此,application(_:didFinishLaunchingWithOptions:) 代理方法和初始视图控制器的 viewDidLoad() 方法也会被触发。

  3. 静默推送通知触发的后台操作将具有大约 30 秒 的执行时间。

extension AppDelegate: MessagingDelegate {
    // 一旦您获得新令牌,此代理方法将被调用,您需要更新服务器上的用户令牌
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        let params = ["fcmToken": token, "deviceType": "ios"]
        APIClient.updateFCM(userID: user.ID, bodyParams: params).done { (response) in
            // 处理响应
        }
    }
    
    func setFirebasePushNotification() {
        Messaging.messaging().delegate = self
        
        if #available(iOS 10.0, *) {
            // 为 iOS 10 显示通知(通过 APNS 发送)
            UNUserNotificationCenter.current().delegate = self
            
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in }
        } else {
            let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            UIApplication.shared.registerUserNotificationSettings(settings)
        }
        
        UIApplication.shared.registerForRemoteNotifications()
    }
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        setFirebasePushNotification()
        return true
    }
}

请参考以下链接以供参考:

英文:

whenever the app lauches then you have to send updated token against that user so there is no way of two FCM token against one user, once you implement slient notification there are a few points that are very important.

  1. The application(_:didReceiveRemoteNotification:fetchCompletionHandler:) delegate method will still trigger even though the app is in the foreground.

  2. The silent push notification will wake up a terminated app. As a result, the application(_:didFinishLaunchingWithOptions:) delegate method and the initial view controller’s viewDidLoad() method will be triggered as well.

  3. The background operation triggered by a silent push notification will have roughly 30 seconds of execution time.

    extension AppDelegate: MessagingDelegate
    {
    // Once you get new token this delegate call and you need to update user token on server
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {

     	let params = ["fcmToken":token,"deviceType":"ios"]
     	APIClient.updateFCM(userID:user.ID , bodyParams:params).done { (response) in
    
    
     	}
     }	
    
     func setFirebasePushNotification(){
    
         Messaging.messaging().delegate = self
    
         if #available(iOS 10.0, *) {
             // For iOS 10 display notification (sent via APNS)
             UNUserNotificationCenter.current().delegate = self
    
             let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
             UNUserNotificationCenter.current().requestAuthorization(
                 options: authOptions,
                 completionHandler: {_, _ in })
         } else {
             let settings: UIUserNotificationSettings =
             UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
             UIApplication.shared.registerUserNotificationSettings(settings)
         }
    
         UIApplication.shared.registerForRemoteNotifications()
     }
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     	setFirebasePushNotification()
     }
    

    }

Please check these links for reference.

https://swiftsenpai.com/testing/send-silent-push-notifications/

https://swiftsenpai.com/testing/send-silent-push-notifications/

答案2

得分: -1

答案是

应用程序(以及类似FCM的库)应使用以下方法更新其令牌:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { ... }

正如文档所述:

设备令牌可能会定期更改,因此缓存该值会导致向服务器发送无效的令牌。

因此,一旦应用程序获得令牌Y,令牌X将变为无效

注意: FCM使用方法交换在两个关键领域,其中之一是映射APNs令牌,因此它可能对您的实现隐藏,但它在每次需要时都会更新令牌并使之前的令牌无效。

英文:

The short answer is No

The application (and libraries like FCM) should update their token using:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { ... }

As the documentation says:
> Device tokens can change periodically, so caching the value risks sending an invalid token to your server.

So as soon as the app gets token Y, token X becomes invalid

Note: FCM uses method swizzling in two key areas and one of them is mapping APNs token So it may be hidden from your implementation but it is updating the token each time its needed and the invalidate the previous one

答案3

得分: -1

不能,它不能。

  1. 来自苹果官方文档
    func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    )

> 永远不要将设备令牌缓存在用户设备上。**设备令牌可能会定期更改,因此缓存该值会导致将无效的令牌发送到您的服务器。**如果设备令牌未更改,则与APNs注册并返回令牌的过程会很快完成。

当您的应用再次变为活动状态时,您可能需要调用此函数:registerForRemoteNotifications(),并将此deviceToken提交给Firebase Messaging、您的BE、OneSignal等...

func registerForRemoteNotifications()

当您调用上述方法时,它将请求APNs以获取新的或当前设备令牌。这是APNs将识别您的应用程序和设备状态的时刻。

  1. 为什么它会定期更改?以下是苹果可能使用的机制、方法或原因,来解释为什么会更改DeviceToken,这是用于解释幕后可能发生的事情,它们既是理论也是事实。
  • 这是苹果为了改善用户体验而做的。定期更改令牌就像您的应用调用/刷新令牌到BE以获取新令牌一样。因为旧令牌已经过期或无效。这增强了安全性,保护了用户的隐私等。想象一下,当应用被删除/卸载时,您仍然可以向用户的设备发送垃圾推送通知,这将是一个糟糕的用户体验。

  • 推送通知是通过互联网连接进行处理/传输的。苹果推送通知服务将定期检查您的设备和应用程序,以确保您的手机处于活动状态,并且您的应用程序已安装,从而成功地将推送通知发送到目标设备上的目标应用程序。

  • 您可以想象设备令牌=手机UUID + 应用程序Bundle ID + 时间 + 一些编码、加密等,甚至可能包括手机IP、套接字连接ID等。

  • 例如:丢失了WiFi?手机公共IP变化,套接字连接ID变化,现在我们需要重新生成一个新的设备令牌。这只是一个更改过程的示例。这并不意味着当手机公共IP变化时设备令牌将100%更改。这由苹果决定,我们只处理更改过程的结果。

英文:

No, it can not.

  1. From the Apple official documentation
    func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    )

> Never cache the device token locally on the user's device. Device tokens can change periodically, so caching the value risks sending an invalid token to your server. If the device token hasn't changed, registering with APNs and returning the token happens quickly.

You may need to call this function: registerForRemoteNotifications(), whenever your app becomes active, again. And submit this deviceToken to Firebase Messaging, your BE, OneSignal,...

func registerForRemoteNotifications()

When you call the above method, it will request to APNs to get a new or current device token. This is the moment that APNs will identify your App & Device status.

  1. Why it changes periodically? Here are the mechanics, methods, or reasons why Apple may use, do in changing DeviceToken, this is used for explaining what will or may happen behind the scene, they are both theories and facts.
  • This is how Apple does to improve user experience. Changing the Token periodically is like your app call /refresh-token to BE to get a new token. Because the old token already expired or is invalid. This increases security, protects user's privacy, etc. Imagine that you can still spam push notifications to user's devices when app is deleted/uninstalled, this is a horrible UX.
  • Push Notification is processed/transferred over the Internet connection. Apple Push Notification service will have to check your Device & App periodically to make sure that your Phone is alive, and your App is installed, to successfully send a push notification to the target App on the target Device.
  • You can imagine that the Device Token = Phone UUID + App Bundle ID + Time + Some encoding, encrypting,... even Phone IP, Socket connection ID,...
  • Ex: Wifi lost? Phone Public IP changes, Socket Connection ID changes,... Now, we need to regenerate a new Device Token. This is just an example of changing process. It doesn't means that Device Token will 100% change when Phone Public IP changes. Apple decides this, we just handle the result of the changing process.

huangapple
  • 本文由 发表于 2023年7月3日 06:51:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76601065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定