iOS 13 background download issue
Asked Answered
S

1

6

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.

Selfsufficient answered 27/1, 2020 at 7:1 Comment(1)
Did you figure out how to overcome this behavior? I have the same problem and already spent days trying to figure it out... Everything works perfectly on iOS13-Yahweh
M
3

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.

Monolatry answered 27/1, 2020 at 8:52 Comment(8)
thanks for your reply. Your question made me aware that the question was a bit ambiguous, so have re-worded it. I have already added the "handleEventsForBackgroundURLSession" callback, and found that the respective logs are not printed.Selfsufficient
Can you verify that all of your background downloads are finishing? If one of them hangs or fails, it will prevent the completion of the background session to be triggered. The delegate method is only called when everything is done, that means that your app will not be activated. Have you checked the device's console for some diagnostic error messages?Monolatry
Hi cristallo, the background downloads do not complete (There are around a few hundred files, of which at least 2-3 are started parallely). Rather I do not see any update for a download ongoing when app goes to background. This is evident from the app size in the settings. I want to figure out the same... why the download does not continue when app is put to background.Selfsufficient
Did you properly configure urlsession with shouldUseExtendedBackgroundIdleMode and discretionary mode?Monolatry
Yes, I tried with shouldUseExtendedBackgroundIdleMode. Also, tried with both values true and false for isDiscretionary. Yet, it is not working. I cannot see the log for the method - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) which is invoked after completion of individual task.Selfsufficient
Have you checked the device's console for diagnostic error messages?Monolatry
Yes, I ca n see the logs like this related to nsurlsessiond: logTaskError isDownload = Y bytesReceived = 111134 bytesSent = 0 isRecoverable = NSelfsufficient
I am pretty confused ... I've try to run then following example on ios13 and it is working fine. raywenderlich.com/3244963-urlsession-tutorial-getting-started Can you try to do the same? just to see if it works or not. It looks pretty similar to your use caseMonolatry

© 2022 - 2024 — McMap. All rights reserved.