Update (October 22, 2013): Radius Networks has taken this question further, and answers with a resounding “NO”, iOS will NOT let you find beacons that aren’t your own. Their conclusion?
- There doesn’t seem to be any hack to look for an arbitrary iBeacon on iOS — you have to know at least the ProximityUUID to see one.
- Using CoreBluetooth is pretty useless for working with iBeacons. You can see their advertisements, and measure the signal strength, but you can’t see any of the identifiers, and thus, you don’t even know for sure if any advertisement you see is an iBeacon at all, versus any other BluetoothLE device.
Their post however validates that you CAN “see” a beacon that isn’t your own, but the only thing you can see is a randomly generated UUID (not the same as the unique ID) and you can see the beacon’s signal strength. It might not even be a beacon – just a Bluetooth device of some kind. So the data is nearly worthless. Android, however, can SEE the unique non-changing identifier and its major and minor fields. (It’s not clear to me whether this is absolutely true in all cases – Bluetooth LE has three models for discovery and I’m not sure if it works for all three).
So what seems fairly clear that while Google lets you scan for devices that aren’t your own, iOS has obscured or locked off the ability to do so.
Update: After some back and forth with Joris Kluviers (mentioned in my original post) on Twitter – it’s starting to look like iOS apps can NOT scan for devices for which you don’t know the UDID. Kluviers notes, as I did in this post, that the iBeacon API doesn’t allow you to find beacons that aren’t your own. But the proposal that you could use CoreBluetooth instead elicited the following response:
@Dusanwriter that’s not possible on iOS it seems. The framework doesn’t give access to the BLE advertisement data which contains the UUID
— Joris Kluivers (@kluivers) October 21, 2013
@Dusanwriter yes, there is a key defined for that in CoreBluetooth. But it doesn’t seem to work
— Joris Kluivers (@kluivers) October 21, 2013
So the original idea, that you could bypass the iBeacon API and use a key in CoreBluetooth looks like it isn’t supported by Apple. As Kluivers notes: the key is there but it doesn’t work.
If you’ve tried any of this and have any light you can shed, please drop it in the comments below, or e-mail me at doug (at) mylocolo.com.
Here was the original post which proposed you could hack your way to a work-around to discover beacons that aren’t your own:
Your iOS app can find iBeacons, even if they aren’t your own. But the process is a bit more complicated than expecting startMonitoringForRegion to work out of the box.
I went into this in-depth yesterday – trying to parse why Radius Networks was claiming that Android devices could ‘find’ all beacons while iOS can’t. I thought I’d strip it down to a simple version of what I found. Maybe this will be useful to others with the same question.
Quite simply, the challenge is that Apple requires a not nil value to initialize and return a region object via initWithProximityUUID. In other words, the iBeacon API requires that you know the UUID of the beacon device in order for your iOS device to find it. What’s unclear is whether Apple’s not nil rule is, well, a rule or a recommendation (if you can help with the answer, drop it in the comments below).
Use a wildcard for UUID:
A comment on Stack Exchange proposes a simple work-around: inserting a wildcard character in place of an actual UDID. In theory, this will return a result showing all beacons in a region. BUT, note the comment above: it seems like there might be the possibility that Apple would reject your app because you’re basically hacking around their recommended approach.
OR, Use CoreBlueTooth Instead
Joris Kluivers notes that proximity detection is perfectly possible without using the iBeacon API. Just use CoreBlueTooth for Bluetooth LE detection instead. (Click through his post to see a video demo of how he achieved this even before iBeacon was available).
You might also want to check out the sample code at Apple for the Heart Rate Monitor app to see how it scans for peripherals. The relevant line is:
[manager scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:@”180D”]] options:nil];
Finding is NOT the Same as Pairing
But finding someone else’s beacon isn’t the same as pairing with it. In order to pair, you DO need the UUID if the device requires authentication in order to pair. That’s because a beacon sends out two ‘streams’ – an ‘advertising packet’ that lets the world know it’s there, and the data channels that get opened up when your iOS device ‘pairs’.
The advertising packet is open. You can discover that there’s a beacon, find out its RSSI strength, and make a rough approximation of how far you are from the beacon based on this data.
But it’s only when you pair with the device that you get the information that’s in the data channel: accuracy, ranging and other information that let you calculate proximity more precisely and take full advantage of the other methods in the iBeacon class.
You also probably don’t want to rely on the information you get without pairing.
According to Apple:
“Pairing may require user authorization depending on Apple product. Once an accessory is paired with an Apple product, it shall retain the distributed keys of both central and peripheral for future use. If the pairing is no longer required, the accessory shall delete both sets of keys.”
So yes, you can discover Bluetooth LE devices with your app. But the real value comes when you pair, which requires authentication, at least when it comes to most of the commercially available iBeacon devices.