I am currently working on an iOS application based on bluetooth low energy devices. In order to get a unique identifier to compare the peripherals got, I have to get the MAC address of the peripherals.
It is observed that the UUID property of a peripheral device varies across iOS devices and also for the peripheral device to get a UUID, it will have to get connected to a master device at least once. Since I have to deal with check-in's I don't want to establish a connection. As I went through the bluetooth services portal, I found that the device information itself is a service, which couldn't be retrieved unless a connection has been established between the master iOS device and the peripheral bluetooth low energy device.
I found that in Android we get the entire information of the device, including its MAC address (using getAddress()) when we get the response from the device on scanning itself.
I didn't find any properties in CBPeripheral class related to the device address. Another way to get a unique parameter would be to customize the advertisement data to send additional information regarding the device, which requires more work on firmware side.
So is there any way in iOS that I could get the MAC address of the bluetooth low energy peripheral without establishing a connection?
Any help would be greatly appreciated.
Bluetooth Smart is also referred to as BLE or Bluetooth Low Energy. Both Bluetooth low energy android and iOS devices are intended for the intermittent advertisement of the position or its presence. The advertisement packet holds the broadcaster's MAC address and unique service formation.
There are two types of Bluetooth in Apple devices, Bluetooth Classic and Bluetooth Low Energy (BLE).
While iOS devices advertise Bluetooth continuity messages it's not possible to track iOS devices using their Bluetooth MAC address because the address changes over time in order to defeat such tracking. However, as previously mentioned, Bluetooth MAC randomisation can be defeated.
CBPeripheral's identifier property will serve your purpose, available from a still-unconnected device in CBCentralManager's didDiscoverPeripheral delegate method:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI CBPeripheral *peripheral ... NSUUID* serverId = [peripheral identifier];
I have a half dozen LE devices I'm experimenting with, including multiple sets of identical devices. I just confirmed that across two iOS devices, the identifiers for all of these LE widgets were different, but for EACH iOS device, the identifier for each widget was retained across application launches and even across app deletes and reinstalls. I would say this definitively proves that the OS is storing enough info internally that for a given iThing, you'll be able to distinguish between, and re-identify, all the peripherals your app encounters, without actually connecting to them. Also note that the advertisementData
, also available before connecting, is full of useful info like CBAdvertisementDataLocalNameKey
, CBAdvertisementDataManufacturerDataKey
, CBAdvertisementDataServiceUUIDsKey
, CBAdvertisementDataSolicitedServiceUUIDsKey
, and others, although none as certain to uniquely identify the device as [peripheral identifier] is.
I didn't try doing a device backup and restore to prove the UUIDs were retained, but I'd wager they are, and if they're not, it's something Apple would consider a bug.
After iOS 12 we can get UDID
print(UIDevice.current.identifierForVendor) print(UIDevice.current.identifierForVendor?.uuidString)
There is no public API to get this information.
If this is an internal or jailbreak application you can get the value of the kLockdownBluetoothAddressKey key via liblockdown.dylib
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With