【问题标题】:Cannot receive push notification on iOS from Firebase 3.2.0 topics无法在 iOS 上接收来自 Firebase 3.2.0 主题的推送通知
【发布时间】:2016-09-29 16:52:45
【问题描述】:

我按照谷歌在https://firebase.google.com/docs/notifications/ios/console-topics#receive_and_handle_topic_messages 上的教程在我的 iOS 应用上订阅了一个 Firebase 主题。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {

    FIRMessaging.messaging().subscribeToTopic("/topics/Notifications")

    let homeViewController = UINavigationController(rootViewController: HomeViewController())

    UINavigationBar.appearance().translucent = false
    window = UIWindow(frame: UIScreen.mainScreen().bounds)
    window?.rootViewController = homeViewController

    window?.makeKeyAndVisible()
    return true
}

但是,当我从 Firebase 控制台发送主题推送通知时。我无法收到任何推送通知。但是当我从控制台向用户段发送推送通知时,推送工作正常。当我检查 Xcode 控制台时,我看到了这个 FIRMessaging 错误。

2016-05-31 11:11:47.893: <FIRMessaging/WARNING> Cannot subscribe to topic: /topics/Notifications with token: (null) 

我已尝试搜索此错误,但没有找到任何东西。我不确定这是否是导致我的应用程序没有收到来自主题的任何推送的问题。

有没有人遇到过这个问题并知道如何解决?

【问题讨论】:

    标签: ios push-notification firebase swift2


    【解决方案1】:

    看来你打电话给subscribeToTopic 太早了。

    首先,在设置任何 Firebase 调用之前,请确保调用

    FIRApp.configure()
    

    这将确保所有 Firebase 服务都正确设置和初始化。

    接下来,您只需稍等片刻即可订阅主题。您的客户端需要先向 APNs 和 FCM 注册您的应用程序,以确保它可以接收通知。这涉及网络调用,这意味着您无法在应用首次启动时订阅主题。

    相反,我建议将该代码放入您的 application:didRegisterUserNotificationSettings 处理程序中。像这样的:

    - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
      NSLog(@"Hooray! I'm registered!");
      [[FIRMessaging messaging] subscribeToTopic:@"/topics/cool_users"];
    }
    

    编辑:还有 Swift 版本...

    func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
      print("Hooray! I'm registered!")
      FIRMessaging.messaging().subscribeToTopic("/topics/swift_fans")
    }
    

    【讨论】:

    • iOS 10 对此有修复吗?在 iOS 10 上订阅主题不起作用。
    • 对于任何尝试使用此代码的人,您应该订阅/topics/cool_users 而不仅仅是cool_users
    • @vnchopra 看起来亨默的答案有效。使用 /topics 前缀为我解决了 iOS 10 上的问题。
    • 谢谢,@henmer!我也在示例代码中添加了该前缀。
    • 这个方法似乎没有被调用(xCode 8.3.3 July 2017)。
    【解决方案2】:

    accepted solution 对我不起作用。调用 application:didRegisterUserNotificationSettings: 时,令牌并不总是可用的。 例如,如果应用程序是全新安装并首次启动,FIRInstanceID.instanceID().token() 返回 nil。

    您需要确保应用程序在令牌可用之后调用subscribeToTopic:。 我最终创建了一个辅助对象,它将subscribeToTopic:unsubscribeFrom: 调用排队并在令牌到达后以 FIFO 顺序执行它们。

    class FIRMessagingHelper {
    
        private let queue: OperationQueue
    
        init() {
            queue = OperationQueue()
            queue.maxConcurrentOperationCount = 1
            queue.addOperation(TokenReadyOperation())
        }
    
        func subscribeTo(topic: String) {
            queue.addOperation { 
                OperationQueue.main.addOperation({ 
                    FIRMessaging.messaging().subscribeToTopic(topic)
                })
            }
        }
    
        func unsubscribeFrom(topic: String) {
            queue.addOperation {
                OperationQueue.main.addOperation({
                    FIRMessaging.messaging().unsubscribeFromTopic(topic)
                })
            }
        }
    }
    

    TokenReadyOperation 一直等到令牌出现。 AsynchronousOperation 用作基类以最小化样板。

    class TokenReadyOperation : AsynchronousOperation {
    
        override init() {
            super.init()
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(TokenReadyOperation.tokenRefreshed(notification:)),
                                                   name: .firInstanceIDTokenRefresh,
                                                   object: nil)
        }
    
        override func didStart() {
            finishIfTokenAvailable()
        }
    
        private func finishIfTokenAvailable() {
            guard FIRInstanceID.instanceID().token() != nil else { return }
            markFinished()
        }
    
        /// Posted every time token changes
        @objc private func tokenRefreshed(notification: Notification) {
            finishIfTokenAvailable()
        }
    }
    

    要记住的几件事:

    • 应用必须在调用任何 Firebase 之前调用 FIRApp.configure()FIRApp.configureWithOptions(_:)(如 Todd Kerpelman 所述)
    • subscribeToTopic:unsubscribeFrom: 不是线程安全的,必须在主线程上执行
    • 主题名称必须采用“/topics/*”格式(如henmer 所述)
    • 确保使用不同的配置 plist 来调试和 App Store 发布您的应用。请参阅 FIRApp.configureWithOptions(_:) 文档。
    • 日期和时间应该是最新的,否则可能无法交付令牌。
    • 确保使用the newest framework version。我在使用 2017 年 1 月左右发布的 SDK 时遇到了通知传递问题。

    【讨论】:

    • 感谢您的调查。在全新安装时收听kFIRInstanceIDTokenRefreshNotification 似乎是防止主题订阅失败的唯一方法。
    【解决方案3】:

    之后调用subscribeToTopic并没有解决我的问题

    func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {

    而是在

    之后调用subscribeToTopic
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    

    当您从 APNS 而不是 firebase 获取推送令牌时,将调用此函数。

    Xcode 8.3.2

    斯威夫特 3.0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 1970-01-01
      相关资源
      最近更新 更多