Ios Firebase FCM最初不工作,但如果应用程序打开,会在3-4次后工作

Ios Firebase FCM最初不工作,但如果应用程序打开,会在3-4次后工作,ios,swift,firebase,push-notification,firebase-cloud-messaging,Ios,Swift,Firebase,Push Notification,Firebase Cloud Messaging,我是Firebase FCM集成的新手,我面临一些问题。第一次安装应用程序时,我不会收到推送通知,但如果我打开和关闭应用程序几次,然后从Firebase发送推送通知,我会收到通知,而不会更改客户端或服务器代码。有人能帮我吗 我已在下面附上我的appdelegate代码 import UIKit import Firebase import UserNotifications import FirebaseMessaging import FirebaseInstanceID @UIApplic

我是Firebase FCM集成的新手,我面临一些问题。第一次安装应用程序时,我不会收到推送通知,但如果我打开和关闭应用程序几次,然后从Firebase发送推送通知,我会收到通知,而不会更改客户端或服务器代码。有人能帮我吗

我已在下面附上我的appdelegate代码

import UIKit
import Firebase
import UserNotifications
import FirebaseMessaging
import FirebaseInstanceID

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

    var window: UIWindow?


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


        FirebaseApp.configure()

        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: { (granted, error) in
                    if error == nil{
                        UIApplication.shared.registerForRemoteNotifications()
                    }
            })
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
                application.registerForRemoteNotifications()
        }

        application.registerForRemoteNotifications()
        return true
    }

    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
    }

    func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
        UIApplication.shared.registerForRemoteNotifications()
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // I have tried both method but none worked and i also tried MessagingAPNSTokenType.sandbox and prod
        // Method 1: Messaging.messaging().apnsToken = deviceToken
        // Method 2:
        Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.unknown)
    }
}

提前感谢

我遇到了与您相同的问题,并且存在一个已知问题,即如果
UIApplication.shared.registerforremotentifications()
调用得不够早,则
FCM令牌
并不总是与
APNs设备令牌
关联

根据GitHub线程的说法,这个问题已经在
FirebaseInstanceID SDK
中修复,应该很快就会出来

同时,您可以:

将您的
FirebaseInstanceID pod锁定到pod文件中的2.0.0
,或

确保在应用程序启动时调用
UIApplication.shared.registerforremotentifications()
,最好在
FirebaseApp.configure()之前

更新:
我只是做了一些额外的测试,我注意到这是一个有点随机的时候,这将工作。对于某些设备,它立即起作用,而对于某些设备则不起作用。对于某些设备,
单令牌推送
工作,而不是
用户段
。我设法让它工作起来,通过添加以下内容,您至少可以获得
单令牌推送
用户段

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    if #available(iOS 10.0, *) {
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: {_, _ in
        })

        // For iOS 10 display notification (sent via APNS)
        UNUserNotificationCenter.current().delegate = self
        // For iOS 10 data message (sent via FCM)
        Messaging.messaging().delegate = self
        application.registerForRemoteNotifications()
        print("::: registerForRemoteNotifications iOS 10")

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

    FirebaseApp.configure()
    Messaging.messaging().delegate = self
    Messaging.messaging().shouldEstablishDirectChannel = true

    if let refreshedToken = InstanceID.instanceID().token() {
        print("::: InstanceID token: \(refreshedToken)")
    }

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

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().setAPNSToken(deviceToken, type: .prod)

    if let refreshedToken = InstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
    }
}

问题是,如果您不访问
didRegisterForRemoteNotificationsWithDeviceToken
函数,它将无法工作。

Firebase FCM,需要一些时间才能生成其第一个令牌。获得此令牌后,您将开始接收推送通知。看看这些。可以肯定的是:


  • 希望这有帮助。

    通过此更新您的appdelegate

    import FirebaseCore
    import FirebaseInstanceID
    import FirebaseMessaging
    import UserNotifications
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate{
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            self.fcmInitialSetup(application)
            return true
        }
        func fcmInitialSetup(_ application: UIApplication){
    
            // [START register_for_notifications]
            if #available(iOS 10.0, *) {
                let uns: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
                application.registerUserNotificationSettings(uns)
                application.registerForRemoteNotifications()
    
            } else {
                let settings: UIUserNotificationSettings =
                    UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
                application.registerUserNotificationSettings(settings)
            }
    
            application.registerForRemoteNotifications()
    
            // [END register_for_notifications]
    
            FIRApp.configure()
    
            // Add observer for InstanceID token refresh callback.
            NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.firInstanceIDTokenRefresh, object: nil)
    
            if let token = FIRInstanceID.instanceID().token() {
                sendTokenToServer(token)
            }
        }
    
        func sendTokenToServer(_ currentToken: String) {
            print("sendTokenToServer() Token: \(currentToken)")
            // Send token to server ONLY IF NECESSARY
    
            print("InstanceID token: \(currentToken)")
            self.token = currentToken
            UserDefaults.standard.set(self.token, forKey: "token")
            UserDefaults.standard.synchronize()
            if self.token != nil{
                let userInfo = ["token": self.token]
                NotificationCenter.default.post(
                    name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
            }
        }
    
    
        // NOTE: Need to use this when swizzling is disabled
        func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
            let tokenChars = (deviceToken as NSData).bytes.bindMemory(to: CChar.self, capacity: deviceToken.count)
            var tokenString = ""
    
            for i in 0..<deviceToken.count {
                tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
            }
    
            FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.unknown)
            print("Device Token:", tokenString)
            print("FIRInstanceID.instanceID().token() Token:", FIRInstanceID.instanceID().token())
            if let tokenData = FIRInstanceID.instanceID().token(){
                UserDefaults.standard.set(tokenData, forKey: "token")
                UserDefaults.standard.synchronize()
                let userInfo = ["token": tokenData]
            }
        }
    
        func tokenRefreshNotification(_ notification: Notification) {
            // NOTE: It can be nil here
            //        print("Token:\(FIRInstanceID.instanceID().token()!)")
            if let refreshedToken = FIRInstanceID.instanceID().token() {
                print("InstanceID token: \(refreshedToken)")
                UserDefaults.standard.set(refreshedToken, forKey: "token")
                UserDefaults.standard.synchronize()
                print("update now \(self.token)")
                if self.token != nil{
                    let userInfo = ["token": self.token]
                    NotificationCenter.default.post(
                        name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
                }
    
            }
    
            // Connect to FCM since connection may have failed when attempted before having a token.
            connectToFcm()
        }
        // [END refresh_token]
        func connectToFcm() {
            FIRMessaging.messaging().connect { (error) in
                if (error != nil) {
                    print("Unable to connect with FCM. \(error)")
                } else {
                    print("Connected to FCM.")
                }
            }
        }
    
        func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
            print(userInfo)
        }
    
        func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
            print("Within open URL")
            return true
        }
    
    
        // [START receive_apns_token_error]
        func application( _ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
            error: Error ) {
            print("Registration for remote notification failed with error: \(error.localizedDescription)")
            // [END receive_apns_token_error]
            let userInfo = ["error": error.localizedDescription]
            NotificationCenter.default.post(
                name: Notification.Name(rawValue: rkey), object: nil, userInfo: userInfo)
        }
    
        func registrationHandler(_ token: String!, error: NSError!) {
            if (token != nil) {
                self.token = token!
                print("Registration Token: \(self.token)")
                UserDefaults.standard.set(self.token, forKey: "token")
                UserDefaults.standard.synchronize()
                let userInfo = ["token": self.token]
                NotificationCenter.default.post(
                    name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
            } else {
                print("Registration to GCM failed with error: \(error.localizedDescription)")
                let userInfo = ["error": error.localizedDescription]
                NotificationCenter.default.post(
                    name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
            }
        }
    
        func registerForPushNotifications(_ application: UIApplication) {
            let notificationSettings = UIUserNotificationSettings(
                types: [.badge, .sound, .alert], categories: nil)
            application.registerUserNotificationSettings(notificationSettings)
        }
    
        func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
            if notificationSettings.types != UIUserNotificationType() {
                application.registerForRemoteNotifications()
            }
        }
    
        // [START receive_message]
        func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                         fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
            // If you are receiving a notification message while your app is in the background,
            // this callback will not be fired till the user taps on the notification launching the application.
            // TODO: Handle data of notification
    
            // Print message ID. add Toast
            print(userInfo);
    
            print(application.keyWindow?.visibleViewController() ?? "")
    
            print("Message ID: \(userInfo["gcm.message_id"]!)")
    
    
            // Print full message.
            print("%@", userInfo)
        }
        // [END receive_message]
    
    
    
        func applicationDidBecomeActive(_ application: UIApplication) {
            connectToFcm()
        }
    
        // [START disconnect_from_fcm]
        func applicationDidEnterBackground(_ application: UIApplication) {
            //        FIRMessaging.messaging().disconnect()
            //        print("Disconnected from FCM.")
        }
    
        func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
        }
    }
    // [END disconnect_from_fcm]
    
    
    // [START ios_10_message_handling]
    @available(iOS 10, *)
    extension AppDelegate : UNUserNotificationCenterDelegate {
    
        // Receive displayed notifications for iOS 10 devices.
        func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    willPresent notification: UNNotification,
                                    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
            let userInfo = notification.request.content.userInfo
            // Print message ID.
            print("Message ID: \(userInfo["gcm.message_id"]!)")
            // Print message ID. add Toast
    
            // Print full message.
            print("%@", userInfo)
            // Print full message.
            print("%@", userInfo)
        }
    }
    
    extension AppDelegate : FIRMessagingDelegate {
        // Receive data message on iOS 10 devices.
        func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
            print("%@", remoteMessage.appData)
        }
    }
    
    导入FirebaseCore
    导入FirebaseInstanceID
    导入FirebaseMessaging
    导入用户通知
    @UIApplicationMain
    类AppDelegate:UIResponder、UIApplicationLegate{
    func应用程序(application:UIApplication,didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptions:[UIApplicationLaunchOptions:任何]?)->Bool{
    self.fcminitialstup(应用程序)
    返回真值
    }
    func fcmInitialSetup(u应用程序:ui应用程序){
    //[启动注册\u以获取\u通知]
    如果可用(iOS 10.0,*){
    let uns:UIUserNotificationSettings=UIUserNotificationSettings(类型:[.alert、.badge、.sound],类别:nil)
    application.registerUserNotificationSettings(uns)
    应用程序.注册表项更改()
    }否则{
    let设置:UIUserNotificationSettings=
    UIUserNotificationSettings(类型:[.alert、.badge、.sound],类别:nil)
    application.registerUserNotificationSettings(设置)
    }
    应用程序.注册表项更改()
    //[结束注册以获取通知]
    FIRApp.configure()
    //添加InstanceID令牌刷新回调的观察者。
    NotificationCenter.default.addObserver(self,选择器:#选择器(self.tokenRefreshNotification),名称:NSNotification.name.firInstanceIDTokenRefresh,对象:nil)
    如果let token=FIRInstanceID.instanceID().token(){
    sendTokenToServer(令牌)
    }
    }
    func sendTokenToServer(currentToken:String){
    打印(“sendTokenToServer()令牌:\(currentToken)”)
    //仅在必要时向服务器发送令牌
    打印(“InstanceID标记:\(currentToken)”)
    self.token=currentToken
    UserDefaults.standard.set(self.token,forKey:“token”)
    UserDefaults.standard.synchronize()
    如果self.token!=nil{
    让userInfo=[“token”:self.token]
    NotificationCenter.default.post(
    name:Notification.name(rawValue:self.rkey),object:nil,userInfo:userInfo)
    }
    }
    //注意:禁用swizzling时需要使用此选项
    func应用程序(application:UIApplication,DidRegisterForRemotionTificationswithDeviceToken deviceToken:Data){
    让tokenChars=(deviceToken作为NSData).bytes.bindMemory(to:CChar.self,capacity:deviceToken.count)
    var tokenString=“”
    因为我在0..Bool{
    打印(“在打开的URL内”)
    返回真值
    }
    //[开始接收\u apns\u令牌\u错误]
    func应用程序(application:UIApplication,didFailToRegisterForRemoteNotificationsWithError
    错误:错误){
    打印(“远程通知注册失败,错误:\(error.localizedDescription)”)
    //[结束接收\u apns\u令牌\u错误]
    let userInfo=[“error”:error.localizedDescription]
    NotificationCenter.default.post(
    name:Notification.name(rawValue:rkey),object:nil,userInfo:userInfo)
    }
    func registrationHandler(uToken:String!,错误:NSError!){
    如果(令牌!=nil){
    self.token=令牌!
    打印(“注册令牌:\(self.Token)”)
    UserDefaults.standard.set(self.token,forKey:“token”)
    UserDefaults.standard.synchronize()
    让userInfo=[“token”:self.token]
    NotificationCenter.default.post(
    name:Notification.name(rawValue:self.rkey),object:nil,userInfo:userInfo)
    }否则{
    打印(“向GCM注册失败,错误:\(error.localizedDescription)”)
    let userInfo=[“error”:error.localizedDescription]
    NotificationCenter.default.post(
    name:Notification.name(rawValue:self.rkey),object:nil,userInfo:userInfo)
    }
    }
    func registerForPushNotifications(uApplication:UIApplication){
    让notificationSettings=UIUserNotificationSettings(
    类型:[.badge、.sound、.alert],类别:无
    
        guard let contents = FIRInstanceID.instanceID().token()
            else {
                return
        }
        print("InstanceID token: \(contents)")
        if let token = FIRInstanceID.instanceID().token(){
            print(token)