Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 13 background download issue

I have a syncing functionality, where a series of downloads happens in the background.

For that, I create a URLSession instance with background configuration as below:

let config = URLSessionConfiguration.background(withIdentifier: "BackgroundSessionDL")
config.httpMaximumConnectionsPerHost = 20

self.session = URLSession(configuration: config, delegate: self, delegateQueue: nil)

Each of the download tasks (which may be in a number of few hundreds) is added as follows:

var request = URLRequest(url: url)
request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

let downloadTask = self.session.downloadTask(with: request)
downloadTask.resume()

This code works perfectly on iOS 12 or earlier - the download continues even in the background for the tasks already added. But, for iOS 13, causes issue as follows:

  1. As soon as app goes to background, downloading stops.
  2. If any download task is in progress and app is put to background, no callaback related logs are observed even after app is again brought to foreground.

I tried to search whether any new classes/framework introduced by Apple for background task download on iOS 13, but did not find anything on this. Also, class used in earlier versions, for representation of a background download task, is still NOT deprecated in iOS 13 and is the only result when searched for background download on iOS 13. Similarly, background configuration used for the HTTP session, is still NOT deprecated. So, I believe the current background download implementation is the one recommended by Apple. (As per my understanding, "BGTaskScheduler" is not intended for this, please correct me if wrong).

So, is this due to any newly introduced bug in iOS 13? OR any change in this implementation, specific to iOS 13, is expected by Apple?

Edit:

I have already added the handleEventsForBackgroundURLSession callback. Found that the respective logs are not printed and app size does not increase in Settings on iOS 13. So, it appears that download does not continue in the background and it is not related to download related callbacks not getting invoked.

like image 329
Harish J Avatar asked Jan 27 '20 07:01

Harish J


People also ask

Can iOS download in background?

When a user requests a background download, iOS spawns a separate process that does only this — downloads the file in the background. This process sends status notifications to the parent process. The parent process must conform to NSURLSessionTaskDelegate protocol to be able to receive notifications.

How do I stop background downloads on iPhone?

Tap on Background App Refresh. A new screen will appear with an option called Background App Refresh and a slide button. Slide the button into the off position.

What is download in the background?

Background download is a feature that enables you to perform other operations while downloading multiple data items or data with a large file size. This feature is available only when the [Download in Background] option is displayed on the screen that is displayed while downloading content.


1 Answers

I guess that if you run the app in the foreground then everything works as expected however as soon as the app is put into the background no callback are received anymore

BackgroundDownloader only works when the app is in the foreground but there is a specific support when the app enters a suspended/backgrounded state.

When an app is in a suspended/terminated state and a download is completed, iOS will wake the app up (in the background) by calling:

class AppDelegate: UIResponder, UIApplicationDelegate { 

    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        //TODO: Handle processing downloads
    }
}

The behavior change between ios12 and ios13 is probably not related to some API changes but just with a more aggressive power saving policy for app while they are not in foreground

Modify the URLSession background configuration identifier Making the isDiscretionary as false in order to avoid OS scheduling the background request transfers due to battery or performance The most important one shouldUseExtendedBackgroundIdleMode as true. This is the ultimate line that makes the TCP sockets open even when the app is locked or suspended.

like image 94
cristallo Avatar answered Oct 03 '22 15:10

cristallo