6

I'm newbie to Swift, I am creating chat application, I need to send notification when app is in foreground or minimized.

But I am not getting the notification when app is minimized (it works when USB is connected.

  1. Enabled Remote notification

  2. Background Fetches in Xcode setup

  3. Enabled Push Notification

  4. Production APns certificate

Notification code:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let gcmMessageIDKey = "gcm.message_id"

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        FirebaseApp.configure()

        Messaging.messaging().delegate = self
        Messaging.messaging().shouldEstablishDirectChannel = true

        if #available(iOS 10.0, *) {

            UNUserNotificationCenter.current().delegate = self

            let authOptions: UNAuthorizationOptions = [.alert, .sound, .badge]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
            application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()

        NotificationCenter.default.addObserver(self, selector: #selector(tokenRefreshNotification(_:)), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)

        return true
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {

        Messaging.messaging().appDidReceiveMessage(userInfo)         
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

        Messaging.messaging().appDidReceiveMessage(userInfo)

        let action = userInfo["action"] as! String
        let notification = UILocalNotification()
        notification.fireDate = NSDate() as Date
        notification.alertTitle = "test"
        notification.alertBody = "test"
        notification.alertAction = "Ok"
        UIApplication.shared.applicationIconBadgeNumber =  1
        UIApplication.shared.scheduleLocalNotification(notification)

        completionHandler(UIBackgroundFetchResult.newData)
    }

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

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("APNs token retrieved: \(deviceToken)")

        // With swizzling disabled you must set the APNs token here.
        Messaging.messaging().apnsToken = deviceToken
    }       
}

@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo

        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        completionHandler([.alert, .sound, .badge])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo

        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        print(userInfo)

        completionHandler()
    }
    @objc func tokenRefreshNotification(_ notification: Notification) {
            guard let token = InstanceID.instanceID().token() else {
            print("No firebase token, aborting registering device")
            return
        }
        print("No firebase token, aborting registering device")           
    }
}   

extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
        Messaging.messaging().subscribe(toTopic: "/topics/channel_18")           
    }

    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
        print("Received data message: \(remoteMessage.appData)")
    }        
}

FCM Payload:

 {
     "to" : "/topics/channel_18",
     "data" : {
      "action" : "NOTIFY",
      "message" : "{"text":"test" }"
     },
     "content_available" : true
    }

I have tried with Priority high and with Sound option but none works.

Please note that I am not using "notification" key as per client request. i am using only data-message in FCM payload

Please anyone help me to work notification when app is in background without USB connection.

US-1234
  • 1,519
  • 4
  • 24
  • 61
  • Just to be clear: it works when app is in forgeround? but just doesn't work when you press home button? – mfaani Jul 30 '18 at 11:26
  • 1. "but i am not getting the notification when app is minimized (it works when USB is connected." what do you mean by this? 2. Are you testing on a physical device or you're using the simulator? – mfaani Jul 30 '18 at 11:36
  • i am using physical device – US-1234 Jul 30 '18 at 12:22
  • notification is not working when screen is locked – US-1234 Jul 30 '18 at 12:23
  • does it work when the app is in the background? ie Just pressing home and not locking the phone? – mfaani Jul 30 '18 at 12:28
  • No it does not work, it works only app is in foreground – US-1234 Jul 31 '18 at 10:42
  • 1
    just to be sure, are you killing the app? ie you're double clicking home button and then swiping the app up? Also have you seen [here](https://stackoverflow.com/questions/42275060/what-is-difference-between-remote-notification-and-silent-notification-in-ios#42302369) – mfaani Jul 31 '18 at 14:42
  • i am not killing the app. just minimized – US-1234 Aug 01 '18 at 04:27
  • On the iphone do you have background app refresh enabled? See [this](https://i.stack.imgur.com/AJ0cG.jpg) – mfaani Aug 01 '18 at 06:44
  • yes its enabled for my app – US-1234 Aug 01 '18 at 06:45
  • notification does not work when is in lock mode too – US-1234 Aug 01 '18 at 06:46
  • I have updated above my full AppDelegate.swift file – US-1234 Aug 01 '18 at 06:50
  • Can you edit and remove the comments from your code? – mfaani Aug 01 '18 at 17:05
  • Aside from your edit, please make sure you see the entire linked question. Additionally I have two more suggestion: a) of all your first 3 steps (Enabled Remote notification Background Fetches in Xcode setup Enabled Push Notification) just unselect and then select again and try again. b) remove the "content-available" flag from your payload and try again and just validate if you get any sort of notification. If that doesn't work then I can't think of anything else :/ – mfaani Aug 01 '18 at 17:56
  • and as a last resort try testing with another device... – mfaani Aug 02 '18 at 02:54
  • tried your points still background notification is not working, is it working for you ? – US-1234 Aug 02 '18 at 04:59
  • if i remove content-available: true then foreground notification is also not working since its s data-message notification – US-1234 Aug 02 '18 at 05:04
  • with information your providing, I think your payload is set incorrectly. I've never used Firebase. See [here](https://stackoverflow.com/a/38277476/5175709). Set your payload accordingly. Also note the comments below it. I'm guessing you're missing the notification object itself. Also based on the research done [here](https://stackoverflow.com/a/43854631/5175709) it seems that you need to include **both** `title` and `body` fields for it to work. – mfaani Aug 02 '18 at 06:16
  • i am not used notification in payload, since notification should handle only by app not OS – US-1234 Aug 02 '18 at 10:21
  • What do you mean app not OS? Do you mean you want it to be silent notification only? And not send a visible user notification? If that's your case still just do what I said so that you can make sure it's working for non Silent notifications – mfaani Aug 02 '18 at 12:02
  • yes Silent notification only i need, when app in background (app is minimized ) didReceiveRemoteNotification is not being called – US-1234 Aug 02 '18 at 12:19
  • Understood. Still add notification field and see if it works for nonSilent notification – mfaani Aug 02 '18 at 12:36
  • it works with notification object in payload. but my requirement is with silent push notification – US-1234 Aug 02 '18 at 12:38
  • I've made an edit. – mfaani Aug 06 '18 at 12:06

1 Answers1

2

If it works with non-Silent notification then all it means is:

  • Then payload is not correctly setup. Based on the answers provided to this question I'd just alter the placement of the content_available field into notification(and since you don't want a title body then just don't add title/body) or just into the payload itself until see it working.
  • I'd also make sure all the correct capabilities in Xcode are set (Enabled Remote notification, Background Fetches in Xcode setup, Enabled Push Notification). As mentioned previously uncheck and recheck all of them again.
  • And make sure Background App refresh is enabled for your app. This is NOT the same with your notifications. Obviously make sure your notifications are also enabled.:

enter image description here

  • But if you tried everything and it just doesn't work for 11.3 then it might be a bug. There is this other open question mentioned the same issue of yours. Run the app directly from tapping the app, ie not launching from Xcode and then use the console to see what it's logging related to the silent notification. If you're getting something like this:
default 13:11:47.178186 +0200   dasd    DuetActivitySchedulerDaemon Removing a launch request for application <private> by activity <private>   default com.apple.duetactivityscheduler

Then likely it's a bug similar to this iOS11 question. But you must open a new radar, because that radar was closed I believe because it was fixed!

mfaani
  • 33,269
  • 19
  • 164
  • 293
  • notification (app in background) works in IOS10.2 but not works on latest IOS version – US-1234 Aug 03 '18 at 07:33
  • interesting. From my other [answer](https://stackoverflow.com/questions/42275060/what-is-difference-between-remote-notification-and-silent-notification-in-ios#42302369) I've linked a similar bug in iOS 11. But it was fixed by the 11.1 release. You're saying you're testing on 11.3, so you might just need to file a radar, if it doesn't work for this version only... – mfaani Aug 03 '18 at 08:08
  • my ios version is 11.4.1 beta latest not, but still same issue, i have tried in IOS version 10.2 mobile it works – US-1234 Aug 03 '18 at 08:29
  • what is your version? 11.4.1 beta or not? – mfaani Aug 03 '18 at 20:56
  • Version is 11.4.1(15G5077a) – US-1234 Aug 04 '18 at 04:59
  • then why is your question tagged with 11.3?! – mfaani Aug 04 '18 at 10:37
  • same issue in 11.3 , yesterday only updated to 11.4.1 version same case – US-1234 Aug 04 '18 at 10:42
  • when app is minimized , i am not getting notification. – US-1234 Oct 15 '18 at 03:26