Search code examples
iosflutterfirebaseapple-push-notifications

IOS notification , how to catch notification payload on tap of notification in flutter


My application is like below.

  1. Backend is sending notification to ios using node-apn package (directly using apn)
  2. APN toke is retrieved using firebase.

In backend server : A.used FCM to send notification for android and apn for IOS. Android works fine in all cases. B. used node-apn For apn ios alert push : i am not able to extract payload. (On tap of notification i want to open specific screen depending upon payload.)

Code to send notification: Node server code:

var apnProvider = new apn.Provider(apnOptions);
var note = new apn.Notification();
//Set contents for note here
…

apnProvider
      .send(note, token obtained from FirebaseMessaging.instance.getAPNSToken())

Below is final continent of note.

{
 encoding: 'utf8',
  payload: {
    messageFrom: 'Health',
    params: {
      title: 'Health',
      body: 'Hello, You have a request. Kindly check.',
      notification_type: 18,
      appointment_id: "610cc37686000662ad14c",
      send_time_in_ms: 1736510662242
    }
  },
  compiled: false,
  expiry: 1736514262,
  priority: 10,
  topic: ‘mytopic,
  pushType: 'alert'
 }

Notification is getting sent and getting displayed in notification tray on IOS , But on click of it i want to extract params from notification body and depending upon it want to navigate to special screen. Curently its just opening app and goes to home screen. How can i extract params?

below is my AppDelegates.swift in flutter project:

    @main
@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      // This is required to make any communication available in the action isolate.
      FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
        GeneratedPluginRegistrant.register(with: registry)
      }
      
      // Added as per documentation of flutter local notification package
      if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
      }
      
      GeneratedPluginRegistrant.register(with: self)

              
      //Setup VOIP (flutter_callkit_incomming)
      let mainQueue = DispatchQueue.main
      let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
      voipRegistry.delegate = self
      voipRegistry.desiredPushTypes = [PKPushType.voIP]
      print("didFinishLaunchingWithOptions")
      
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

   // As per flutter_callkit_incomming Start ///////////////////
    // Handle updated push credentials
    func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
        print(credentials.token)
        let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
        print(deviceToken)
        //Save deviceToken to your server
        SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken)
    }
    
    func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
        print("didInvalidatePushTokenFor")
        SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("")
    }

...


Solution

  • You need to implement this function from UNUserNotificationCenterDelegate to handle the push notification payload. Full documentation here.

    func userNotificationCenter(
            _ center: UNUserNotificationCenter,
            didReceive response: UNNotificationResponse,
            withCompletionHandler completionHandler: @escaping () -> Void) {
        let payload = response.notification.request.content.userInfo
    
        //TODO: - Do something with payload here
    
        completionHandler()
    }