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.
  • A BLE peripheral device to be scanned (Galaxy S7 running BLE Peripheral Simulator app [1])


1. Launch Xcode and create a Single View App.

2. Select Info.plist in Project navigator.

3. Click on “+” button next to “Information Property List” and select “Required Background Modes”.

4. Expand “Required Background Modes” by clicking on the triangle icon.

5. Add “App communicates using CoreBluetooth” as the value.

6. Open ViewController.swift file and import CoreBluetooth framework.

7. Add CBCentralManagerDelegate protocol to ViewController class.

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.

10. Instantiate CBCentralManager in viewDidLoad().

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

In order to scan in background, service UUIDs need to be specified [2]. In this post, the app will scan for Battery Service [3] for testing purpose (Line 3).

8. Define centralManager didDiscover method. It will be called when any advertising device is discovered. Inside the method, it prints the device name, RSSI, and advertising data.

9. Open AppDelegate.swift file and add print statements in applicationDidEnterBackground method and applicationWillEnterForeground method to output the app state transitions.


1. Background Scan
1-1. Make sure below conditions before start.

  • The peripheral device is not advertising yet.
  • Bluetooth is ON on the iPhone.

1-2. Connect iPhone to Mac.

1-3. Build and run the program.

1-4. Lock the iPhone screen by pressing the side button.

1-5. Start advertising on the peripheral device. In case of BLE Peripheral Simulator, launch the app and tap on “Battery”.

Below is the example of the result of background scan.

Notice that the Bluetooth device name is not detected. Let’s scan in foreground and compare the results.


2. Foreground Scan
2-1. Stop advertising on the peripheral device by tapping Back button.

2-2. Cancel screen lock on iPhone.

2-3. Restart advertising on the peripheral device.

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).


BLE 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.

  • Service UUIDs need to be specified when starting BLE scan.
  • Some data may not be received. (i.e. Data in Scan Response)
  • Other limitations are describe in Apple’s official document [5].


[1] BLE Peripheral Simulator – Google Play Store
[2] scanForPeripherals(with Services: options:) – Apple Developer
[3] GATT Specifications Battery Service – Bluetooth SIG
[4] Apple Developer Forums – Apple Developer
[5] Core Bluetooth Background Execution Modes – Apple Developer




Sponsor Link

Leave a Reply

Your email address will not be published. Required fields are marked *