'Not receiving push notification sent via firebase cloud functions in iOS app though I get the from messaging console

I have my project setup in the correct way (I believe) i.e:

  • The APNs Authentication Key is added in the cloud messaging section of the firebase console.
  • The remove notification app delegate functions:

App Delegate functions:


extension AppDelegate: UNUserNotificationCenterDelegate {
    func registerForPushNotifications() {
        if !Device.isSimulator {
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(options: authOptions,
                                                                    completionHandler: {_, _ in
                dispatchOnMainThread {
                    Messaging.messaging().delegate = self
                    UIApplication.shared.registerForRemoteNotifications()
                }
            })
        }
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("😔 Failed to register for remote notifications with error: \(error)")
    }
    
    private func processNotification(_ notification: UNNotification) {
        let userInfo = notification.request.content.userInfo
        UIApplication.shared.applicationIconBadgeNumber = 0
        print("📲 Notification Content Received: \(userInfo)")
        if let resourcePath = Bundle.main.path(forResource: "general_notification", ofType: "m4a") {
            let url = URL(fileURLWithPath: resourcePath)
            audioPlayer = try? AVAudioPlayer(contentsOf: url)
            audioPlayer?.prepareToPlay()
            audioPlayer?.play()
        }
    }
    
}

extension AppDelegate {
    
    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        print("🥸 Notification received in an state: \(application.applicationState)")
    }
    
    // MARK: Handles Silent Push Notifications
    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("📲 Notification Content Received in Background State: \(userInfo)")
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: () -> Void) {
        processNotification(response.notification)
        completionHandler()
    }
    
    // MARK: Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        processNotification(notification)
        completionHandler([.badge, .banner, .sound])
    }
}

In my cloud functions this is what I have:

admin.initializeApp(functions.config().firebase);
   
function sendNotification(userID){
    
        let notificationToken = db.collection('notification_tokens').doc(userID);
        notificationToken.get().then(doc => {
    
            if (!doc.exists) {
                console.log(`⛔️ Cant find notification token for user ${userID}`);
            } else {
                const tokenData  = doc.data();
                const tokenID = Object.keys(tokenData)[0];
                console.log(`📲 Device Token Found with tokenID: ${tokenID}`);
    
                const messagePayload = {
                    title:  `${userName} just joined`, 
                    body: `Your friend ${userName} is now on Your App`,
                    sound: 'general_notification.m4a',     
                    badge: `1`
                };
                
                const notificationMessageObject = {
                    token: tokenID,
                    data: messagePayload
                };
    
                admin.messaging().send(notificationMessageObject).then((response) => {
                    console.log(`✅ Successfully sent message: ${response}`);
                    return true;
                }).catch((error) => {
                    console.log('❌ Error sending message:', error);
                    return false;
                });
            }
        }).catch(err => {
            console.log('Error getting tokenID document', err);
            return false;
        });
    }

When I test the push notification functionality by sending a push notification from the Messaging Panel on Firebase Console to my physical device token captured from the app delegate, I get the notification on my phone,

When I run a cloud function trigger to get there notification, I get a success response in the logs but the notification does not get received on my device.

It was working on a staging database I had but when I setup a new database and replicate the old one, the above occurs.

Might there be something I missed?

enter image description here



Solution 1:[1]

Eventually found the solution - which lay in the node.js cloud function.

Instead of doing this:

admin.messaging().send

I had to use:

 admin.messaging().sendToDevice

The final cloud function looks like this:

const payload = {
            notification: {
                    title:  `John just joined`,
                    body: `Your friend John is now on your app`,
                    sound: 'default',
                    badge: `1`
                }
            };

            const options = {
                priority: "high",
                timeToLive: 60 * 60 *24
            };

            admin.messaging().sendToDevice(tokenID, payload, options).then(function(response) {
                console.log(`? Successfully sent message: ${response}`);
                return true;
            }).catch(function(error) {
                console.log('? Error sending message:', error);
                return false;
            });

Hope it helps someone.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Gugulethu