user25626237
user25626237

Reputation: 39

How can I retrieve the APNs before the FCM token in Firebase specifically?

Before encountering the error, I was using Xcode which had Firebase installed. At around 12pm today, I began encountering an error that looked like this

APNS device token not set before retrieving FCM Token for Sender ID 'XXXX'. Be sure to re-retrieve the FCM token once the APNS device token is set.

Prior to 12pm, I did not encounter the error at all

After tinkering with it for 9 hours, I tried moving methods around, looked up many websites to find the exact error, debugging, and even went to YouTube of all places, but can't figure out where the error is coming from.

If it helps, I am currently using Xcode 16 with Firebase version 10.27.

Here's the code for anyone who thinks they can find the answer

This is in my AppDelegate from constant debugging

For extra context:

    // This method gets called when the app successfully registers for remote notifications and receives a device token from APNs
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
            print("APNs Device Token: \(deviceToken)")

           // Fetch the FCM registration token (this token is used to send push notifications through Firebase)
           Messaging.messaging().token { token, error in
               if let error = error {
                   print("Error fetching FCM registration token: \(error)")
               } else if let token = token {
                   print("FCM registration token: \(token)")
               }
           }
       }

       // This method is called when the app finishes launching
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Initialize Firebase
        FirebaseApp.configure()
        
        // Log app open event (for Firebase Analytics)
        FirebaseAnalytics.Analytics.logEvent(AnalyticsEventAppOpen, parameters: nil)
        
        // Set the delegate for Firebase Messaging
        Messaging.messaging().delegate = self
        
        // Register for remote notifications
        application.registerForRemoteNotifications()
        
        // Request notification authorization from the user
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
        
        // Set UNUserNotificationCenter delegate
        UNUserNotificationCenter.current().delegate = self
        
        return true
    }
    
    
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        if let fcm = Messaging.messaging().fcmToken {
            print("fcm", fcm)
        }
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        handleDailyReportTrigger()
        completionHandler([.banner, .sound, .badge])
    }

Upvotes: 1

Views: 976

Answers (1)

Umar Muzaffer
Umar Muzaffer

Reputation: 36

Steps to Implement: Register for APNs in Your AppDelegate: Add the following code to your AppDelegate to register for remote notifications (APNs) and retrieve the APNs token.

import Firebase
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Firebase configuration
        FirebaseApp.configure()

        // Request permission to use notifications
        requestNotificationAuthorization(application)

        return true
    }

    func requestNotificationAuthorization(_ application: UIApplication) {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
        }
    }

    // This method will be called once the user has granted permission and APNs has successfully registered the app
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Convert APNs token to string
        let apnsToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()

        // Print the APNs token (you can send it to your server if needed)
        print("APNs token: \(apnsToken)")

        // Pass the APNs token to Firebase (if FCM token is requested later)
        Messaging.messaging().apnsToken = deviceToken
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register for remote notifications: \(error)")
    }
}

Firebase and APNs Integration: In the above method didRegisterForRemoteNotificationsWithDeviceToken, the APNs token is retrieved before Firebase starts handling the FCM token. You can pass the APNs token to Firebase using:

Messaging.messaging().apnsToken = deviceToken

Retrieve the FCM Token After the APNs Token: After APNs registration is complete, Firebase will automatically retrieve the FCM token. You can handle the FCM token as shown below:

Messaging.messaging().token { token, error in
    if let error = error {
        print("Error fetching FCM token: \(error)")
    } else if let token = token {
        print("FCM token: \(token)")
    }
}

Flow to follow:

  1. Your app first registers for APNs.
  2. Once registered, didRegisterForRemoteNotificationsWithDeviceToken provides the APNs token.
  3. You can pass the APNs token to Firebase, allowing it to retrieve the FCM token.
  4. Finally, handle the FCM token in the completion handler of Messaging.messaging().token.

NOTE: Please adjust your other code in the above given methods. OR Please leave a comment will help you.

Upvotes: 0

Related Questions