Swift – Bluetooth Low Energy – how to get paired devices?

Posted on Posted in iOS

This question is asked probably by many programmers who start working with BLE on iOS. Unfortunately, it’s not possible to retrieve a list of paired peripherals from iOS. Neither it’s possible to check if a specific peripheral is paired. However, there are some ways to deal with it.

If you think about it from application’s perspective, it’s not important if you are paired or not, it’s important if you can do things permitted only for paired devices such as reading from protected characteristics.

Retrieving peripheral

There are two cases which we need to consider:

  • Peripheral may be already connected in the system – iOS connects automatically with some paired peripherals in order to display battery level. In this case peripheral won’t be broadcasting and detection using scanForPeripherals(withServices:) won’t work.
  • Peripheral is paired, but disconnected. In this case retrieveConnectedPeripherals(withServices:) won’t work.

Therefore to retrieve your peripheral you need to combine multiple things:

  1. If you have peripheral UUID (identifier) you should try retrievePeripherals(withIdentifiers:).
  2. If not, you should retrieveConnectedPeripherals(withServices:).
  3. If not, you should scanForPeripherals(withServices:).

Here is a good example (source):

Peripheral Reconnection
Peripheral Reconnection

Detecting if peripheral is paired

There is only one way to detect if the specific peripheral is paired. You need to try to read from protected characteristic (which requires encryption – pairing). If you receive expected data, it means that the user accepted pairing request. Otherwise you will receive empty response or none.

However, this is not a good way to test all devices returned from scanning. First of all, you don’t know which characteristic may be protected for unknown peripheral, another thing is that accessing it from unpaired peripheral will display iOS pairing alert to user, which would be annoying and strange behaviour.

In most cases if not all, you don’t have to display to user their paired devices, you can just show detected peripherals. Paired devices from your application you can list based on saved information using methods from “Retrieving peripheral” section.

Unpairing peripheral from iOS

Unfortunately, it’s not possible to remove programatically paired peripheral from iOS Bluetooth settings. User must do it manually. Therefore if you have unpairing in your application, this functionality should remove association between the application and the peripheral, stop further synchronization and inform user about additional steps required to unpair it from the system.

You should also make sure that associating application again with the peripheral that is paired in iOS works as expected. In this case it may be required to implement some feature in firmware for BLE device to handle situation in which user turns on pairing mode, but smartphone is already paired with this device.

Difference between pairing and bonding

In this article I’m using “pairing” to make it simple, however I think that “bonding” would be more accurate in many cases. To avoid confussion the same does Apple – in iOS you won’t see “bonding”.

Pairing is a procedure in which BLE devices exchange encryption keys to secure transmission and to prevent man-in-the-middle attack. However, those keys are not remembered at this point and next time it won’t be possible to communicate using the same keys.

Bonding is just an extra feature which allows to ask BLE devices to remember exchanged keys and use them next time without pairing again. Currently iOS doesn’t allow to just pair without bonding. The alert asking if you want to pair with BLE device actually performs both things under the hood.