1

I have successfully implemented push notifications in my two related apps via FCM and while trying to implement some logic to increment badge number on receiving the notification.

I realized that didReceiveRemoteNotificationdelegate method is not called at all as I don't get any prints out of it, but I do get prints from willPresent notificationand didReceive response. So setting UIApplication.shared.applicationIconBadgeNumber in didFinishLaunchingWithOptionshas no effect, but setting in it didReceive responsedoes.

Following the documentation didReceiveRemoteNotification should be called but I never get prints out of it when a notification arrives.

I tried commenting out the whole didReceiveRemoteNotificationmethod and notifications are still delivered.

Why is it so? I guess I didn't really understand who's handling messaging in this set up. Can you please help me clarifying it?

AppDelegate methods:

didFinishLaunchingWithOptions:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        window?.tintColor = UIColor.blue
        // Use Firebase library to configure APIs
        FirebaseApp.configure()
        Messaging.messaging().delegate = self
        Crashlytics().debugMode = true
        Fabric.with([Crashlytics.self])
        // setting up notification delegate
        if #available(iOS 10.0, *) {
            //iOS 10.0 and greater
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            //Solicit permission from the user to receive notifications
            UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: { granted, error in
                DispatchQueue.main.async {
                    if granted {
                        print("didFinishLaunchingWithOptions iOS 10: Successfully registered for APNs")
                        UIApplication.shared.registerForRemoteNotifications()
//                        UIApplication.shared.applicationIconBadgeNumber = 1
                        AppDelegate.badgeCountNumber = 0
                        UIApplication.shared.applicationIconBadgeNumber = 0
                    } else {
                        //Do stuff if unsuccessful...
                        print("didFinishLaunchingWithOptions iOO 10: Error in registering for APNs: \(String(describing: error))")
                    }
                }
            })
        } else {
            //iOS 9
            let type: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound]
            let setting = UIUserNotificationSettings(types: type, categories: nil)
            UIApplication.shared.registerUserNotificationSettings(setting)
            UIApplication.shared.registerForRemoteNotifications()
//            UIApplication.shared.applicationIconBadgeNumber = 1
            UIApplication.shared.applicationIconBadgeNumber = 0
            print("didFinishLaunchingWithOptions iOS 9: Successfully registered for APNs")
        }
        // setting up remote control values
        let _ = RCValues.sharedInstance
        GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
        Crashlytics().debugMode = true
        Fabric.with([Crashlytics.self])
        //        // TODO: Move this to where you establish a user session
        //        self.logUser()
        var error: NSError?
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        } catch let error1 as NSError{
            error = error1
            print("could not set session. err:\(error!.localizedDescription)")
        }
        do {
            try AVAudioSession.sharedInstance().setActive(true)
        } catch let error1 as NSError{
            error = error1
            print("could not active session. err:\(error!.localizedDescription)")
        }
        // goggle only
        GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
//        GIDSignIn.sharedInstance().delegate = self
        // Facebook SDK
        return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
//        return true
    }

didReceiveRemoteNotification:

 // foreground
        func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
            print("didReceiveRemoteNotification: Received new push Notification")
            // 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

            // With swizzling disabled you must let Messaging know about the message, for Analytics
            Messaging.messaging().appDidReceiveMessage(userInfo)
            AppDelegate.badgeCountNumber += userInfo["badge"] as! Int
            print("AppDelegate.badgeCountNumber is : \(String(describing: AppDelegate.badgeCountNumber))")
//            UIApplication.shared.applicationIconBadgeNumber = AppDelegate.badgeCountNumber
            UIApplication.shared.applicationIconBadgeNumber =  10//AppDelegate.badgeCountNumber
            // Print full message.
            print("didReceiveRemoteNotification: Push notificationMessage is: \(userInfo)")
        }




        // background
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("didReceiveRemoteNotification with handler : Received new push Notification while in background")
        // 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

        // With swizzling disabled you must let Messaging know about the message, for Analytics
        Messaging.messaging().appDidReceiveMessage(userInfo)
        if let messageID = userInfo[ userDetails.fcmToken] { // working for looged in
            print("didReceiveRemoteNotification: Message ID: \(messageID)")
        }

        // Print full message.
        print("didReceiveRemoteNotification: Push notificationMessage is: \(userInfo)")
        AppDelegate.badgeCountNumber += userInfo["badge"] as! Int
        print("AppDelegate.badgeCountNumber is : \(String(describing: AppDelegate.badgeCountNumber))")
        UIApplication.shared.applicationIconBadgeNumber +=  userInfo["badge"] as! Int
        completionHandler(UIBackgroundFetchResult.newData)
    }
Vincenzo
  • 5,304
  • 5
  • 38
  • 96
  • Please check your added didReceiveRemoteNotification delegate method its deprecated? – Siva May 30 '19 at 10:31
  • @Ranjani I updated the code to show the `didReceiveRemoteNotification`code as well. No, I don't get any warn regarding it being depreciated. Any Ideas of what's going on? It should be called right? – Vincenzo May 30 '19 at 10:49
  • As I'm about to implement rich remote notifications this is something that I have to sort out before I even start or it will be a lot of frustration I guess.. – Vincenzo May 30 '19 at 10:51
  • Please show the didReceiveRemoteNotification declaration code and refer this link also https://stackoverflow.com/questions/35724945/swift-didreceiveremotenotification-not-called – Siva May 30 '19 at 11:40
  • @Ranjani I did put the `didReceiveRemoteNotification` code in question. Thanks for the link – Vincenzo May 30 '19 at 11:41
  • Please check your Target->capabilities -> Background Modes remote notification option is enabled – Siva May 30 '19 at 11:48
  • @Ranjani it is enabled both, remote notifications in Background Modes and Push Notifications. – Vincenzo May 30 '19 at 11:52
  • @Ranjani I finally solved it. Thanks for trying helping out. – Vincenzo May 30 '19 at 16:51

2 Answers2

2

I finally found the solution. Alert needs"content_available": true to be set in the alert definition from the post sending funtion from App2 to App1 or else notifications get delivered but 'didReceiveRemoteNotification` is not called and you can't use 'userInfo'. Hope this will help others as I haven't found much info about this problem. If you're setting the notification with Postman or similars check here didReceiveRemoteNotification function doesn't called with FCM notification server as that's the only post I found on this problem and solved mine. Thanks to @Ranjani for trying helping me.

let postParams: [String : Any] = [
                "to": receiverToken,
                "notification": [
                    "badge" : 1,
                    "body": body,
                    "title": title,
                    "subtitle": subtitle,
                    "sound" : true, // or specify audio name to play
                    "content_available": true, // this will call didReceiveRemoteNotification in receiving app, else won't work
                    "priority": "high"
                ],
                "data" : [
                    "data": "ciao",
            ]
                ]
Vincenzo
  • 5,304
  • 5
  • 38
  • 96
  • does not fit for my case T_T – The Dongster Sep 17 '19 at 07:40
  • Even though the answer doesn't say so, the code in this answer is for FIREBASE CLOUD MESSAGING ("FCM"), and is not going to help with any other push notification service. (The only other hint is the tag that was added to the question.) – Robin Daugherty May 28 '20 at 17:55
  • @RobinDaugherty Hi, Indeed the answer is for FCM as the question is about FCM. But good point. Thanks. – Vincenzo May 28 '20 at 18:12
0

For Node.js (send to topic example)

var admin = require("firebase-admin");

var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "<your database URL>"
});

var topic = "topicA";

var payload = {
    notification: {
        title: "title",
        body: "body",
        sound: "default"
    },
    data: {
        a: "dataA",
        b: "dataB"
    }
};

var options = {
    content_available: true,
    priority: "high",
    timeToLive: 1
};

// Send a message to devices subscribed to the provided topic.
admin.messaging().sendToTopic(topic, payload, options)
    .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
    })
    .catch((error) => {
        console.log('Error sending message:', error);
    });
leesa1522
  • 1
  • 1