iOS应用程序每次都会收到一个新的APNS设备令牌

iOS应用程序每次都会收到一个新的APNS设备令牌,ios,azure,push-notification,apple-push-notifications,token,Ios,Azure,Push Notification,Apple Push Notifications,Token,我正在使用Azure推送通知,并注意到每次启动我的应用程序时,APNS都会向我发送一个新的设备令牌。根据苹果的文档,设备令牌通常应保持不变: 每个请求中包含的设备令牌表示 接收通知的设备。APNs使用设备令牌来 识别每个独特的应用程序和设备组合。它还使用它们来 验证发送到设备的远程通知的路由。 每次应用程序在设备上运行时,它都会从APNs获取此令牌 并将其转发给您的提供商。您的提供商存储令牌和 在向特定应用程序和设备发送通知时使用它。 令牌本身是不透明和持久的,只有当 设备的数据和设置被擦除。只

我正在使用Azure推送通知,并注意到每次启动我的应用程序时,APNS都会向我发送一个新的设备令牌。根据苹果的文档,设备令牌通常应保持不变:

每个请求中包含的设备令牌表示 接收通知的设备。APNs使用设备令牌来 识别每个独特的应用程序和设备组合。它还使用它们来 验证发送到设备的远程通知的路由。 每次应用程序在设备上运行时,它都会从APNs获取此令牌 并将其转发给您的提供商。您的提供商存储令牌和 在向特定应用程序和设备发送通知时使用它。 令牌本身是不透明和持久的,只有当 设备的数据和设置被擦除。只有APN可以解码和读取数据 设备令牌

然而,根据通过Azure发送的失败消息的固定数量,我可以推断,每次启动应用程序时,我的应用程序都会从APN接收一个新的设备令牌。谁能告诉我:

  • 为什么每次我都会得到一个新的设备令牌,即使我没有更改手机设置或删除应用程序

  • 在上面的苹果摘录中,“删除设备数据”是什么意思?APNS使用哪些数据来确定“独特的应用程序和设备组合”

  • 代码如下:

    AppDelegate.m

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    
        if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge |
                                                                                                 UIUserNotificationTypeAlert |
                                                                                                 UIUserNotificationTypeSound)
                                                                                     categories:nil];
            [application registerUserNotificationSettings:settings];
        } else {
            [application registerForRemoteNotifications];
        }
    }
    
    
    - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
    {
        //initiate registration process with Apple Push Notification service
        [application registerForRemoteNotifications];
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *) token {
    
        // Setting token with Azure hub
        [[MyAzureNotificationHub sharedInfo] setDeviceTokenData:token];
    }
    
    您可以阅读以下内容:

    从不缓存设备令牌;需要时,请始终从系统中获取它们。虽然设备令牌对于应用程序和设备是唯一的,但它们可以随时间而改变。设备令牌可以随时更改,但当用户从备份中恢复其设备、用户在新设备上安装应用程序以及用户重新安装操作系统时,设备令牌保证会有所不同。从系统获取令牌可确保您始终拥有与APN通信所需的当前令牌。此外,如果令牌没有更改,那么获取它的速度很快,并且不会产生任何显著的开销

    (来源:)

    根据我使用APNS的经验,只要您注册远程通知,令牌就会随时更改(应用程序会重新启动)。每次您都应该将新令牌重新发送到后端,以便它使用最新的令牌发送推送通知。

    您可以阅读以下内容:

    从不缓存设备令牌;需要时,请始终从系统中获取它们。虽然设备令牌对于应用程序和设备是唯一的,但它们可以随时间而改变。设备令牌可以随时更改,但当用户从备份中恢复其设备、用户在新设备上安装应用程序以及用户重新安装操作系统时,设备令牌保证会有所不同。从系统获取令牌可确保您始终拥有与APN通信所需的当前令牌。此外,如果令牌没有更改,那么获取它的速度很快,并且不会产生任何显著的开销

    (来源:)


    根据我使用APNS的经验,只要您注册远程通知,令牌就会随时更改(应用程序会重新启动)。每次你都应该向你的后端重新发送新的令牌,这样它就会使用最新的令牌发送推送通知。

    简单的回答是,设备令牌不应该在每次应用程序向APN注册时更改。发件人:

    每个请求中包含的设备令牌表示 接收通知的设备。APNs使用设备令牌来 识别每个独特的应用程序和设备组合。它还使用它们来 验证发送到设备的远程通知的路由。 每次应用程序在设备上运行时,它都会从APNs获取此令牌 并将其转发给您的提供商。您的提供商存储令牌和 在向特定应用程序和设备发送通知时使用它。 令牌本身是不透明和持久的,只有当 设备的数据和设置被擦除。只有APN可以解码和读取数据 设备令牌

    我的应用程序每次都会得到一个新的设备令牌,因为我并没有正确地将deviceToken的数据类型从数据转换为字符串。APNS将设备令牌作为类型数据发送,但要将其传递给Azure,我需要首先使用以下函数将令牌转换为字符串:

        private func convertDataToString(data:NSData) -> String {
            let singleChar = UnsafePointer<CChar>(data.bytes)
            var tokenbuilder = String()
    
            if data.length > 0
            {
                for index in 0...data.length - 1
                {
                    tokenbuilder += String(format: "%02.2hhx", arguments: [singleChar[index]])
                }
                return tokenbuilder
            }
            else
            {
                return ""
            }
        }
    
    private func convertDataToString(数据:NSData)->String{
    让singleChar=UnsafePointer(data.bytes)
    var tokenbuilder=String()
    如果data.length>0
    {
    对于0中的索引…data.length-1
    {
    tokenbuilder+=字符串(格式:“%02.2hhx”,参数:[singleChar[index]]
    }
    返回令牌生成器
    }
    其他的
    {
    返回“”
    }
    }
    

    在我的例子中,我忘记了第一个字符的位置从0开始(不是1),因此,原始for循环从0到data.length(而不是data.length-1),导致函数返回一个包含随机额外字符的字符串。即使字符串有额外的字符,应用程序也会收到推送通知;但是,Azure日志中也有大量无效令牌。这也导致用户在每次启动应用程序(并注册设备令牌)时都会收到一个新的deviceToken。一旦我修复了for循环,APNS开始向用户返回相同的设备令牌,只要应用程序没有被删除(因此,删除设备数据)并重新安装到我的设备上;因此,创建“独特的应用程序和设备组合”。

    简而言之,设备令牌不应在每次应用程序向APN注册时更改。发件人:

    每个请求中包含的设备令牌表示 接收通知的设备。APNs使用设备令牌来 识别每个独特的应用程序和设备组合。它还使用它们来 验证发送到设备的远程通知的路由。 每次应用程序运行时