How do you allow tasks that take longer than the 30 seconds allowed in the background thread to continue performing until done?

I am making a video sharing app, and in my app I am trying to upload videos to firebase. When I try to upload a video that is less than 1 minute long it works perfectly fine, but when I try to upload a video that is longer than 1 minute it does not work.

I think the reason for this is because background threads only allow 30 seconds before it is terminated and it gives me this error:

[BackgroundTask] Background Task 27 ("GTMSessionFetcher-firebasestorage.googleapis.com"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.

After I realized I was getting this error I tried to implement the UIApplication.endBackgroundTask(_:) to extend the amount of time that this process can finish and I tried using this which I got from apples documentation:

    func saveMovie(path: String, file: String, url: URL) {

        var backgroundTaskID: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid

        // Perform the task on a background queue.

        DispatchQueue.global(qos: .utility).async {

            // Request the task asseration and save the ID

            backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish doing this task", expirationHandler: {

                // End the task if time expires

                UIApplication.shared.endBackgroundTask(backgroundTaskID)

                backgroundTaskID = UIBackgroundTaskIdentifier.invalid

            })

            // Send the data synchronously

            do {

                let movieData = try Data(contentsOf: url)

                self.storage.child(path).child("\(file).m4v").putData(movieData)

            } catch let error {

                fatalError("Error saving movie in saveMovie func. \(error.localizedDescription)")

            }

            //End the task assertion

            UIApplication.shared.endBackgroundTask(backgroundTaskID)

            backgroundTaskID = UIBackgroundTaskIdentifier.invalid

        }

    }

Unfortunately this did not work and I am still getting the same error.

I am now stuck and unsure how I can allow this process to finish before background task terminates itself. Does anybody know how to allow a long-running task like this finish before it is terminated? Thanks in advance for any help!

Answered by Frameworks Engineer in 697230022

It is not possible to extend a background task for longer than the system decides to give you (usually 30 seconds - although that's not even guaranteed by the API - you could get less or more!). You should always call endBackgroundTask when a background task is done, but all that does is let the system know you're done, so that it can know it's safe to suspend the app. It does not extend the time you get to perform the task.

For uploading to servers, you can use the URL loading system, which can operate in the background while the app is not running, so you don't need to worry about termination. See also discussion here: https://developer.apple.com/forums/thread/10239

Accepted Answer

It is not possible to extend a background task for longer than the system decides to give you (usually 30 seconds - although that's not even guaranteed by the API - you could get less or more!). You should always call endBackgroundTask when a background task is done, but all that does is let the system know you're done, so that it can know it's safe to suspend the app. It does not extend the time you get to perform the task.

For uploading to servers, you can use the URL loading system, which can operate in the background while the app is not running, so you don't need to worry about termination. See also discussion here: https://developer.apple.com/forums/thread/10239

How do you allow tasks that take longer than the 30 seconds allowed in the background thread to continue performing until done?
 
 
Q