iOS Swift Firebase InstanceID token returns Nil at first time

12,079

Solution 1

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.")
  }
}
  }

Solution 2

Finally I got some solution for this. Firebase will take some time to connect to FCM. So what I did is, I make my code to update after 5 seconds if FIRInstanceID.instanceID().token() returns nil. Within 5 seconds Firebase will connected to FCM. This is not the perfect solution but now this is the only way to solve it.

Share:
12,079
Kavin Kumar Arumugam
Author by

Kavin Kumar Arumugam

3 years of experience in iOS application development with 2.3 years of industrial experience. Skilled IT professional and specialised in the entire iOS development cycle. Interested to work with more challenging position with an organisation where innovation and excellence is the way of life.

Updated on June 05, 2022

Comments

  • Kavin Kumar Arumugam
    Kavin Kumar Arumugam almost 2 years

    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.