I want my users to be able to track their heart-rate with my app. So I use CBCentralManager for that. Everything works fine if no other app is connected to the heart-rate sensor yet. The problem I have is if I start f.e. Strava or Endomondo first. Then I just can't find any devices any more. The other way round everything works fine, so I guess I am missing an options somewhere?
What I currently do:
I instantiate my CBCentralManager like so
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
which will cause the delegate method for connection to be triggered
func centralManagerDidUpdateState(_ central: CBCentralManager) {
let heartRateServiceUUID = CBUUID(string: "180D")
let services = [heartRateServiceUUID]
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: services, options: nil)
and from there on no peripheral are found.
But again, when I force quit other apps like Endomondo or Strava and then start my app, everything works fine.
See Best Practices For Interacting With A Remote Peripheral Device for full details on how to connect to devices you already know about.
The main issue you're encountering is that most BLE devices stop advertising once they have a connection. Since they aren't advertising, you can't see them in a scan. In this particular case, the BLE device is connected to the iPhone you're running on, but that doesn't change anything. It's still not advertising.
To deal with this, you want to ask the iPhone for connected devices that have the service you want, using
retrieveConnectedPeripherals(withServices:). This is a very fast, synchronous call, and you generally should do it before callingscanForPeripherals(withServices:options:).There are several other steps that you generally should do. The precise order and logic depends a little on your situation, but the linked flowchart above walks you through one approach. Basically it will look something like this:
Call
retrievePeripherals(withIdentifiers:)to find a peripheral you already know the identifier for. Note that this just tells you the system knows about the peripheral; it doesn't mean it's currently nearby. Callingconnecton it may never succeed.Call
retrieveConnectedPeripherals(withServices:)to find a peripheral that is already connected to this iPhone and advertises your service. You still need to callconnecton it for your process, but it should succeed.If all the rest fails, then call
scanForPeripherals(withServices:options:).