What happens by default
An iOS app with no Bluetooth background mode is suspended shortly after it leaves the screen, like most iOS apps. Apple’s Core Bluetooth background guide spells out what that means for Bluetooth:
- As a central, the app cannot scan for or discover advertising peripherals while it is in the background or suspended.
- As a peripheral, its advertising is disabled, and a central that tries to read a dynamic characteristic value from one of its published services gets an error.
- Bluetooth events that happen while it is suspended are queued and delivered only when it returns to the foreground. If a connection drops in the meantime, the app does not find out until then.
There is a middle ground for apps that only need to know when something important happens. When a central connects to a peripheral, it can pass options such as CBConnectPeripheralOptionNotifyOnDisconnectionKey, and the system shows the user an alert for that event while the app is suspended. The user decides whether to bring the app back.
The two Bluetooth background modes
To do real Bluetooth work off screen, an app declares a Core Bluetooth background execution mode by adding the UIBackgroundModes key to its Info.plist with one or both of these values:
bluetooth-central, for apps that communicate with Bluetooth LE peripherals.bluetooth-peripheral, for apps that share data as a peripheral.
An app that plays both roles, as phone-to-phone apps usually do, may declare both. The system then wakes the app from suspension to handle Bluetooth events. For a central that includes connections being made or torn down, new characteristic values from a peripheral, and changes in the central manager’s state. For a peripheral it includes read, write and subscription requests from connected centrals.
What changes for a central in the background
A backgrounded central can still discover and connect to peripherals and work with their data, but scanning behaves differently:
- It must name what it is looking for. Apple’s
scanForPeripherals(withServices:options:)reference says a background scan has to list one or more service UUIDs. An open scan for every nearby device is a foreground-only option. - Duplicates are merged. The
CBCentralManagerScanOptionAllowDuplicatesKeyoption is ignored, so repeated advertisements from one peripheral arrive as a single discovery. - Scans run less often. If every app that is scanning is in the background, the interval between scans grows, and Apple warns that discovering a peripheral may take longer.
What changes for a peripheral in the background
With bluetooth-peripheral, the app can keep advertising, but in a reduced form:
- The local name is not advertised.
- Every service UUID moves into a special “overflow” area. Apple’s documentation says these UUIDs can be discovered only by an iOS device that is explicitly scanning for them.
- If every app that is advertising is in the background, the device may send advertising packets less often.
Even in the foreground, space is tight. The startAdvertising(_:) reference gives an app up to 28 bytes in the initial advertisement for the local name and service UUIDs, plus 10 bytes in the scan response usable only for the local name, not counting 2 bytes of header per data type. Service UUIDs that do not fit go to the overflow area too.
The overflow area is the main reason a scanner on another platform can miss an iPhone whose app is in the background. How do iPhone and Android phones message each other over Bluetooth? covers what that means for a mixed pair, and How do two phones find each other over Bluetooth? covers discovery in general.
When the system terminates the app
A background mode does not let an app run forever. The system may terminate it to free memory for the foreground app, and any active or pending connections are lost with it. Since iOS 7, Core Bluetooth has offered state preservation and restoration for this case.
An app opts in by giving each central or peripheral manager a unique restoration identifier when it creates it, using CBCentralManagerOptionRestoreIdentifierKey or CBPeripheralManagerOptionRestoreIdentifierKey. The system then keeps working on the app’s behalf after termination. For a central manager it tracks the services it was scanning for, the peripherals it was connected or connecting to, and the characteristics it was subscribed to. For a peripheral manager it tracks the data it was advertising, the services it published, and the centrals subscribed to its characteristics.
When one of those tasks completes, for example a peripheral it was scanning for is found, the system relaunches the app into the background. The app recreates its managers with the same identifiers, and centralManager:willRestoreState: or peripheralManager:willRestoreState: tells it what the system was doing while it was gone.
As an example, Offline Protocol’s React Native installation guide asks apps to declare both modes, because the mesh SDK creates its central manager with a state-restoration identifier, which Core Bluetooth honours only when bluetooth-central is declared.
Rules for running in the background
Apple asks apps that declare these modes to behave responsibly, because radio use costs battery:
- Be session based, and give the user a way to start and stop Bluetooth activity.
- Finish quickly when woken. Apple says an app has around 10 seconds to complete a task, and that apps which spend too long in the background can be throttled or killed.
- Do not use a Bluetooth wake to do unrelated work.
In practice, test every combination of foreground and background on real phones, and make it clear to users when discovery needs the app to be open.