Need Help with Handling Push Notifications in iOS AppDelegate

Hi everyone,

I’m currently developing an app using Capacitor and I need to handle push notifications natively on iOS. Specifically, I want Capacitor to notify my AppDelegate with the contents of the push notification.

I’ve tried the following setup in my AppDelegate:

import UIKit
import Capacitor

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var pushNotificationHandler: CustomPushNotificationHandler?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Initialize CustomPushNotificationHandler
        self.pushNotificationHandler = CustomPushNotificationHandler()

        // Configure NotificationRouter
        notificationRouter.pushNotificationHandler = self.pushNotificationHandler
        
        return true
    }
}

Here is my CustomPushNotificationHandler:

import UIKit
import UserNotifications
import Capacitor

class CustomPushNotificationHandler: NSObject, NotificationHandlerProtocol {
    func willPresent(notification: UNNotification) -> UNNotificationPresentationOptions {
        // Additional tasks before the notification is presented
        print("Notification received while app is in the foreground: \(notification.request.content.userInfo)")
        return [.alert, .sound, .badge]
    }

    func didReceive(response: UNNotificationResponse) {
        // Additional tasks when the user interacts with the notification
        print("User interacted with the notification: \(response.notification.request.content.userInfo)")
        NotificationCenter.default.post(name: Notification.Name("didReceiveRemoteNotification"), object: response.notification.request.content.userInfo)
    }
}

Unfortunately, this doesn’t seem to be working. I need to obtain the push notification data natively in iOS.
my appdelegate

import UIKit
import Intents
import AVFAudio
import Capacitor
import Firebase
import PushKit



@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var sip: SipMobile?
    var callKit: CallKitIntegration?
    var voipRegistry: PKPushRegistry?
    var pushNotificationHandler: CustomPushNotificationHandler?
    let notificationRouter = NotificationRouter()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        print("AppDelegate didFinishLaunchingWithOptions")
        FirebaseApp.configure()
    
        
        // Inicializar el manejador de notificaciones push personalizado
        self.pushNotificationHandler = CustomPushNotificationHandler()

        // Configurar el NotificationRouter
        notificationRouter.pushNotificationHandler = self.pushNotificationHandler
        
        self.sip = SipMobile()
        self.callKit = CallKitIntegration(sip: self.sip!)
        self.sip!.setVoip(callKit!)

        self.voipRegistry = PKPushRegistry(queue: nil)
        self.voipRegistry?.delegate = self.callKit
        self.voipRegistry?.desiredPushTypes = [.voIP]

        return true
    }
    @objc func handleWillPresentNotification(_ notification: Notification) {
         if let notification = notification.object as? UNNotification {
             let userInfo = notification.request.content.userInfo
             print("Will present notification: \(userInfo)")
             // Maneja la notificación aquí
         }
     }

     @objc func handleDidReceiveNotificationResponse(_ notification: Notification) {
         if let response = notification.object as? UNNotificationResponse {
             let userInfo = response.notification.request.content.userInfo
             print("Did receive notification response: \(userInfo)")
             // Maneja la respuesta de la notificación aquí
         }
     }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("AppDelegate didRegisterForRemoteNotificationsWithDeviceToken")
        NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("AppDelegate didFailToRegisterForRemoteNotificationsWithError")
        NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // Manejar la notificación aquí
        print("AppDelegate Notificación recibida: \(userInfo)")
        NotificationCenter.default.post(name: Notification.Name("didReceiveRemoteNotification"), object: userInfo)
        completionHandler(.newData)
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
        return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
    }

    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
    }
    func applicationWillResignActive(_ application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }
    func applicationDidEnterBackground(_ application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }
    func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    func applicationWillTerminate(_ application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


    
}

//extension AppDelegate: NotificationHandlerProtocol {
//    func willPresent(notification: UNNotification) -> UNNotificationPresentationOptions {
//        let userInfo = notification.request.content.userInfo
//               print("AppDelegate NotificationHandlerProtocol Will present notification: \(userInfo)")
//               // Maneja la notificación aquí
//
//               return [.alert, .sound, .badge]
//    }
//    
//    func didReceive(response: UNNotificationResponse) {
//        let userInfo = response.notification.request.content.userInfo
//        print("AppDelegate NotificationHandlerProtocol Did receive notification response: \(userInfo)")
//    }
//    
//    
//}

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        print("AppDelegate UNUserNotificationCenterDelegate Notificación en primer plano: \(userInfo)")
        NotificationCenter.default.post(name: Notification.Name("didReceiveRemoteNotification"), object: userInfo)
        completionHandler([.alert, .sound, .badge])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        print("AppDelegate UNUserNotificationCenterDelegate Respuesta de notificación: \(userInfo)")
        NotificationCenter.default.post(name: Notification.Name("didReceiveRemoteNotification"), object: userInfo)
        completionHandler()
    }
}

Could anyone guide me on how to properly set this up so that my AppDelegate can handle push notifications directly? Any help or examples would be greatly appreciated.

Thank you!

Did you follow the docs? I don’t see anywhere in your code the needed methods.

How do I ask a good question? - Help Center - Stack Overflow

1 Like

I have shown the code I have in the AppDelegate and the tests I have been doing to try to override the Capacitor class that handles push notifications so that I get notified in my AppDelegate when push notifications arrive. As I mentioned in the description, what I want is to subscribe to some protocol or notification so that Capacitor notifies me every time a push notification arrives in my native code in the AppDelegate.

El El mié, 31 jul 2024 a las 16:20, John Doe via Ionic Forum <notifications@ionicframework.discoursemail.com> escribió: