nzackoya
nzackoya

Reputation: 356

IOS: Inapp notification + Notification Service + Content extensions

The thing is that notification service extension is useless by itself, except one thing that it can be shown when the app is killed. So with inapp notifications and content extension I can show custom notification, but that notification will appear only if the app is not killed/force-closed. Question: How to manage the inapp notifications in case there are content and service notifications extensions, and how to force notifications service extension to call/wake up the notification content extension.

Upvotes: 0

Views: 815

Answers (1)

nzackoya
nzackoya

Reputation: 356

Seemed that I needed to clean the project and remove the app and install again. Here is the full steps for FCM to achieve this case, maybe some of the steps are redundant, but I don't want to touch it while it is working :

App is killed/closed: Notification appears with custom content view App is in background: Notification appears with custom content view App is in foreground: Notification arrives silently

  1. From server side the notification should look like this

    { "notification"://mandatory { "data":{}, "body":""//seemed mandatory as well, anyway you can change it in service extension } "content_available":true,//mandatory "mutable_content":true,//mandatory "to":""//mandatory }

  2. Create Notification Service Extension target.

  3. In info.plist under NSExtension add UNNotificationExtensionCategory as Array and add one category with whatever name you want, but use the same one everywhere.
  4. In Notification Service Extension target be sure everything is same as in main target(swift version, build version, deployment target, devices).
  5. In capabilities add app groups(should be same as in main target).
  6. In NotificationService in didReceive get the mutable content

    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

  7. Add your category to the content

    bestAttemptContent.categoryIdentifier = "yourCategory"

  8. After calling contentHandler(bestAttemptContent) the standart notification appears.

  9. Create Notification Content Extension target.

  10. In info.plist under NSExtension add UNNotificationExtensionCategory as Array and add one category with same name you already created for the service.
  11. Change the design in MainInterface.storyboard according to your design.
  12. In NotificationViewController the custom data will be in notification.request.content.userInfo["gcm.notification.data"] . So in NotificationViewController fill the views with the data. Don't forget about the the preferredContentSize.
  13. In capabilities add app groups(should be same as in main target).
  14. In main target AppDelegate implement UNUserNotificationCenterDelegate.
  15. In didFinishLaunchingWithOptions add

    UNUserNotificationCenter.current().delegate = self UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in } application.registerForRemoteNotifications()

  16. In AppDelegate add

    func application( _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data ) { Messaging.messaging().apnsToken = deviceToken }

  17. In userNotificationCenter willPresent check if your app is not running. I made it this way:

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { if self.window?.rootViewController == nil { completionHandler([.badge, .alert, .sound]) } UIApplication.shared.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1 }

  18. Handle the silent notification here:

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

    1. Handle the tap on the notification in here:

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)

here you can get the custom data with the same way response.notification.request.content.userInfo["gcm.notification.data"]

  1. If you have async network calls to load data/images don't forget to implement func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void)

Seems that's all :) . Ah, the extensions are working starting IOS 10. Please correct me if there is something missing or something is redundant.

Upvotes: 1

Related Questions