Cannot receive push notification on iOS from Firebase 3.2.0 topics

11,138

Solution 1

Looks like maybe you're calling subscribeToTopic too early.

First, before you set up any Firebase call, make sure you call

FIRApp.configure()

That will ensure that all Firebase services are properly set up and initialized.

Next, you're going to need to wait just a bit to subscribe to topics. Your client needs to first register your app with both APNs and FCM to ensure that it can receive notifications. That involves a network call, which means you can't subscribe to topics when your app first launches.

Instead, I'd recommend putting that code into your application:didRegisterUserNotificationSettings handler instead. Something like this:

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

Edit: And the Swift version...

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

Solution 2

The accepted solution did not work for me. The token is not always available when application:didRegisterUserNotificationSettings: is called. For example if application is freshly installed and starts for the first time FIRInstanceID.instanceID().token() returns nil.

You need to make sure application calls subscribeToTopic: after the token is available. I ended up with creating a helper object that enqueues subscribeToTopic:, unsubscribeFrom: calls and executes them in FIFO order after the token arrives.

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 waits until the token appears. AsynchronousOperation is used as the base class to minimize boilerplate.

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

Few things to keep in mind:

  • App must call FIRApp.configure() or FIRApp.configureWithOptions(_:) prior making any Firebase calls (as Todd Kerpelman mentioned)
  • subscribeToTopic:, unsubscribeFrom: are not thread safe and must be executed on main thread
  • Topic names has to be in "/topics/*" format (as henmer mentioned)
  • Make sure to use different configuration plist for debug and App Store release of your app. See FIRApp.configureWithOptions(_:) documentation.
  • Date & Time should be current, otherwise the token may not be delivered.
  • Make sure to use the newest framework version. I had issues with notification delivery with the SDK released around January 2017.

Solution 3

My problem was not solved by calling subscribeToTopic after

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

instead it worked by calling subscribeToTopic after

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

this function get called when you get your push token from APNS not firebase.

Xcode 8.3.2

Swift 3.0

Share:
11,138
howly
Author by

howly

Updated on June 03, 2022

Comments

  • howly
    howly almost 2 years

    I followed the tutorial by google on https://firebase.google.com/docs/notifications/ios/console-topics#receive_and_handle_topic_messages to subscribe to a Firebase topic on my iOS app.

    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
    }
    

    However, when I send a topic push notification out from the Firebase console. I could not receive any push notifications. But when I send out push notification to user segment from the console, the push is working perfectly. When I check the Xcode console, I am seeing this FIRMessaging error.

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

    I've tried to search for this error but have no luck finding anything. I am not sure if this is the problem that is causing my app to not receive any push from topics.

    Does anyone have this issue and know how to solve it?

  • vnchopra
    vnchopra over 7 years
    Is there an iOS 10 fix for this? Subscribing to topics on iOS 10 does not work.
  • henrikmerlander
    henrikmerlander over 7 years
    For anyone trying to use this code, you should subscribe to /topics/cool_users instead of just cool_users
  • kevinl
    kevinl over 7 years
    @vnchopra it looks like henmer's answer works. Prefixing with /topics resolves the issue on iOS 10 for me.
  • Todd Kerpelman
    Todd Kerpelman about 7 years
    Thanks, @henmer! I've added that prefix in my sample code, too.
  • andrew k
    andrew k about 7 years
    Thanks for your investigation. Listening for the kFIRInstanceIDTokenRefreshNotification on a fresh install seems to be the only way to prevent topic subscribe failures.
  • ffritz
    ffritz almost 7 years
    This method doesn't seem to get called (xCode 8.3.3 July 2017).
  • Hashan Seneviratne
    Hashan Seneviratne almost 7 years
    According to latest sdk func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) gets called.
  • mkhoshpour
    mkhoshpour over 6 years
    @vnchopra you should use this: stackoverflow.com/a/46431208/2108523