Correct way to retrieve token for FCM - iOS 10 Swift 3

前端 未结 15 2014
日久生厌
日久生厌 2021-01-31 02:42

i had implement Firebase with FirebaseAuth/FCM etc and did sent notification successfully through Firebase Console.

However i would need to push the notification from m

相关标签:
15条回答
  • 2021-01-31 02:53

    First register for the firebase token refresh notification:

    NotificationCenter.default.addObserver(self, selector: 
         #selector(tokenRefreshNotification), name:     
         NSNotification.Name.InstanceIDTokenRefresh, object: nil)
    

    Then you can receive the token in the tokenRefreshNotification selector:

    func tokenRefreshNotification(_ notification: Notification) {
        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()
    }
    
    0 讨论(0)
  • 2021-01-31 02:53

    I was having the same problem, but could not figure out what was going on.

    The didRegisterForRemoteNotificationsWithDeviceToken suggested by @Sam is called (almost) every time, so it is a good work around. BUT, it is NOT called the first time you open the app with the refreshed token.

    So for this scenario you still need the:

    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
        print("Refreshed Token: \(fcmToken)")
    }
    

    So if you only use the:

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        if let fcmToken = InstanceID.instanceID().token() {
            print("InstanceID token: \(fcmToken)")
        }
    }
    

    You will only get the "refreshed token" the second time the user opens the app.

    I managed to force a refresh token by uninstalling the app and cleaning the Build Folder (Product > Clean Build Folder). Good for testing.

    Ideally it could all be handled at messaging:didReceiveRegistrationToken delegate method, but I was not able to make it work. Another way to get notified for changes in the FCM token is to listen NSNotification named kFIRMessagingRegistrationTokenRefreshNotification as suggested in the documentation: https://firebase.google.com/docs/cloud-messaging/ios/client

    0 讨论(0)
  • 2021-01-31 02:54

    Swift 4 + Firebase (5.3.0)

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        InstanceID.instanceID().instanceID(handler: { (result, error) in
            if let error = error {
                print("Error fetching remote instange ID: \(error)")
            } else if let result = result {
                print("Remote instance ID token: \(result.token)")
            }
        })
    }
    
    0 讨论(0)
  • 2021-01-31 02:55

    The tokenRefreshNotification function doesn't always get called when launching the app.

    However, when placing the code inside the regular didRegisterForRemoteNotificationsWithDeviceToken delegate function, I can get the token every time:

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        if let refreshedToken = InstanceID.instanceID().token() {
            print("InstanceID token: \(refreshedToken)")
        }
    }
    

    (Swift 3 + Firebase 4.0.4)

    0 讨论(0)
  • 2021-01-31 02:59

    First import the libraries like:

    import FirebaseInstanceID
    import FirebaseMessaging
    import UserNotifications
    

    set Delegate:MessagingDelegate, UNUserNotificationCenterDelegate

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
    

    Write this code on didFinishLaunching():

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
        // Override point for customization after application launch.
        FirebaseApp.configure()
        Messaging.messaging().delegate = self
    
        //remote Notifications
        if #available(iOS 10.0, *) {
            UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (isGranted, err) in
                if err != nil {
                    //Something bad happend
                } else {
                    UNUserNotificationCenter.current().delegate = self
                    Messaging.messaging().delegate = self
    
                    DispatchQueue.main.async {
                        UIApplication.shared.registerForRemoteNotifications()
                    }
                }
            }
        } else {
            // Fallback on earlier versions
        }
    
        if #available(iOS 10, *) {
            UNUserNotificationCenter.current().requestAuthorization(options: [.badge,.sound,.alert], completionHandler: { (granted, error) in
                application.registerForRemoteNotifications()
            })
        }else{
            let notificationSettings = UIUserNotificationSettings(types: [.badge,.sound,.alert], categories: nil)
            UIApplication.shared.registerUserNotificationSettings(notificationSettings)
            UIApplication.shared.registerForRemoteNotifications()
        }
    
        return true
    }
    

    Write connectFCM method like this way:

    func ConnectToFCM() {
        Messaging.messaging().shouldEstablishDirectChannel = true
    
        if let token = InstanceID.instanceID().token() {
            print("\n\n\n\n\n\n\n\n\n\n ====== TOKEN DCS: " + token)
        }
    

    Also write delegate methods for registering and receiving push notification:

    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
        print("\n\n\n\n\n ==== FCM Token:  ",fcmToken)
        HelperFunction.helper.storeInUserDefaultForKey(name: kFCMToken, val: fcmToken)
        ConnectToFCM()
    }
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    
       // UIApplication.shared.applicationIconBadgeNumber += 1
    
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Barker"), object: nil)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    
        print(userInfo)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
        print(userInfo)
    
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
    }
    

    Now we can test it from firebase console.

    100% working, easy and tested

    Note: 1) Enable push notification from capability section of xcode.

    2) check twice your both p12 certificates uploaded on firebase project setting.

    3) Device token only can get from real device not a simulator.

    0 讨论(0)
  • 2021-01-31 03:02

    Go with the second option, and this is going to seem really stupid/simple, but to fix that nil optional fatal error, just remove the force-unwrap at the end

    Your code:
    var token = FIRInstanceID.instanceID().token()!
    Make it:
    var token = FIRInstanceID.instanceID().token()

    That will at least fix that nasty crash

    0 讨论(0)
提交回复
热议问题