Files
workavia-mail-front/docs/adr/0051-push-notification-click-logic-on-ios.md

3.1 KiB

51. Push notification click logic on iOS

Date: 2024-06-07

Status

Accepted

Context

On iOS, we use Notification Service Extension NSE to modify email content first when displaying push notifications to users.

  • In NSE we have implemented getting new email list based on EmailDeliveryState sent from FCM.
  • NSE only modifies and displays 1 notification, so we will display the notification for the last email in the list via NSE (is called RemoteNotification). For the remaining emails we will use UNUserNotificationCenter to automatically display notifications (is called LocalNotification).

Decision

Brief the logic flows when clicking notifications:

  1. Foreground/Background state
  • When clicking on notifications (both LocalNotification and RemoteNotification) the didReceive function of UNUserNotificationCenter in AppDelegate will be called.
 override func userNotificationCenter(
    _ center: UNUserNotificationCenter, 
    didReceive response: UNNotificationResponse, 
    withCompletionHandler completionHandler: @escaping () -> Void
 ) {}

response.notification.request.content.userInfo is the contents of the push payload notification. We use FlutterMethodChannel to pass UserInfo from iOS native code to Flutter dart code

  self.notificationInteractionChannel?.invokeMethod("current_email_id_in_notification_click_when_app_foreground_or_background", arguments: response.notification.request.content.userInfo)
  1. Terminated state
  • With RemoteNotification, we will get the push notification payload through launchOptions?[.remoteNotification] in the didFinishLaunchingWithOptions function of AppDelegate
override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {}

Save it in a remoteNotificationPayload variable in memory and use FlutterMethodChannel to retrieve it every time you open the app.

self.notificationInteractionChannel?.setMethodCallHandler { (call, result) in
    switch call.method {
        case "current_email_id_in_notification_click_when_app_terminated":
            result(self.remoteNotificationPayload)
            self.remoteNotificationPayload = nil
        default:
            break
    }
}
  • As for LocalNotification, we will receive the push notification payload at the didReceive function of UNUserNotificationCenter (similar to Foreground/Background state)
 override func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
) {
    self.remoteNotificationPayload = response.notification.request.content.userInfo
 }

Consequences

  • The application is correctly adjusted to the detailed screen email when clicking on the notification.
  • Any changes to the click push notification logic must be updated in this ADR.