Scan for BLE peripheral in background - iOS

Viewed 1051

I am looking for a solution to scan for BLE peripherals while the app is in background state through an iOS device. I have tried checking the capabilities, adding central and peripheral in info.plist for background process, creating a singleton CBCentralManager. It scans and connects to the BLE devices while in foreground but once it goes to background, it never calls the didDiscover method. Is there any solution fo the same? Thanks in advance.

My info.plist

<array>
    <string>bluetooth-central</string>
    <string>bluetooth-peripheral</string>
    <string>fetch</string>
    <string>location</string>
    <string>processing</string>
    <string>remote-notification</string>
</array>

My capabilities enter image description here

I have also called the scanPeripheral with a service as you have mentioned.

centralManager.scanForPeripherals(withServices: [CBUUID(string: "6T5FFJJIL-B5A3-D839-LDKL-KJBLKJ33")])

I also tried using allow duplicates true/false for the options for scanPeripherals and also retrievePeripherals delegates too.

2 Answers

You are almost certainly passing nil as the forServices parameter of scanForPeripherals. This is not allowed in the background.

Your app can scan for Bluetooth devices in the background by specifying the bluetooth-central background mode. To do this, your app must explicitly scan for one or more services by specifying them in the serviceUUIDs parameter. The CBCentralManager scan option has no effect while scanning in the background.

You also will not receive duplicates while in the background, even if you request them with CBCentralManagerScanOptionAllowDuplicatesKey.

You will need to determine the list of service UUIDs you want to scan for, and pass those to scanForPeripherals.

I was able to get background connection working by doing the following:

  1. In the didDisconnectPeripheral, I called a function startScanning. Inside startScanning is where I have myCentral.scanForPeripherals(withServices: [SERVICE_UUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])

  2. Nothing was working until I added the following above scanForPeripherals:

     if let savedPeripheral = self.myPeripheral {
         if savedPeripheral.state == .disconnected {
             self.myCentral.connect(savedPeripheral)
         }
     }
    

Now all seems to be working as it should.

Related