ios设备上的Firebase InstanceID令牌刷新延迟

Posted

技术标签:

【中文标题】ios设备上的Firebase InstanceID令牌刷新延迟【英文标题】:Firebase InstanceID Token Refresh delay on ios device 【发布时间】:2016-10-13 12:51:07 【问题描述】:

我已经在我的 ios 应用程序中实现了 Firebase 云消息传递。一切似乎都运行良好,除了一件事,即从应用启动到在 Firebase 中刷新设备令牌需要将近 10 秒的时间。

我已将此代码添加到 App Delegate 中的 application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中:

[FIRApp configure];

//Add an observer for handling a token refresh callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshCallback:) name:kFIRInstanceIDTokenRefreshNotification object:nil];

这是tokenRefreshCallback: 方法:

- (void)tokenRefreshCallback:(NSNotification *)notification 

    NSString *refreshedToken = [[FIRInstanceID instanceID] token];
    NSLog(@"InstanceID token: %@", refreshedToken);

    if ([[FIRInstanceID instanceID] token] != NULL) 
        [[FIRMessaging messaging] subscribeToTopic:@"/topics/news"];
        NSLog(@"Subscribed to news topic");
    

    //Connect to FCM since connection may have failed when attempting before having a token
    [self connectToFirebase];


这是记录器的相关部分:

2016-10-13 14:36:23.844 My-App[1111] <Debug> [Firebase/Core][I-COR000001] Configuring the default app.
2016-10-13 14:36:26.492 My-App[1111:2222222] InstanceID token: (null)
2016-10-13 14:36:32.732 My-App[1111:2222222] InstanceID token: c1kmaskdmj...(the actual device token)

    为什么InstanceID为(null)时会调用tokenRefreshCallback:

    为什么要花将近 10 秒才能检索到实际令牌?

【问题讨论】:

【参考方案1】:

就我而言。使用深度链接在屏幕之间导航时遇到了同样的问题。

如果没有,一切都很好。

这对我有用。在应用程序 didFinishLaunchingWithOptions 我调用 [self configureFirebase];

- (void)configureFirebase 
    [FIRApp configure];
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) 
        UIUserNotificationType allNotificationTypes =
        (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings =
        [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
     else 
        // iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
        UNAuthorizationOptions authOptions =
        UNAuthorizationOptionAlert
        | UNAuthorizationOptionSound
        | UNAuthorizationOptionBadge;
        [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) 
        ];

        // For iOS 10 display notification (sent via APNS)
        [UNUserNotificationCenter currentNotificationCenter].delegate = self;
        // For iOS 10 data message (sent via FCM)
        [FIRMessaging messaging].remoteMessageDelegate = self;
#endif
    

    [[UIApplication sharedApplication] registerForRemoteNotifications];

我也实现了这个消息:

// [START receive_message]
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
    if (!(application.applicationState == UIApplicationStateActive)) 
        [AuthenticationController showAuthenticationViews:self.window];
    
    [self readNotification:userInfo];


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 
    [self readNotification:userInfo];
    completionHandler(UIBackgroundFetchResultNewData);

// [END receive_message]

// [START ios_10_message_handling]
// Receive displayed notifications for iOS 10 devices.
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler 
    NSDictionary *userInfo = notification.request.content.userInfo;
    [self readNotification:userInfo];
    completionHandler(UNNotificationPresentationOptionNone);


// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler 
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    [self readNotification:userInfo];
    completionHandler();

#endif
// [END ios_10_message_handling]

// [START ios_10_data_message_handling]
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Receive data message on iOS 10 devices while app is in the foreground.
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage 
    // Print full message
    //NSLog(@"%@", remoteMessage.appData);

#endif
// [END ios_10_data_message_handling]

// [START refresh_token]
- (void)tokenRefreshNotification:(NSNotification *)notification 
    // Note that this callback will be fired everytime a new token is generated, including the first
    // time. So if you need to retrieve the token as soon as it is available this is where that
    // should be done.
    //NSString *refreshedToken = [[FIRInstanceID instanceID] token];
    // NSLog(@"InstanceID token: %@", refreshedToken);

    // Connect to FCM since connection may have failed when attempted before having a token.
    [self connectToFcm];

    // TODO: If necessary send token to application server.

// [END refresh_token]

// [START connect_to_fcm]
- (void)connectToFcm 
    // Won't connect since there is no token
    if (![[FIRInstanceID instanceID] token]) 
        return;
    

    // Disconnect previous FCM connection if it exists.
    [[FIRMessaging messaging] disconnect];
    [[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) 
        if (error != nil) 
            // NSLog(@"Unable to connect to FCM. %@", error);
         else 
            [[FIRMessaging messaging] subscribeToTopic:notificationTopic];
            //NSLog(@"Connected to FCM.");
        
    ];

// [END connect_to_fcm]

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error 
    //  NSLog(@"Unable to register for remote notifications: %@", error);


// This function is added here only for debugging purposes, and can be removed if swizzling is enabled.
// If swizzling is disabled then this function must be implemented so that the APNs token can be paired to
// the InstanceID token.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 
    // NSLog(@"APNs token retrieved: %@", deviceToken);

    // With swizzling disabled you must set the APNs token here.
    // [[FIRInstanceID instanceID] setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeSandbox];
    BOOL automatic = [[[NSUserDefaults standardUserDefaults] objectForKey:@"automaticLogin"] boolValue];
    if (!automatic) 
        [[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"automaticLogin"];
        [self moveToInit];
    


// [START connect_on_active]
- (void)applicationDidBecomeActive:(UIApplication *)application 
    [self connectToFcm];

// [END connect_on_active]

// [START disconnect_from_fcm]
- (void)applicationDidEnterBackground:(UIApplication *)application 
    [[FIRMessaging messaging] disconnect];
    // NSLog(@"Disconnected from FCM");

// [END disconnect_from_fcm]

#pragma mark - Process notifications



- (void)readNotification:(NSDictionary *)userInfo 
   //read your notification


-(void)readLaunchWithOptions:(NSDictionary*)launchOptions
    if (launchOptions[notificationKey]) 
        [self readNotification:launchOptions[notificationKey]];
    

【讨论】:

以上是关于ios设备上的Firebase InstanceID令牌刷新延迟的主要内容,如果未能解决你的问题,请参考以下文章

iOS 上的 Firebase 自动登录失败

Firebase 有时会为 ios 设备获取令牌 NULL

iOS 上的 Firebase 身份验证失败(Unity、Xcode)

IOS Web 浏览器上的 Firebase 消息传递

Firebase 向 iOS 上的用户群发送通知不起作用

为啥推送通知不能在 iOS 中使用 Firebase 从设备到设备?