BackgroundTask and Foreground app state

Hi,

I'm trying to better understand how BackgroundTasks work.

From what I understand the application has two interesting states: Foreground and Background. Once the app is put in background state, all executions are paused. Once back in the foreground these executions are resumed from the moment they stopped.

Assuming I have a long task to perform that starts when the app is in the foreground, is it possible that it can pick up where it left off once the app is relaunched for a BackgroundTask?

All the indications given by Apple mention use cases where the app is awakened to do other tasks from 0, but I would like to continue something that is already in progress!

I'm having a hard time experiencing this behavior because to trigger the

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"TASK_IDENTIFIER"]

command i have to resume the app as mentioned here.

So at that point I'm no longer sure if my process is continuing because I actually have the app in the foreground or it would run with the app in the background as well

thx

Answered by DTS Engineer in 706974022

From what I understand the application has two interesting states: Foreground and Background. Once the app is put in background state, all executions are paused. Once back in the foreground these executions are resumed from the moment they stopped.

That’s not quite right. It’s way more complex, but isn’t it always (-: Here’s a short list of states that I can think of:

  1. Running in the foreground

  2. Running in the background

  3. Suspended in the background

  4. Terminated in the background, eligible for relaunch

  5. Terminated in the background, ineligible for relaunch

[There’s definitely more states that don’t spring immediately to mind.]

You get into state 5 when the user removes your app from the multitasking UI.

The Background Tasks framework takes you from either states 3 or 4 to state 2.

If you get suspended while executing a long-running task, there’s a race between two events:

  • Your app being resumed, either by the user into the foreground (state 1) or by the system into the background (state 2).

  • The system terminating your app, leaving you in state 4.

If the first event wins this race, your code resumes this long-running task exactly where it left off. If the second event wins, your app gets relaunched and you are responsible for resuming the long-running task based on state that you’ve saved to disk.

Clear?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

From what I understand the application has two interesting states: Foreground and Background. Once the app is put in background state, all executions are paused. Once back in the foreground these executions are resumed from the moment they stopped.

That’s not quite right. It’s way more complex, but isn’t it always (-: Here’s a short list of states that I can think of:

  1. Running in the foreground

  2. Running in the background

  3. Suspended in the background

  4. Terminated in the background, eligible for relaunch

  5. Terminated in the background, ineligible for relaunch

[There’s definitely more states that don’t spring immediately to mind.]

You get into state 5 when the user removes your app from the multitasking UI.

The Background Tasks framework takes you from either states 3 or 4 to state 2.

If you get suspended while executing a long-running task, there’s a race between two events:

  • Your app being resumed, either by the user into the foreground (state 1) or by the system into the background (state 2).

  • The system terminating your app, leaving you in state 4.

If the first event wins this race, your code resumes this long-running task exactly where it left off. If the second event wins, your app gets relaunched and you are responsible for resuming the long-running task based on state that you’ve saved to disk.

Clear?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Ok, very clear! Thank you very much!

Only a doubt about the

The system terminating your app, leaving you in state 4.

this means that the system can terminate my app forever even if i submit an BGTaskRequest before i finish my execution time? I mean using something like

let request = BGAppRefreshTaskRequest(identifier: "<my_id>")
try BGTaskScheduler.shared.submit(request)

In this case my app come back to a state 2 when the OS give me execution time, right?

In this case my app come back to a state 2 when the OS give me execution time, right?

That’s one possibility, yes.

There are two ways a background app refresh can pan out:

  • The user moves your app to the background and you stay in state 3 until the system decides to give you background app refresh time, at which point you move to state 2. This is a resume, not a relaunch, and so your app picks up where you left off.

  • The user moves your app to the background and you enter state 3. At some point in the future the system decides to terminate your app, moving you to state 4. Later on the system decides to give you background app refresh time, at which point you move to state 2. This is a relaunch, not a resume, and so your app goes through it startup sequence in the background.


If you haven’t already done so, I highly recommend watching WWDC 2020 Session 10063 Background execution demystified. It’s an excellent resource.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

BackgroundTask and Foreground app state
 
 
Q