Enabling Background BLE Scanning on iPhone

A previous post shows how to create a simple BLE (Bluetooth Low Energy) scanner app for iPhone. The app can detect BLE devices while the app is in foreground. The goal of this post is to create an app that scans even it goes to the background.

Prerequisites (parentheses indicate my environment)

Xcode (10.0) ruining on Mac (10.14)

iPhone (iPhone 8 with iOS 12.0.1)* An actual iOS device is required since Bluetooth is not supported in Xcode simulator.

8. Then, Xcode will prompt an error. Click on “Fix” button and it will create centralManagerDidUpdateState() method which will be called when the central manager’s state is changed. At startup, this method is called after instantiating CBCentralManager.

9. Declare a variable for CBCentralManager in ViewController class.

1

privatevarcentralManager:CBCentralManager!

10. Instantiate CBCentralManager in viewDidLoad().

1

centralManager=CBCentralManager(delegate:self,queue:nil,options:nil)

11. In centralManagerDidUpdateState() method, start scanning when the state is poweredOn.

In above, didDiscover peripheral callback was called twice (Line 3-7 and Line 9-14). AD Data of the first result is same as the background scan result. The second result additionally has a device name in AD Data (Line 11).
According to an Apple Developer Forum post [4], the first result is from the initial Advertising packet and the second is from Scan Response packet. And the second packet is not guaranteed when the iOS app is running in background. That explains why the background scan result didn’t have the second packet.
So, when scanning in background, some data may not be available (e.g. in this case, the device name).

TakeawayBLE scan while app is in background (even when screen is locked) is possible. However, there are some limitations need to be consider when writing an app.