14

I'm trying to determine what devices are connected via bluetooth in iOS but can't seem to figure it out. Ideally I'd like to generate a list of connected bluetooth devices.

I've tried using "retrieveConnectedPeripheralsWithServices" but this requires a specific service to search for. I'd like to generate a list of all connected bluetooth devices, not just specific-service bluetooth devices. Is there a way to just search for all services without looping through all possible services?

Any ideas?

MGY
  • 7,245
  • 5
  • 41
  • 74
alan478
  • 183
  • 1
  • 1
  • 9
  • 1
    Bluetooth or Bluetooth Low-Energy? ExternalAccessory.framework (for classical Bluetooth MFi compliants) can give you the list of connected devices. – Larme Jun 04 '15 at 06:41
  • Sorry, should've mentioned it is BLE – alan478 Jun 05 '15 at 12:45

2 Answers2

6

The Solution for iOS:

(Thank you Larme)

NSArray *connectedAccessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories]; 

documentation :

https://developer.apple.com/library/prerelease/ios/documentation/ExternalAccessory/Reference/EAAccessoryManager_class/index.html#//apple_ref/occ/instp/EAAccessoryManager/connectedAccessories

Also if someone needs, this is documentation for Mac :

https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/Bluetooth/BT_Intro/BT_Intro.html

and code snippet for Mac

NSArray *devices = [IOBluetoothDevice pairedDevices];

For alan478's BLE question :

The Core Bluetooth framework provides the classes needed for your iOS and Mac apps to communicate with devices that are equipped with Bluetooth low energy wireless technology. You can take a look this tutorial :

http://www.raywenderlich.com/52080/introduction-core-bluetooth-building-heart-rate-monitor

and BLE code snippet is :

// In this case you need to tell UUID for serching specific device
CBUUID *hrate = [CBUUID UUIDWithString:@"180D"];

// Create a dictionary for passing down to the scan with service method
NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];

// Tell the central manager (cm) to scan for the heart rate service
[cm scanForPeripheralsWithServices:[NSArray arrayWithObject:hrate] options:scanOptions]

Please read this document on developer.apple.com :

https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/BestPracticesForInteractingWithARemotePeripheralDevice/BestPracticesForInteractingWithARemotePeripheralDevice.html

here is an interesting paragraph for you :

Explore a Peripheral’s Data Wisely A peripheral device may have many more services and characteristics than you may be interested in when you are developing an app to fulfill a specific use case. Discovering all of a peripheral’s services and associated characteristics can negatively affect battery life and your app’s performance. Therefore, you should look for and discover only the services and associated characteristics your app needs.

For example, imagine that you are connected to a peripheral device that has many services available, but your app needs access to only two of them. You can look for and discover these two services only, by passing in an array of their service UUIDs (represented by CBUUID objects) to the discoverServices: method of the CBPeripheral class, like this:

[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];

After you have discovered the two services you are interested in, you can similarly look for and discover only the characteristics of these services that you are interested in. Again, simply pass in an array of the UUIDs that identify the characteristics you want to discover (for each service) to the discoverCharacteristics:forService: method of the CBPeripheral class.

Also there is this comment :

"think Apple forbids this thing. We can only get list of Devices with specific CBUUID. so if you want to list all the devices(same as the Bluetooth settings does natively) then It is not possible. Please correct me if i am wrong. – Mrug Mar 11 at 13:24"

under this question :

How to get list of available Bluetooth devices?

Swift 5.3

EAAccessoryManager.shared().connectedAccessories
let devices = IOBluetoothDevice.pairedDevices()
// In this case you need to tell UUID for serching specific device
let hrate = CBUUID(string: "180D"),
// Create a dictionary for passing down to the scan with service method
let scanOptions = [CBCentralManagerScanOptionAllowDuplicatesKey : NSNumber(value: false)]
// Tell the central manager (cm) to scan for the heart rate service
cm.scanForPeripherals(withServices: [hrate] as? [CBUUID], options: scanOptions)
peripheral.discoverServices([firstServiceUUID, secondServiceUUID])
MGY
  • 7,245
  • 5
  • 41
  • 74
  • The question appears on iOS, no Mac OSX. – Larme Jun 04 '15 at 17:32
  • Thanks for your help gyer. I should've mentioned it is for BLE. Is there a similar way to do this for BLE? What I'm essentially trying to do is re-create the iOS Bluetooth menu (as found in Settings > Bluetooth) but only for connected devices. – alan478 Jun 05 '15 at 12:47
  • You're welcome alan478, I just add a code snippet for BLE and detailed tutorial link too, hope it's work for your case. – MGY Jun 05 '15 at 14:34
  • Is it fix your problem alan478? – MGY Jun 08 '15 at 11:07
  • 2
    Gyer, I appreciate all your help and guidance but am still struggling with this... This seems to be a good way to work with bluetooth within a specific app (searching, discovering, connecting, etc.) but is there any way to generate a list of devices that are **already** connected to the iOS device, i.e. find devices that were connected via Settings > Bluetooth? Devices that I'm interested in are likely already connected. Is there any way to interact with those system connected devices via our own apps? – alan478 Jun 10 '15 at 04:33
  • You're welcome alan478, I just updated my answer, can you check the document that I refer please. – MGY Jun 12 '15 at 13:39
  • on iOS and swift you can check notification Notification.Name.MPMusicPlayerControllerVolumeDidChange. In the moment when classic Bluetooth device done connection/pairing - the volume was changed rapidly. in the MPVolumeView object's subviews yo can find the UISlider which give you current sound volume. Nothing like device name etc. here - only connection/disconnection fact. – WINSergey Oct 30 '18 at 16:05
  • Does this answer still valid in 2021? – Keselme May 09 '21 at 16:09
  • Surely "1800" should read "180D" and this is a typo? – Sean Dev Oct 05 '21 at 12:04
  • Thank you Sean Dev, I've fixed the typo, for the heart rate it is "180D". – MGY Oct 07 '21 at 07:05
2

There are two cases which you need to consider:

  1. Peripheral may be already connected in the system (iOS connects automatically with some peripherals in order to for example display battery level). In this case peripheral won't be broadcasting and detection using scanForPeripherals won't work.

  2. Peripheral is paired, but disconnected. In this case retrieveConnectedPeripherals(withServices:) won't work.

Therefore to retrieve your peripheral you need to combine both things. First you need to check if it's in peripherals returned from retrieveConnectedPeripherals(withServices:). If not you should scanForPeripherals.

If you want to retrieve peripheral which is out of range, you can try to use retrievePeripherals(withIdentifiers:), however it may return also not paired devices and it relies on peripheral's UUID which you have to save after pairing.

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

Krishna Kirana
  • 438
  • 4
  • 10