Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call API when app is terminated in push notifcation iOS Swift?

We are working on push notification. We need to call the web service when we get a notification in active, background, foreground and terminated. But when we terminated the app we get a notification but can’t able to call the web service. The reason for calling the web service is to identify the message was received for a mobile app.

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if ( application.applicationState == .inactive || application.applicationState == .background ) {
                **// Need to call API**
        }
    }

Is any other way to identify the message was delivered in mobile app in the server side?

like image 205
HariKarthick Avatar asked Jan 17 '19 12:01

HariKarthick


People also ask

Do push notifications work when app is closed iOS?

Apple does not offer a way to handle a notification that arrives when your app is closed (i.e. when the user has fully quit the application or the OS had decided to kill it while it is in the background). If this happens, the only way to handle the notification is to wait until it is opened by the user.

How can we execute code when app is not running in iOS?

You can't run any code when the app is terminated in iOS as given in the documentation. You can do something before the app is going to get terminated by using the following ways. func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate.

Do push notifications expire?

Your push notifications certificates are generally only valid for one year.


2 Answers

As per Apple guidelines, you can get push notification for the background as well as on foreground state but when it comes to Terminate state apple don't allow you to automatically open the app or do any kind of operation unless you launch the app through notification.

Though you can handle notification during the Terminated state using Launch Options at the time of app launch.

Coding Example:

In your AppDelegate.swift import firebase library

import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications

Whenever app launch register for push notification service, add the following lines of code into your didFinishLaunchingWithOptions

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    registerForPushNotifications(application: application)
    handleNotificationWhenAppIsKilled(launchOptions)
    return true
}

func handleNotificationWhenAppIsKilled(_ launchOptions: [UIApplicationLaunchOptionsKey: Any]?) {
    // Check if launched from the remote notification and application is close
    if let remoteNotification = launchOptions?[.remoteNotification] as?  [AnyHashable : Any] {
        // Handle your app navigation accordingly and update the webservice as per information on the app.
    }
}

Add extension methods of appDelegate to register for remote notification and to get device token from APNS

//MARK: - Notifications related...
extension AppDelegate {
    func registerForPushNotifications(application: UIApplication) {
        if #available(iOS 10.0, *) {
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
            // For iOS 10 data message (sent via FCM
            Messaging.messaging().delegate = self
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        let savedAPNSToken = UserDefaults.standard.object(forKey: "savedAPNSToken") as? String
        if savedAPNSToken != token {
            UserDefaults.standard.set(token, forKey: "savedAPNSToken")
            UserDefaults.standard.synchronize()
            Messaging.messaging().apnsToken = deviceToken
        }
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(error.localizedDescription)
    }

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

}

Use the following methods of notificationCenter to handle notification in the foreground and background states :

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

    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        completionHandler([.alert])
    }


    /// Handle tap on the notification banner
    ///
    /// - Parameters:
    ///   - center: Notification Center
    ///   - response: Notification response
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {

        let userInfo = response.notification.request.content.userInfo
        completionHandler()
    }

Firebase token renewel:

extension AppDelegate : MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        // Note: This callback is fired at each app startup and whenever a new token is generated.
        let savedFCMToken = UserDefaults.standard.object(forKey: "savedFCMToken") as? String
        if savedFCMToken != fcmToken {
            UserDefaults.standard.set(fcmToken, forKey: "savedFCMToken")
            UserDefaults.standard.synchronize()
            // Update FCMToken to server by doing API call...
        }
    }
}
like image 54
Jarvis The Avenger Avatar answered Nov 05 '22 20:11

Jarvis The Avenger


We have a option called silent notification check below link https://medium.com/@m.imadali10/ios-silent-push-notifications-84009d57794c

like image 1
Rajasekaran Gopal Avatar answered Nov 05 '22 22:11

Rajasekaran Gopal