Are you mystified about why and when your app gets background processing time? No need for a crystal ball! We'll show you how to tackle the seven major factors that impact background runtime, and how you can integrate background modes that help your app come back to the foreground faster, run more smoothly, and reduce battery drain.
Learn about the major factors affecting runtime for your app, the nuances of each opportunistic background mode, and how you can help your apps run more often and stay fresher by minimizing energy and data consumption.
For more information on background processing and execution, watch “Advances in App Background Execution” from WWDC19.
Hi. My name's Roberto, and I'm a software battery life engineer here at Apple, and I'm going to demystify background execution for you today.
You may have asked yourself this question: "My app adopted a background mode, but it's not running as much as I would like it to. Why?" At Apple, we understand that background execution allows apps to take their user experience to the next level, and we provide a wide variety of APIs that grant background execution for different use cases, each with different parameters. In this video, we will address some of these APIs and answer this most common question.
Today we'll start by talking about general factors affecting background runtime. Then we will dive into four specific APIs: background app refresh tasks, background pushes, URLSession background downloads and uploads, and background processing tasks. Now, before you proceed, if your app does not currently use these APIs, or you want to learn how to adopt them, then we recommend viewing existing sessions and documentation first.
A great start would be the "Advances in App Background Execution" session from WWDC 2019.
And before we dive into the general factors affecting runtime, let's highlight the goals we balance when determining what factors play a role in system scheduling of background execution.
On the right, we have your app's goals: having the latest content, being fresh when the user brings the app to the foreground, and being able to achieve both of these reliably.
And we balance these with the goals on the left.
First, there's battery life. We want to make sure that any background execution can occur while maintaining all-day battery life.
Next is performance. We set strategic limits to ensure that opportunistic background execution does not interfere with active usage.
Third is privacy. We want to make sure that users are not surprised by an app running in the background. That is, based on their particular usage patterns, they would reasonably expect that this app should get some background execution.
Finally, we have user intent. This is really important to us. If a user takes a certain action, we want to make sure the system responds to and tailors the experience to those unique actions. In balancing all these goals, we arrive at many different factors that affect background launches and runtime.
And here you can see some of these factors.
Today, we'll cover the top seven factors that are likely to affect you.
These are critically low battery, Low Power Mode, app usage, the App switcher, the Background App Refresh switch, system budgets, and rate-limiting. Let's start with critically low battery.
Sometimes people find themselves in critically low battery conditions where they may not have much battery charge left, but they still expect their phone can last long enough to get them to a place to charge.
An app running in the background may be invisible to the user, so it doesn't make sense to use power and risk the user not being able to reach that charging destination.
That's why in these situations, the system will attempt to pause discretionary and opportunistic work, which may not bring direct utility in real time, and instead focus on essential work that is directly user-requested.
Next, we have Low Power Mode.
Low Power Mode is different from critically low battery because it is a user-determined setting. The user has explicitly told the system that preserving battery is critically important to them, potentially even at levels higher than 20 percent.
Therefore, given it is such a strong and direct signal, the system will take this as a cue to limit certain activity.
As a developer, remember you can always check if a user is in Low Power Mode. And further, you can register for state change notifications.
These can both be a trigger to pause activity in your app. For example, maybe your app can turn off autoplaying videos in Low Power Mode to limit energy consumption due to networking and rendering.
Now, let's talk about other user-driven factors affecting background runtime.
One of these is app usage. There is a finite amount of resources on the system, and sometimes the system must prioritize running certain apps over others, as running everything at once would be detrimental to performance and battery life.
Therefore, whenever reasonable, the system will prioritize apps that are most important to the user.
Typically, these are simply the apps they use the most.
There is an on-device predictive engine that learns which apps people will use and when, and this information is used to prioritize background activity.
But it's not just the apps the user uses the most. We sometimes have indirect cues from the user on which apps they want to run.
For example, they may jump into the App Switcher and decide to swipe up to remove a few apps, perhaps to declutter or explicitly terminate an app.
For the modes we will discuss today, when the system determines which apps to run, it constrains to the set of apps that are still visible in the App Switcher.
Similarly, there are more direct cues on which apps to run, like specific user settings. There are settings for many different background modes: for example, Location and Bluetooth.
For discretionary and opportunistic background execution, we have the Background App Refresh switch. It may be obvious that this maps to Background App Refresh tasks, but it may not be as apparent that this setting applies to other modes too. In fact, it applies to every mode we will discuss today.
This switch defaults to "on." No special permission prompt required.
And just like Low Power Mode, you can query the state of the switch as well as listen for notifications when the state is changed.
Now, because this switch defaults to "on," the system needs a way to mitigate against all apps running all day and overwhelming a user's battery or data plan.
This is where system budgets come into play.
To ensure that opportunistic activities do not deplete batteries or data plans, we have an energy and data budget, and every time an app runs, it deducts from these budgets.
The budgets are slowly made available throughout the day so that updates can be distributed and apps remain fresh throughout.
As long as you limit the amount of energy and cellular data that you use per launch, this will prevent the system from limiting you.
Also, to help apps with budget management, the system performs some rate-limiting on your app's behalf.
This means the system reasonably spaces out launches just enough to maintain freshness while mitigating against frequent energy and data usage.
This is all done for you, so don't worry about implementing complex logic to do rate-limiting on your own. Just request what you need, and the system will space out launches depending on what's appropriate for each background mode.
So those are the top seven factors the system considers and that you should keep in mind when examining your app's background execution.
And now, here's my colleague Andy to explain how the seven factors apply to specific background modes.
Thanks, Roberto. I'm Andy from iOS System Experience. Let's see how the seven factors apply to each of the specific background modes.
First, let's start with Background App Refresh tasks.
Background App Refresh tasks are a way to ask the system to run your app periodically in the background so that your app can be fresh just before the user foregrounds it.
It's great for things like refreshing a social media feed, fetching emails, and retrieving the latest stock price. Let's take a look at how your Background App Refresh tasks might run over the course of the day.
On this timeline, I have plotted the background launches for App Refresh tasks.
You might expect that they would be evenly distributed over the course of the day.
But in reality, you may observe something like this. Why could this be? This is where the seven factors come into play.
Over time, the system learned usage patterns and understood that the user typically launches your app in the morning, around lunchtime, and in the evening. Therefore, the launches were scheduled just before typical launch times.
But wait. Maybe you also notice a large gap in launches.
Why could this be? This is where the other factors come into play.
Maybe the user was in Low Power Mode, as they realized they would be out until late in the evening and wanted to preserve battery life.
Or maybe the user forgot to charge their phone the previous night, and the battery was critically low.
Any of the seven factors could have played a role. There's one factor, though, where you have the most influence as a developer, and this is the system budgets.
As a developer, you can focus on efficient usage of these budgets to maximize the opportunities for your app to run.
So, first, minimize power consumption.
Avoid bringing up unnecessary hardware like the GPS or accelerometer unless you absolutely need to.
Along those lines, try to finish your work as quickly as possible.
This can mean parallelizing network activity and limiting computation to the bare minimum.
And don't let these optimizations go to waste. Tell the system when you are done. This allows the system to immediately suspend your app and enter a lower power state.
For Background App Refresh tasks, this means calling setTaskCompleted. For other APIs, it means calling a completion handler.
The other budget to optimize for is the cellular data budget.
Try to limit your downloads to what's necessary for a fresh UI.
For example, download thumbnails instead of full-size images.
And enqueue the rest of your downloads as a URLSession discretionary background transfer for completion at a better time.
Try to keep your cellular data usage under a hundred kilobytes each time your app refreshes.
This is a good target to use for Background App Refresh tasks as well as for background pushes.
Now let's talk about background pushes.
Background pushes are pushes that wake up your app without a visible notification to the user.
They are great for when you have new content, but it's not immediately important to the user.
For example, a message to a muted conversation or an email to an unimportant in-box or even as a trigger to initiate a discretionary download for a new episode of a TV show.
The seven factors come into play for background pushes as well except for one: app usage. The system does not gate background pushes based on app usage.
One common question we hear is, "How does rate-limiting apply to background pushes?" Let's take a look at that. Here's the timeline again, and let's hone in on an early part of the day.
Say in a given window, you send 14 pushes with a few denser clusters.
You may expect a launch upon every push.
But running this frequently could cause significant battery-life issues, and on top of that, it could lead to exhausting the energy and data budgets early in the day.
Just imagine if that one chatty Messages conversation you muted caused your app to run every time you received a message.
Instead of running upon every push, the system does this.
The system delays the delivery of some pushes to limit the amount of execution while maintaining a frequent launch cadence.
So the 14 pushes we had result in seven launches.
And while you might be thinking, "Oh, no. Only half our pushes are being delivered." Well, the time interval between runs was just 15 minutes, meaning we had many times per hour, and the app will be up-to-date before the user launches it.
So focus on the launch interval when evaluating your background push deliveries instead of the delivery rate.
Now that we've talked about background push, let's talk about Background URLSessions.
Background URLSessions are downloads and uploads that are off-loaded from your app to the system.
This is great because it allows transfers to continue after the app exits, meaning they are unconstrained by runtime limits.
Background URLSessions are perfect for things like file downloads, photo uploads, and full-size social media content kicked off as a result of a background push.
There are many different parameters you can configure for your download. One important one is you can prevent the transfer from going over cellular and other expensive links.
Another important parameter is sessionSendsLaunchEvents. Setting this to "Yes" requests that the system launch your app after the background transfer is complete.
There are two main types of background URLSessions: discretionary and nondiscretionary. You signal this by setting the isDiscretionary property.
Discretionary background transfers are transfers you are okay with deferring. The system will perform discretionary transfers when conditions are optimal, perhaps when the phone is plugged in and on Wi-Fi.
Nondiscretionary transfers are transfers you want to occur as soon as possible, perhaps because the user hit a download button in your app.
If you enqueue a transfer while the app is in the background, the system will ignore the isDiscretionary property and treat it as true. From the foreground, you can optionally request discretionary.
For discretionary transfers, most of the seven factors apply, but there aren't app usage requirements, nor does the system impose rate limits on the transfers you enqueue.
If you requested sessionSendsLaunchEvents, it will attempt to launch you if conditions permit. Distinct from the transfers, we have some basic rate-limiting for the launches. If the app was brought foreground recently, rate-limiting won't apply.
For nondiscretionary transfers that you've enqueued in the foreground, the transfer continues after you dismiss the app.
For these, only two of the seven factors apply.
Users can stop transfers by swiping to kill the app in the App Switcher.
And there are indeed some system budgets, but they are greatly relaxed and unlikely to get in your way.
And again, if you requested sessionSendsLaunchEvents, the launches will follow five of the seven factors.
Since these sessions were enqueued while the app was foreground, rate-limiting due to app usage won't happen.
Last, there is one more specific run mode we want to cover: background processing tasks.
Background processing tasks give your app several minutes' worth of runtime at system-friendly times to do maintenance work, like indexing a database. You can also do intensive work like on-device Core ML training.
Given these are long-running tasks, the system will wait to run you until the user is not actively using the device, such as when it's charging at night.
So how do the seven factors apply to background processing tasks? Since you're going to be running while plugged in, you won't have to worry about critically low battery, Low Power Mode, or the system energy budget.
With regard to app usage, the user doesn't need to use your app every day for your processing tasks to run. As long as they've brought the app foreground in the past couple of weeks, you should be fine. The App Switcher and Background App Refresh switches are still gating factors, so as to prevent the app from running unexpectedly, against user intent.
And with regard to rate limits, as long as the user plugs in every day, your background processing tasks should be able to run daily.
Now that you've learned the seven factors and how they apply to specific background modes, think about how they apply to your app. Remember, you can check the state of user switches, such as Low Power Mode and Background App Refresh, in order to respond gracefully to user intent.
And now that you understand the differences between these modes, reevaluate whether you are choosing the right mode for a specific job. This could even mean using multiple modes.
Finally, the power is in your hands. If you reduce energy and data usage, then you can maximize your app's freshness, maintain great battery life, preserve data plans, and overall deliver a mystically delightful experience. Thanks for watching.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.