Skip to content

Using Push notifications to initiate downloading when app is in background or not running state

Davor Komušanac edited this page Dec 5, 2022 · 2 revisions

Mobile Messaging SDK is designed to deliver notification content to the application as soon as possible, even if notification arrives when application is in the background, suspended or not running state.

To accomplish this, all notifications are being sent with content-available key set to 1 (Apple Notifications Payload). This literally means that new content is available on the server and iOS is allowed to run the application in background (by moving the app from the suspended state or launching it after terminating) so that application can start downloading the new content right away (Apple Background Execution Documentation).

Notice

In order to enable this feature, go to your applications target settings -> "Capabilities" tab and check the "Remote Notifications" option in the "Background Modes" section.

After the notification has been received and the app has been moved into the background state, MobileMessaging SDK synchronises itself with the server with just a single HTTP request: reports about delivery and fetches not delivered notifications (Message fetching).

When the synchronisation is finished, MobileMessaging SDK executes a fetch completion handler (fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void), passing a result to the handler which indicates whether new notifications were fetched or not (UIBackgroundFetchResult). The result tells the iOS that it can move the application back to the suspended state and evaluate its power usage.

You can download additional data and provide your own UIBackgroundFetchResult. To do this, integrate library by app delegate composition, in your AppDelegate file implement the method application(_:didReceiveRemoteNotification:fetchCompletionHandler:) as follows:

func application(_ application: UIApplication, 
	           didReceiveRemoteNotification userInfo: [AnyHashable: Any], 
	           fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
		
        let customCompletionHandler: (UIBackgroundFetchResult) -> Void = 
           { (result) in
                //...
		//download operation can be initialed here
                //...
		let customResult = <# either .noData, .newData or .failed in accordance of the result of download #>
		completionHandler(customResult)
	   }
	MobileMessaging.didReceiveRemoteNotification(userInfo, fetchCompletionHandler: customCompletionHandler)
}

You can also use DispatchGroup to start several asynchronous tasks simultaneously with MobileMessaging SDK message handling and call the fetch completion handler once all of them has finished.

Notice

iOS won't wake up your application, when a notification with content-available flag arrives, in following cases:

  1. Application was killed by the user.
  2. "Low power mode" is enabled - it restricts most of background activities.
  3. In cases when the app drains too much battery during the background activity.
Clone this wiki locally