Slide 1

Slide 1 text

Apps in the Background The secret life of apps when you minimize them. Alexis Aubry — App Builders 2019 @_alexaubry

Slide 2

Slide 2 text

Delivering a good UX means More than a foreground experience

Slide 3

Slide 3 text

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?

Slide 4

Slide 4 text

What does it mean to be in the background?

Slide 5

Slide 5 text

Possible States Minimized App Push Notification Background Refresh

Slide 6

Slide 6 text

Moving to the Background applicationWillResignActive(_:) UI Snapshot Suspended applicationDidEnterBackground(_:)

Slide 7

Slide 7 text

Handling Background Events UI Snapshot Process the events applicationDidEnterBackground(_:) Launch if needed Suspended

Slide 8

Slide 8 text

How to identify issues?

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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.

Slide 11

Slide 11 text

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.

Slide 12

Slide 12 text

What are the techniques for the best background experience?

Slide 13

Slide 13 text

Use background tasks 1

Slide 14

Slide 14 text

✅ Get more time to complete your background work

Slide 15

Slide 15 text

How it Works UIApplication Your Code

Slide 16

Slide 16 text

Starting a Task beginBackgroundTask Your Code Expiration Handler

Slide 17

Slide 17 text

Starting a Task beginBackgroundTask Your Code Expiration Handler

Slide 18

Slide 18 text

Starting a Task beginBackgroundTask Your Code Expiration Handler Task Identifier

Slide 19

Slide 19 text

Check for Expiration beginBackgroundTask Your Code Expiration Handler .invalid

Slide 20

Slide 20 text

Performing your work UIApplication Task Identifier Expiration Handler Async Queue Your Background Work

Slide 21

Slide 21 text

Finishing your work endBackgroundTask Your Code Expiration Handler Task Identifier

Slide 22

Slide 22 text

Expiring Properly endBackgroundTask Your Code Expiration Handler Task Identifier

Slide 23

Slide 23 text

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() } }

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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.

Slide 26

Slide 26 text

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.

Slide 27

Slide 27 text

Building a Task Manager BackgroundTasksManager UIKit Your Code

Slide 28

Slide 28 text

Building a Task Manager beginBackgroundTask UIKit Your Code

Slide 29

Slide 29 text

Building a Task Manager BackgroundTasksManager Begin task with UIKit Your Code No Internal Background Task

Slide 30

Slide 30 text

Building a Task Manager BackgroundTasksManager Save the token of the custom task When we have an Internal Background Task UIKit

Slide 31

Slide 31 text

Building a Task Manager endBackgroundTask UIKit Your Code After ending your work

Slide 32

Slide 32 text

Building a Task Manager When there are no more active tasks BackgroundTasksManager End the internal task Your Code

Slide 33

Slide 33 text

Building a Task Manager BackgroundTasksManager Expire all active tasks When the extended lifetime expires UIKit expiration callback

Slide 34

Slide 34 text

Building a Task Manager BackgroundTasksManager End the internal task Your Code When the extended lifetime expires

Slide 35

Slide 35 text

Building a Task Manager BackgroundTasksManager Expire immediately When creating tasks while the app is expiring UIKit cannot start a real task

Slide 36

Slide 36 text

Implementation on GitHub github.com/alexaubry/background-tasks-manager

Slide 37

Slide 37 text

Keep your memory usage under control 2

Slide 38

Slide 38 text

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/

Slide 39

Slide 39 text

Use the right API for the right task 3

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Design for immediately cancellable tasks and restoration 4

Slide 42

Slide 42 text

“Apps must be prepared for
 termination to happen at any time.”

Slide 43

Slide 43 text

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?

Slide 44

Slide 44 text

What should happen if we cancel a running task? Is it recoverable? Does it need user interaction to recover?

Slide 45

Slide 45 text

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.

Slide 46

Slide 46 text

Thank you! Questions? Tweet me @_alexaubry