iOS Swift Firebase InstanceID token returns Nil at first time

Kavin Kumar Arumugam picture Kavin Kumar Arumugam · Apr 21, 2017 · Viewed 12.1k times · Source

I am using Firebase notification in my app. When I install my app for first time FIRInstanceID.instanceID().token() returns nil, but it won't return nil at next time. Everything is done perfect except this.

Here is the code:

import UIKit
import Firebase
import FirebaseMessaging
import FirebaseInstanceID
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, FIRMessagingDelegate
{

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
        //Configuring Firebase
        FIRApp.configure()
if #available(iOS 10.0, *)
        {
            print("Test")
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self
            UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { (granted, error) in
                if granted
                {
                    //self.registerCategory()
                }
            }
            // For iOS 10 data message (sent via FCM)
            FIRMessaging.messaging().remoteMessageDelegate = self
        }
        else
        {
            let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.firInstanceIDTokenRefresh, object: nil)
        return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    {
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.prod)
    }
func tokenRefreshNotification(notification: NSNotification)
    {
        if let refreshedToken = FIRInstanceID.instanceID().token()
        {
            print("InstanceID token: \(refreshedToken)")
        }
        // Connect to FCM since connection may have failed when attempted before having a token.
        connectToFcm()
    }

    func connectToFcm()
    {
        FIRMessaging.messaging().connect { (error) in
            if (error != nil)
            {
                print("Unable to connect with FCM. \(error)")
            }
            else
            {
                print("Connected to FCM.")
            }
        }
    }
}

In Remote Page I am Calling Firebase InstanceID Token

let token = FIRInstanceID.instanceID().token()

But at first time it return nil value.

Answer

Anbu.Karthik picture Anbu.Karthik · Apr 21, 2017

change the order of FIRApp.configure() and try once, for more information you can get the sample here

func application(_ application: UIApplication,
               didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

// Register for remote notifications. This shows a permission dialog on first run, to
// show the dialog at a more appropriate time move this registration accordingly.
// [START register_for_notifications]
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 })

  // For iOS 10 data message (sent via FCM)
  FIRMessaging.messaging().remoteMessageDelegate = self

} else {
  let settings: UIUserNotificationSettings =
  UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
  application.registerUserNotificationSettings(settings)
}

application.registerForRemoteNotifications()

// [END register_for_notifications]
FIRApp.configure()

// [START add_token_refresh_observer]
// Add observer for InstanceID token refresh callback.
NotificationCenter.default.addObserver(self,
    selector: #selector(self.tokenRefreshNotification),
    name: .firInstanceIDTokenRefresh,
    object: nil)
// [END add_token_refresh_observer]
return true
}

on that delegate check once the token is comes or not

func tokenRefreshNotification(notification: NSNotification) {
      //  print("refresh token call")
        guard let contents = FIRInstanceID.instanceID().token()
        else {
            return
        }
           // let refreshedToken = FIRInstanceID.instanceID().token()!
            print("InstanceID token: \(contents)")

           // UserDefaults.standardUserDefaults().set(contents, forKey: "deviceToken");
            // Connect to FCM since connection may have failed when attempted before having a token.

            connectToFcm()

    }

finally connect the FCM like

func connectToFcm() {
// Won't connect since there is no token
guard FIRInstanceID.instanceID().token() != nil else {
  return
}

// Disconnect previous FCM connection if it exists.
FIRMessaging.messaging().disconnect()

FIRMessaging.messaging().connect { (error) in
  if error != nil {
    print("Unable to connect with FCM. \(error?.localizedDescription ?? "")")
  } else {
    print("Connected to FCM.")
  }
}
  }