Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Apps in the Background

Apps in the Background

When building an app, a lot of focus and effort is put on crafting the best foreground experience for users. However, our apps also have a hidden life when we move them the background. And the system watchdog is here to make sure they all behave! In this talk, you will learn what the common pitfalls of background execution are, how you can make sure you don’t exceed system resources by applying best practices, and finally, how to optimize network requests when your app is not in the foreground.

Alexis Aubry

April 29, 2019
Tweet

Other Decks in Programming

Transcript

  1. Apps in the Background The secret life of apps when

    you minimize them. Alexis Aubry — App Builders 2019 @_alexaubry
  2. Our Plan How do we provide the best experience to

    our users even when they don’t interact with the app? 1. What does it mean to be in the background? 2. What are the common problems and how to detect them? 3. How can we fix these issues and improve the UX?
  3. Common Exception Codes • 0x8badf00d = took too long to

    respond to a system event • 0xdead10cc = forgot to release a file lock after suspension • 0xc51bad01 = CPU usage too high in the background • 0xc51bad02 = took too long to move to the background • 0xc51bad03 = system resources too low to continue • 0xbada5e47 = exceeded the limit of background tasks
  4. Other Symptoms • Missing data or expected event not happening

    • Example: taking too long to process a push payload. • Routinely check your crash reports for the aforementioned codes.
  5. Other Symptoms • Unexpectedly high battery usage • If you

    take a lot of time to process events, but stay under the limit, the system will probably not terminate your app. • Example: you can spend 20 seconds for each push notification, under the limit, but will have an impact on user’s battery. • At Wire: reduced background activity by 5 hours a week.
  6. For App Extensions ProcessInfo.processInfo.performExpiringActivity(withReason: "Request") { [weak self] expiring in

    guard let self = self else { return } if expiring { // Clean up your code before suspension self.currentRequest?.cancel() } else { // Otherwise perform the task let request = self.networkingLayer.createRequest() self.currentRequest = request request.resume() } }
  7. When to Use It • Every time interrupting the work

    would be detrimental to the UX • Example: when sending a message or saving a file. • When operating in the foreground • Example: asking for extra time to send a message before going in the background, so you don’t need to care about the state of the app. • Caveat: having too many active background tasks can cause a crash
  8. How to Optimize It • Give names to tasks when

    creating them. • Create all your tasks from a single thread. • Centralize the tasks creation inside one object.
  9. Benefits of a Task Manager • Manages a single background

    task to keep the app awake. • Avoids repeated overhead of creating background tasks. • Avoids issues with gaps between tasks. • Avoids issues with needing to create tasks from multiple threads.
  10. Building a Task Manager BackgroundTasksManager Save the token of the

    custom task When we have an Internal Background Task UIKit
  11. Building a Task Manager When there are no more active

    tasks BackgroundTasksManager End the internal task Your Code
  12. Building a Task Manager BackgroundTasksManager Expire all active tasks When

    the extended lifetime expires UIKit expiration callback
  13. Building a Task Manager BackgroundTasksManager Expire immediately When creating tasks

    while the app is expiring UIKit cannot start a real task
  14. Reducing Memory Usage • Makes the system more likely to

    keep your app suspended for a longer period of time. • Example: Use a purgeable cache with a disk counterpart. • Example: Reduce your use of images. • Recommended Reads • https://developer.apple.com/library/archive/technotes/tn2434/_index.html • http://www.thomashanning.com/building-memory-efficient-apps/
  15. Using the Right API • Processing notifications in the background?

    • Use a notification service extension. • Downloading files in the background? • Use a background URLSession with sessionSendsLaunchEvents. • https://developer.apple.com/documentation/foundation/ url_loading_system/downloading_files_in_the_background
  16. Architecture Tips • Don’t wait for the user to close

    the app to save data. • Make every task cancellable, so that you can stop them during expiration. • Design background behavior with UX in mind. • Example: if we cancel sending a message, how do we communicate that to the user?
  17. What should happen if we cancel a running task? Is

    it recoverable? Does it need user interaction to recover?
  18. Wrapping Up • Different scenarios, different rules. • Comply to

    stay frozen in the background as long as possible. • Look for the signs to detect potential bottlenecks. • Use background tasks as often and efficiently as possible. • Use the latest APIs and tools to optimize background work. • Design for immediately cancellable tasks, think about the UX.