2

I work on iOS application which is using BLE for communication with our custom made BLE unit. We want to send specific commands via BLE to the unit automatically.

When user is near unit and specific criteria are met, the app should connect to the unit, "login" the user, send command via BLE and disconnect right away.

These specific criteria are based on manufacturer data from advertisement (i.e. the unit is in "available to login" state when manufacturer data has last byte 0x01, when it's "NOT available to login", last byte is 0x00).

In foreground, this mechanism works flawlessly. We want to do this even when app is in background or terminated (swipe up in dashboard on iPhone).

The mechanism we have implemented:

  • the unit has capability of acting as iBeacon
  • when unit is NOT available for login, the iBeacon is OFF
  • when it IS available for login, the iBeacon will turn ON and wakes up application, upon that the BLE scan will start in background mode
  • background mode setting is bluetooth-central

Problem here is that no matter what I tried, the advertisement:

  1. sometimes it's not discovered at all (looks like it's timing issue?)
  2. when it's discovered, it does NOT contain manufacturer data

Did anyone come across something similar? Any help is appreciated and have a nice day!

RichX
  • 494
  • 5
  • 13
  • This article may be helpful: https://medium.com/@cbartel/ios-scan-and-connect-to-a-ble-peripheral-in-the-background-731f960d520d – DonMag Jul 30 '20 at 14:56
  • Thanks, I read it few times. His problem was not discovering peripheral in background mode at all. In my case, the discovery sometimes happen. – RichX Jul 30 '20 at 15:02

1 Answers1

4

An app simply cannot read raw BLE manufacturer advertisement data when in the background on iOS -- the operating system prohibits it.

Two exceptions to this rule:

  1. iBeacon, which itself is implemented as a specific type of manufacturer advertisement. An app can detect iBeacons in the background on iOS, although only four bytes of readable data (encoded in the major and minor fields) are fully usable. If you can modify your device to send information this way, it will do what you want. However you must use CoreLocation APIs to detect iBeacon, as CoreBluetooth does not allow reading manufacturer data from iBeacon advertisements. If you do use CoreLocation, you cannot use the detections to establish a Bluetooth connection with CoreBluetooth as the two APIs are sandboxed.

  2. Overflow Area advertisements. Backgrounded iOS apps can read these special types of manufacturer advertisements when in the background but only if the screen is turned on. (It is often possible to force the screen on at specific times by sending a local notification.) See my blog post here for more info: http://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area

An alternative to detecting manufacturer advertisements is to use BLE Service advertisements with attached data. For this to work, you'd need to define a 16 bit or 128 bit GATT Service UUID and send out an advert with attached data bytes. Eddystone beacon formats work this way, and allow detection in the background on iOS. This is probably the best approach if you can alter the BLE hardware.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • @davidyoung so I can't use CoreLocation and CoreBluetooth at the same time? Like monitoring for iBeacon and scanning for BLE advertisements? – RichX Aug 03 '20 at 10:56
  • 1
    You can absolutely use the two at the same time, yes. However, there is no way to correlate detections from one with the other. When you detect a beacon with identifiers (ProximityUUID: 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6, major: 12, minor: 127) and you detect the exact same bluetooth device with CoreBluetooth peripheralID 0A82ED1E-5043-49F9-9B77-C0765A17C9AB, there is no way to programmatically correlate the CoreBluetooth peripheral with the iBeacon detection even if they are the same device. Apple intentionally sandboxes them so you cannot do this. – davidgyoung Aug 03 '20 at 15:51
  • 1
    You could, of course, expose GATT characteristics to allow you to read the beacon identifiers so you can correlate -- but this doesn't help you until *AFTER* you have already connected, so it is not useful in determining the device to connect to. – davidgyoung Aug 03 '20 at 15:54
  • @davidyoung thanks a lot! We'll try to work with iBeacon major, minor fields and see if it's sufficient. – RichX Oct 26 '20 at 12:26
  • @davidyoung regarding your alternative approach, did you mean that if we define our custom GATT service, we could advertise any data with it and iOS will not omit that while in background? – RichX Nov 10 '20 at 13:26
  • Yes. You can scan for a custom gatt service in the background and get attached service data to the advert. This is how eddystone beacons work. The only drawback is that they are slower to detect in the background than iBeacon. – davidgyoung Nov 10 '20 at 19:50