9

When an iOS BLE peripheral enters the background state, the advertising packets are not emitted in the regular manner and they are placed in a special “overflow” area which is only detectable by another iOS device explicitly looking for this device.

The bluetooth-peripheral Background Execution Mode

That said, you should be aware that advertising while your app is in the background operates differently than when your app is in the foreground. In particular, when your app is advertising while in the background:

• The CBAdvertisementDataLocalNameKey advertisement key is ignored, and the local name of peripheral is not advertised.

• All service UUIDs contained in the value of the CBAdvertisementDataServiceUUIDsKey advertisement key are placed in a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them.

Is there any way an Android central (scanner) can detect any advertised custom UUID without having to connect to the iOS peripheral?

Community
  • 1
  • 1
Ahimsa Das
  • 111
  • 7
  • Were you able to find a way for Android devices to be able to detect iOS devices when the iOS app is in the background ? – Rahul Iyer Apr 08 '20 at 06:05
  • Specifically - if an iOS app is acting as a peripheral, and is in the background, and an Android app has never connected to it before, can an Android app detect the iOS peripheral based on a service UUID ? – Rahul Iyer Apr 08 '20 at 06:17
  • 1
    @KaizerSozay nope. The only work around could be to... **queue every other iOS device -> connect -> look for your serviceUUID -> if present, then do your thing -> disconnect**. Yes, this is slow and not asynchronous as opposed to just reading the advertisement packets without connecting, but it's the only work around I know as of now. – Ahimsa Das Apr 08 '20 at 06:56
  • Sorry - I don’t fully understand: are you saying an Android device can not detect an iOS device whose app is in the background? – Rahul Iyer Apr 08 '20 at 06:59
  • 1
    An Android central (scanner) will be able to detect an iOS peripheral (advertiser) that's in the background state, but will not be able to read any custom serviceUUID without connecting to it. You can tell that it's an Apple device by [reading the manufacturer ID](https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/) - look for Apple. – Ahimsa Das Apr 08 '20 at 07:17
  • Thanks - do you have any link / sample code for this? It seems like an android device will have to scan for all peripherals and then filter based on the manufacturer id, and then try and connect....and then check for service & characteristic ids - meaning it may detect iOS devices which do not have the app installed, and only after connecting be able to determine if it has the service you are looking for... – Rahul Iyer Apr 08 '20 at 07:20
  • 1
    Yes that's correct! You can try using this [Blessed Library](https://github.com/weliem/blessed-android) - but you'd have to write the queuing and connection logic by yourself based on your requirements / conditions. – Ahimsa Das Apr 08 '20 at 07:26
  • If you have a simple example of code for android, where the only thing it does is scan for and connect to an iOS device (where the iOS app is in the background, and the Android app is in the background), can you share it please? – Rahul Iyer Apr 09 '20 at 08:02
  • 1
    You can't write a generic code which will work for every case. You'd have to define your own UUIDs, scanning / advertising conditions & settings. Please go through the Android & iOS BLE docs, you can easily implement it once you've clearly defined your use case and requirements. Also, Apple & Google have [teamed up](https://www.theverge.com/2020/4/10/21216484/google-apple-coronavirus-contract-tracing-bluetooth-location-tracking-data-app) in efforts to use BLE for contact tracing the COVID-19 pandemic. We *may* see some changes in the core BLE stacks for better cross platform inter-operability. – Ahimsa Das Apr 11 '20 at 09:39
  • Actually that’s the whole problem - can’t find a single code sample where they scan for all UUIDs rather than a specific set of uuids... – Rahul Iyer Apr 11 '20 at 10:56
  • 1
    Just perform a non-filtered scan and then manually look through each and every scanResult for your custom serviceUUID. If you can't find it here, then check if it's an Apple device and queue it for connecting (what we discussed above). – Ahimsa Das Apr 11 '20 at 11:15
  • Do you have an example for that one line of code? – Rahul Iyer Apr 11 '20 at 11:22
  • Unfortunately, it's not one line. You'll have to set your scanFilter and settings so that it scans for and returns every other peripheral to the callback method. Inside which you can implement the following... `List UUIDs = scanResult.getScanRecord().getServiceUuids(); if (UUIDs != null) { // Check for your custom serviceUUID here and if not found check if Apple device and queue it up for connection. }` Note, this process is asynchronous. The connections need to be synchronous. There is a lot more! Please explore the docs you'll figure it out. – Ahimsa Das Apr 11 '20 at 11:54
  • Thanks. I’ve been exploring the docs, and it seems like it would save a lot of time to just ask someone who knows. While normally I would take the time to pour through the docs myself, having access to some code right now would be invaluable right now, and possibly help a lot of people. If you happen to have a spare moment and anything to share, it could really help a lot of people. – Rahul Iyer Apr 11 '20 at 11:59

1 Answers1

1

With "overflow" area I guess they mean Scan Response Data. To get that data, a device must perform an active scan, rather than a passive scan. In an active scan, the scanner sends a scan request packet immediately after it detects an advertisement packet. The advertising device will only broadcast the scan response data if it detected a scan request.

Android devices only perform active scans, so you should be fine.

EDIT: the answer above is not correct. See http://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area for correct information.

Emil
  • 16,784
  • 2
  • 41
  • 52
  • Ok, so what is a passive/active scan on android and iOS? What does apple mean by overflow? Can both iOS and android devices see the iOS peripherals by doing "active scan" in background? – Filip Luchianenco Apr 04 '20 at 16:26
  • 1
    An iOS central (scanner) can detect an iOS peripheral (advertiser) that's either in the background or foreground state by mentioning the serviceUUID it's looking for in the instance method [scanForPeripherals ()](https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/1518986-scanforperipherals). So you don't have to worry about the iOS scanner doing an active or passive scan. – Ahimsa Das Apr 05 '20 at 09:25
  • 1
    However, that's not the case with an Android central (scanner). Even if it only does active scans, when the iOS peripheral (advertiser) is in the background state, there is no trace of the custom serviceUUID in the Android scanner's [scanResult](https://developer.android.com/reference/android/bluetooth/le/ScanResult) callback. It does not detect the custom serviceUUID even if explicitly mentioned in the Android scanner's [scanFilter](https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder). – Ahimsa Das Apr 05 '20 at 09:32
  • 1
    @FilipLuchianenco the 'overflow area' is a section of the BLE advertising packet emitted by an iOS peripheral (advertiser) that cannot be read or detected by any device, other than an iOS central (scanner) that's explicitly looking for it - using the serviceUUID as mentioned in my initial comment. – Ahimsa Das Apr 05 '20 at 09:42
  • 1
    I found at least some investigation here: https://github.com/crownstone/bluenet-ios-basic-localization/blob/master/BROADCASTING_AS_BEACON.md. – Emil Apr 05 '20 at 12:12
  • thank you so much guys for these invaluable insights. So to summarize: when app is in background, iOS devices will be able to see other iOS and android devices, android devices will only be able to see other Android devices and won't be able to see iOS devices. Is that right? – Filip Luchianenco Apr 06 '20 at 03:08
  • 3
    @Emil yes. So basically it is not possible to decipher the advertisement packets (more specifically the overflow area data) emitted by an iOS peripheral (advertiser) that's in the background state. – Ahimsa Das Apr 08 '20 at 06:37
  • 3
    @FilipLuchianenco it depends on what your definition of "see" is here. You will be able to detect any device in any state - but when it comes to reading a custom serviceUUID without connecting to the peripheral, you cannot do so if the peripheral (advertiser) is an iOS device in the background state and the central (scanner) is a non-iOS device. – Ahimsa Das Apr 08 '20 at 06:44
  • Thank you and I believe this fully answers the question now. Can you please summarize everything in one answer so I can accept it? – Filip Luchianenco Apr 08 '20 at 13:52
  • @AhimsaDas can you please summarize in an answer? – Filip Luchianenco Apr 10 '20 at 14:51
  • @Emil maybe you can summarize everything so it helps others understand the limitations/challenges. Thank you – Filip Luchianenco Apr 10 '20 at 14:51
  • @FilipLuchianenco in all honesty this doesn't answer the question. It only elaborates on the question better. Apparently, there seems to be no way to detect a custom serviceUUID without connecting to an iOS peripheral (advertiser) that's in the background state - which actually happens to be my question lol. – Ahimsa Das Apr 11 '20 at 09:56
  • 1
    Why don't you just perform a non-filtered scan on Android and dump the whole raw scan record? Then it will be pretty clear if there is any data there (encoded in some proprietary format or not) containing the service uuid. Otherwise you have to connect and perform a service discovery. – Emil Apr 11 '20 at 10:14
  • @Emil Yes that's exactly what we just discussed. Performing a non-filtered scan and simply printing out the scanResult shows some extra encoded data which cannot be deciphered / decrypted. Which is why connection seems to be the only work around. – Ahimsa Das Apr 11 '20 at 11:10
  • How large is the extra data? Is it big enough to contain a 16 byte random uuid? – Emil Apr 11 '20 at 12:49