iOS FCM not getting push notifications

2019-09-10 06:31发布

问题:

Since i updated to swift 3, FCM doesn't work.

Push Notifications are enabled in Capabilities and Certificates are updated on Firebase console.

Btw, fcm on android app works just fine, and it was working on ios but after update on swift 3 and new firebase libraries, it doesn't.

AppDelegate.swift:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let notificationCenter = NotificationCenter.default

    var connectedToFcm: Bool = false

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

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

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

        return true
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        disconnectFromFcm()
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        connectToFcm()
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("REGISTRED")
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: .unknown)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
        error: Error ) {
        print("Registration for remote notification failed with error: \(error.localizedDescription)")
    }

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

    func tokenRefreshNotification(_ notification: Notification) {
        let refreshedToken = FIRInstanceID.instanceID().token()
        if refreshedToken != nil {
            print("InstanceID token: \(refreshedToken!)")
            // Connect to FCM since connection may have failed when attempted before having a token.
            connectToFcm()
        }
    }

    func connectToFcm() {
        guard FIRInstanceID.instanceID().token() != nil else {
            return;
        }
        if connectedToFcm == false {
            FIRMessaging.messaging().disconnect()
            FIRMessaging.messaging().connect { (error) in
                if (error != nil) {
                    self.connectedToFcm = false
                    print("Unable to connect with FCM. \(error)")
                } else {
                    self.connectedToFcm = true
                    print("Connected to FCM.")
                    self.sendTokenToServer()
                }
            }
            return
        }
    }

    func sendTokenToServer() {
        let fcmToken = FIRInstanceID.instanceID().token()
        if self.sharedUser.getToken().characters.count == 0 || fcmToken == nil {
            return
        }
        let params = [
            "reg_id": fcmToken!,
            "dev_id": Config().devId
        ]

        Alamofire.request(Config().fcmUrl, method: .post, parameters: params, encoding: JSONEncoding.default, headers: Config().apiHeaders)
            .validate()
            .responseJSON { response in
                if response.result.isSuccess {
                    print("FCM token send to app server")
                }
            }
    }

    func disconnectFromFcm() {
        FIRMessaging.messaging().disconnect()
        connectedToFcm = false
        print("Disconnected to FCM")
    }
}

Log:

2016-12-22 09:26:34.921315 app[6198:1607437] Firebase automatic screen reporting is enabled. Call +[FIRAnalytics setScreenName:setScreenClass:] to set the screen name or override the default screen class name. To disable automatic screen reporting, set the flag FirebaseAutomaticScreenReportingEnabled to NO in the Info.plist
2016-12-22 09:26:35.056527 app[6198:1607490] [Firebase/Core][I-COR000001] Configuring the default app.
2016-12-22 09:26:35.057: <FIRInstanceID/WARNING> FIRInstanceID AppDelegate proxy enabled, will swizzle app delegate remote notification handlers. To disable add "FirebaseAppDelegateProxyEnabled" to your Info.plist and set it to NO
2016-12-22 09:26:35.057 app[6198] <Debug> [Firebase/Core][I-COR000001] Configuring the default app.
2016-12-22 09:26:35.060: <FIRInstanceID/WARNING> Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001 "(null)"
2016-12-22 09:26:35.064: <FIRMessaging/INFO> FIRMessaging library version 1.2.0
2016-12-22 09:26:35.065598 app[6198:1607526] <FIRAnalytics/INFO> Firebase Analytics v.3501000 started
2016-12-22 09:26:35.067: <FIRMessaging/WARNING> FIRMessaging AppDelegate proxy enabled, will swizzle app delegate remote notification receiver handlers. Add "FirebaseAppDelegateProxyEnabled" to your Info.plist and set it to NO
2016-12-22 09:26:35.067 app[6198:] <FIRAnalytics/INFO> Firebase Analytics v.3501000 started
2016-12-22 09:26:35.069638 app[6198:1607526] <FIRAnalytics/INFO> To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled
2016-12-22 09:26:35.069 app[6198:] <FIRAnalytics/INFO> To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled
2016-12-22 09:26:35.073182 app[6198:1607488] <FIRAnalytics/INFO> Successfully created Firebase Analytics App Delegate Proxy automatically. To disable the proxy, set the flag FirebaseAppDelegateProxyEnabled to NO in the Info.plist
2016-12-22 09:26:35.073 app[6198:] <FIRAnalytics/INFO> Successfully created Firebase Analytics App Delegate Proxy automatically. To disable the proxy, set the flag FirebaseAppDelegateProxyEnabled to NO in the Info.plist
2016-12-22 09:26:35.181355 app[6198:1607488] <FIRAnalytics/WARNING> The AdSupport Framework is not currently linked. Some features will not function properly.
2016-12-22 09:26:35.181 app[6198:] <FIRAnalytics/WARNING> The AdSupport Framework is not currently linked. Some features will not function properly.
2016-12-22 09:26:35.198981 app[6198:1607490] <FIRAnalytics/INFO> Firebase Analytics enabled
2016-12-22 09:26:35.199 app[6198:] <FIRAnalytics/INFO> Firebase Analytics enabled
2016-12-22 09:26:35.285: <FIRInstanceID/WARNING> APNS Environment in profile: development
REGISTRED
2016-12-22 09:26:35.387693 app[6198:1607489] [Firebase/Core][I-COR000019] Clearcut post completed.
2016-12-22 09:26:35.387 app[6198] <Debug> [Firebase/Core][I-COR000019] Clearcut post completed.
Connected to FCM.
FCM token send to app server

I made prints to check if app gets token, and it does. Also, token is sent to server and i checked there if it is ok and if server is sending push.

回答1:

I have faced same issue with iOS FCM integration I have solved it by using latest code for push notification in iOS 10.

You need to check the OS version of the device and segregate relevant codes.

if #available(iOS 10, *)
        {
            let center = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
                if error == nil{
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }else
        {
            // Register for remote notifications
            if #available(iOS 8.0, *) {
                // [START register_for_notifications]
                let settings: UIUserNotificationSettings =
                    UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
                application.registerUserNotificationSettings(settings)
                application.registerForRemoteNotifications()
                // [END register_for_notifications]
            } else {
                // Fallback
                let types: UIRemoteNotificationType = [.alert, .badge, .sound]
                application.registerForRemoteNotifications(matching: types)
            }
        }

Put this code in a function and call it from did finish launching also comment your code. Do let me know if you still have any issues.

Important :- import UserNotifications

Delegate :-

func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings)
    {

        /**
        Allow device to register for remote notification.
        */
        UIApplication.shared.registerForRemoteNotifications()
        FIRMessaging.messaging().subscribe(toTopic: "/topics/test")
    }



    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    {
        /**
        Send device token to firebase to get the FCM token for pushnotification from firebase.
        */
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.prod)
    }