首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Firebase FCM一开始不起作用,但如果应用程序打开,则在3-4次之后才能工作。

Firebase FCM一开始不起作用,但如果应用程序打开,则在3-4次之后才能工作。
EN

Stack Overflow用户
提问于 2017-10-05 05:39:29
回答 4查看 2.5K关注 0票数 2

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

我已将我的应用程序代码附在下面。

代码语言:javascript
复制
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)
    }
}

提前感谢

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-10-05 05:44:21

我有与您相同的问题,而且有一个已知的问题,如果FCM token没有足够早地被调用,那么UIApplication.shared.registerForRemoteNotifications()并不总是与APNs device token相关联。

根据 GitHub线程的说法,这个问题已经在FirebaseInstanceID SDK中解决了,并且应该很快就会出现。

在此期间,你可以:

FirebaseInstanceID pod to 2.0.0锁定在Podfile中,或

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

更新:

我刚刚做了一些额外的测试,我注意到这是有点随机的,什么时候会起作用。对于一些设备,它立即对一些不起作用。对于某些设备,Single Token push工作,而不是User Segment。我设法使它正常工作,这样您至少可以通过添加以下内容获得Single Token pushUser Segment

代码语言:javascript
复制
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函数,它将无法工作。

票数 3
EN

Stack Overflow用户

发布于 2017-10-05 06:09:31

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

  1. 检查这个答案
  2. 用FCM实现AppDelegate

希望这能有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2017-10-05 07:23:39

通过以下方式更新应用程序委托

代码语言:javascript
复制
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)
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46578563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档