IOS Developpement : Background BLE Precisions on Apple doc - ios

I everyone,
I'm trying to develop two apps that act as a central and a peripheral, which automatically connect to each other when they enter in the bluetooth range while both are in background.
I posted something about my issue (because none of my tests were conclusive) on this post : IOS Developpement : Background BLE scanning.
The answer I always find on the internet directly come out of the Apple documentation. One post example (https://stackoverflow.com/a/20460113/5464805):
The problem is the difference in scanning in foreground and background. When you are scanning for devices in the foreground you can scan for anything. In the background you must specify the actual service UUID you are scanning for. Ok, this isn't actually a problem as you know the UUID you are looking for.
Peripheral: Broadcasting as a peripheral again works differently in foreground and background. In foreground it works like any normal BT peripheral. In the background it has a very limited amount of space to work with, so your peripherals UUID is hidden away and not broadcast. Only when a central device (an iPhone in foreground) requests the information from it will it wake your app and show it's UUID.
So the 2 cancel each other out. As your background scan can only scan for devices with a specific UUID and your background peripheral cannot advertise its UUID, they cannot see each other.
But there is something I don't understand: In my central, I already specify the UUID [centralmgr scanForPeripheralsWithServices:[NSArray arrayWithObject:servicesUUID] options:scanOptions];. According to the functionning detailed above, it shouldn't connect when the peripheral is in background and the central in foreground, but it does !
Does somebody have an idea on what is happening in this specific case ? Or maybe a solution to make my two devices connect while in background ?
Thank you!
PS: Also the answer I found is pretty old (2013).

I think that when the central is in the foreground it can wake the peripheral up to retreive the UUID when the peripheral has been detected, but when the central is in the background it cannot. That is why it will not work to have both sides in background mode.

Related

Can iOS app act as beacon, even when it is running in the background?

I need my app to act as a BLE beacon, even when it is in the background.
I've already made the beacon part - works fine when I'm using the app.
The problem is I've never made anything run in the background before, and not sure what the limitations are - if I will be allowed to let the app act as a beacon in the background.
Was wondering if this is possible or not (both technically, as well according to App Store rules)
Is this technically possible ? Can my app act as a beacon, even when the app is not in the foreground.
Is it within App Store rules ?
Unfortunately, iOS apps cannot emit iBeacon advertisements unless they are in the foreground. If you program your app to advertise iBeacon frames, as soon as the screen turns off or the app is not visible, iOS changes the advertising format to a special generic background advertisement that does not match the iBeacon format.
This proprietary background advertisement is useless for identification of a device. It is designed for connection to BLE GATT services from other iOS devices. Unless you want to advertise a connectable BLE GATT service to other iOS devices this advertisement has little value. EDIT: There is a way to make use of this advertisement. See below.
Apple's documentation describes this limitation here in the section titled "The bluetooth-peripheral Background Execution Mode":
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.
If all apps that are advertising are in the background, the frequency at which your peripheral device sends advertising packets may decrease.
It may not be obvious that the above causes iBeacon transmissions to break, but I assure you that is absolutely a consequence.
Read my blog post here for more information on how to put useful beacon data into this background "Overflow Area" advertisement.

How to send messages to a connected bluetooth device in iOS in the background

I'm using BLECommander to connect to a bluetooth device in the foreground and my code is heavily based off this sample app. I believe my app would use both bluetooth-central and bluetooth-peripheral. Additionally, I would ping in the background every couple of hours to retrieve any new missing data. I am fine with connecting to a device in the foreground; I simply want to send messages to it in the background and retrieve data.
I have read the apple documentation on using core bluetooth to operate in the background.
If you read the apple documentation, you should know that your options are quite limited on iOS on what you can do in general when your app is in background.
However, there could be ways to achieve what you want. If you have control over the other bluetooth device you can make it change the BLE advertisement from time to time. When you scan on iOS, you will also get a scan result in background (but only once for a certain advertisement!) and can then connect to the device and read/write.
Hope this helps!

iOS - Scan BLE devies in background

I have noticed that scanForPeripheralsWithServices is not working in background. I tried with following:
specified UUID and option nil
set UIBackgroundModes bluetooth-central and bluetooth-peripheral info.plist
I want a background service that should scan BLE devices in background continuously.
Thanks for your help!
Background mode works differently for scanning.
Every peripheral is only reported the first single time it is observed (you cannot track proximity through RSSI without connecting to it while in background mode).
You can initiate a connect request to a peripheral that's not within range, and the connection will complete when the peripheral becomes available. Don't have to actively scan for this (except for initial discovery, so you know which UUID to connect).
Maybe, you can solve the problem by sending a connect request instead of scanning, while in background. This way, iOS knows that you are really interested in a specific peripheral and I could imagine that this affects discovery times.

Core Bluetooth: Transmit specific data in background as advertiser

I'm trying to use an iOS BLE device as BLE peripheral which also advertises in background.
I already figured out how to advertise in background and got it detected by another device looking for the specific bluetooth UUDID.
Unfortunately the advertiser-info is not transmitted when the app is in background. Is there a way to send a short string or something else device specific when the app is in background? It would be ok if the app would be woken up for a short period (if this is possible).
The advertised services are removed from the advertisement packages when the app is backgrounded. Only foreground scanning iOS devices will be able to obtain the services.
The advertised services are arbitrary UUIDs. You can easily figure out some encoding to store characters in them. However, this has several caveats, like
the general scheme is usually that the scanner finds your peripheral by the service UUIDS. If the data can be anything, then this is tricky.
the peripheral will not be able to change the advertisement data while backgrounded.
I suggest you not try to trick around with the system. Rather plan for connecting to the peripheral for a short time and sending the data to the central during this interval.

Core Bluetooth advertise and scan in the background

I have been trying to setup an app to make the device both scan for peripherals and advertise as a peripheral. The goal is for two devices to be woken up in the background when they become near each other via bluetooth discovery. From the Apple Documentation, it seems that you should be able to run BLE in the background (with bluetooth-central and bluetooth-peripheral background modes enabled), and my application works when one device is in the foreground.
First, I advertise data like so:
NSDictionary *advertisingData = #{CBAdvertisementDataLocalNameKey:#"my-peripheral",
CBAdvertisementDataServiceUUIDsKey:#[[CBUUID UUIDWithString:identifier]]};
// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];
I then set the device to scan for data:
NSArray *services = #[[CBUUID UUIDWithString:identifier]];
[centralManager scanForPeripheralsWithServices:services options:nil];
However, when both go into the background (device has to be locked), the bluetooth cannot discover and
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
never gets called on either device. How can I fix this?
Thanks
I'm afraid what you are trying to do will not work.
I have tried to achieve the same thing.
The problem is the difference in scanning in foreground and background.
When you are scanning for devices in the foreground you can scan for anything. In the background you must specify the actual service UUID you are scanning for. Ok, this isn't actually a problem as you know the UUID you are looking for.
Peripheral:
Broadcasting as a peripheral again works differently in foreground and background.
In foreground it works like any normal BT peripheral. In the background it has a very limited amount of space to work with, so your peripherals UUID is hidden away and not broadcast. Only when a central device (an iPhone in foreground) requests the information from it will it wake your app and show it's UUID.
So the 2 cancel each other out. As your background scan can only scan for devices with a specific UUID and your background peripheral cannot advertise its UUID, they cannot see each other.
1 of your devices (either peripheral or central) must be in the foreground to work.
This has been discussed several times on the Apple Bluetooth mail list.
You should elaborate on how you're testing this, because theoretically it looks like it should work. There's two primary issues you may be facing:
1.) Scanning is throttled down when iOS devices are in the background.
While scanning in the foreground will likely immediately discover a device advertising next to it, discovery in the background can take up to ~60 times longer. The iOS system makes no assumptions that the user would prefer one app to have better Bluetooth functionality than another (or that only one app wants to use it). And since it is shared functionality, they want users to have a uniform experience across apps. You should check out the technical specifications regarding Advertising and Scanning intervals to get a better idea of what Apple has to do under the covers.
2.) Your devices may have already discovered each other before entering the background.
We must remember that Apple disables the CBCentralManagerScanOptionAllowDuplicatesKey scanning flag when we enter the background. Since you're not even specifying this flag, it defaults to NO anyways. So if they've even seen each other once, you will not get another callback when they are in the background.
I personally needed such a feature and I developed an open source component: https://github.com/omergul123/Discovery
It might be very helpful if you want to exchange an ID even if the peer apps are running at background.

Resources