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.
Related
I am currently using CoreBluetooth to scan for peripherals. Every 30 seconds it sends its packet of information to the cloud by using a Timer. This is working good in foreground. I would like this exact operation to function seamlessly in the background too.
I have declared a CBUUID ahead of time for it seek out the designated peripheral in the background. Upon entering background mode, the scan stops functioning after 10~ seconds. How do I continually make the scan operate continue in the background?
I was looking into Bluetooth State Preservation, would this alleviate the issue? Should it also not be on the main thread?
After the packets are advertised I would like them stored in memory. I am aware the DiscoverPeripherals logs the peripherals... is it possible to log the RSSI and additional peripheral data in chronological order and have it an operation take affect per an interval? I was looking at BGProcessingTask to fire off a function in the background. Would a better approach be to use CoreData to store the memory and clear it after? Best/easy suggestion is appreicated.
I have changed the CBUUID to the right peripheral for centralManager.scanForPeripherals(withServices: [uuid], options: nil)
with uuid being the CBUUID. That seem to be allowing the peripheral to be detected in the background. It stopped logging the scan after a short period of time. Right when I put the app in background, it functions properly for a bit. I theorize it could just be calling it on the same thread and it may not be operating in the background all together. I did test this by changing the the withServices to nil, the result was that the operating was not being logged at all once I closed to the background.
I was expecting the operation to continually be scanning on the basis of the Timer every period, after the period is up it would send it the cloud just how it was doing it in the foreground.
There are lots of restrictions on iOS apps when they are not in the foreground. Once an app moves from the foreground it is suspended and can only execute in the background for specific reasons and for limited durations.
In general, anything based on a Timer will not fire when the app is not in the foreground.
Some Core Bluetooth events are delivered while your app is in the background:
Pending connect operations can complete with a corresponding delivery to your app.
Peripheral disconnections will be delivered to your app
GATT Notify/Indicate operations from a connected peripheral will be delivered to your app.
Discovery of new peripherals advertising a service that you are specifically scanning for will be delivered to your app.
It is this last behaviour that you are relying on.
While you have done the right thing by specifying the specific service you are interested in, your plans are being thwarted by the fact that Core Bluetooth will not deliver repeated discovery notifications for a particular peripheral.
When your app is in the foreground you can use the CBCentralManagerAllowDuplicatesKey option to request a discovery notification each time a peripheral advertisement is seen, even if an advertisement from that peripheral has been seen before. This option has no effect when your app is not in the background.
The best way to gather data on a periodic basis from a peripheral (whether in the background or foreground) is for that peripheral to send its data via Notify/Indicate, however you seem to be trying to scan for the existence of peripherals rather than gather specific data from them, so this may not work for you.
When one of the supported Core Bluetooth background events occurs and your app has been jettisoned, State restoration allows your app to respond after iOS relaunches your app. It will not help you in this case.
It probably isn't possible to do what you want, at least not without changing the behaviour of your peripheral.
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.
I have worked on an app which read heart rate from server kinds of bluetooth low energy HRM(Heart Rate Monitor)by bluetooth notification.
And I have added the "App communicates using CoreBluetooth" into the app's "Background Modes".
It works fine when the app is in foreground, but when the app is in background, one of the Heart Rate Monitors is always to be disconnect with the app in sever minutes.
So I debugged the app and find that, this kind of HRM is always push notification irregularly.The interval between notifications is from 1 second to 20+ second.
I know that when the app is in background, iOS will stop the bluetooth connection if it is too long between bluetooth notifications.
So my question is: Is it possible to keep the connection when the app is in background?
Is reconnection the only way to solve my problem?
Detecting the disconnection and reconnecting to the peripheral will make your app more robust as it will handle the case where the peripheral goes out of range and then returns in addition to the case you are seeing.
When the peripheral is disconnected your centralManager:didDisconnectPeripheral method will be called on your delegate. In this method you can call connectPeripheral:options again to re-establish the connection. iOS will either do this immediately if the device is still in range or automatically later, once the device comes back into range.
Once your centralManager:didConnectPeripheral method is called you can re-establish the characteristic monitoring.
Edit Clarify that you can call connectPeripheral immediately
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.
my app using scanForPeripheralsWithServices: to scan BLE device,the argument is specified servicesUUIDs array, sometimes could discover peripheral quickly,but sometimes need to wait for a moment.And my app is session backgrounding.Then,how can I discoverPeripherals as quickly as possible on background.
When the app is in the background iOS is enabling Bluetooth from time to time and it is not always listening. This is to save battery and because the WiFi and Bluetooth share the same antenna and cannot send at the same time. To make it discover your peripheral as fast as possible you should if you have access to peripheral implementation, make sure the peripheral advertises itself as often as possible. I believe Apple recommends at least once each 20th ms.