I know, from documentation, that iOS application can scan for BLE devices when it is in background mode. It can also retrieve data form peripherals devices.
Question
What can I do with this data. My purpose is to save this data (after deserialize of course) to core data. How can I do that?
If this is not possible, what is the recommended way to do it? (NSUserDefaults and after sync with CoreData?)
(iOS10, Swift3)
While in background an app registered to BLE event will be awaken by the system in occurrence of BLE related event that you are registered for. Then the appropriate delegate methods will be called as documented in the official apple documentation.
Events that will awake your app from the BLE are notifications, new peripheral if you are in discovery mode, new connection events (connection/disconnection).
From the moment the app is awaken by the system you have roughly 8 seconds to execute your code and respond to the BLE update. In this time window you can perform any kind of operation you wish, including core data related jobs.
Please consider to read this document released by apple to help developers to develop amazing apps that works with BLE: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html
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'm working on an iPhone app to control some custom BLE hardware. I am able to talk to my device and generate all required controls, but my problem now comes with setting up UserNotifications.
Part of the functionality of this device is to alert the user if one of the BLE characteristic values gets outside of a certain range. When the app is in focus, I am able to do this via UIAlerts. I have played with UserNotifications and I can trigger a notification while the app is focused so that the notification will appear after a specific interval. My issue is trying to generate a UserNotification based on data that's coming over a BLE connection in an app that's not focused.
I can tell via LED's on my hardware that the BLE connection is being maintained even while I'm out of focus/locked. Is there a way to evaluate data from a background BLE connection and create a UserNotification based on it?
I found This Question on StackExchange asking basically the same thing, but I'm hoping that several years later there may be more answers out there.
Cheers,
Roger
Paulw11 above mentioned the app being set up for background operation, which I was not aware of (I'm really new to IOS, I'm more of a low-level firmware guy).
It was just a matter of setting up Xcode background mode to let this run in the background, now I can alert the user regardless of whether the app is Active or 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!
I am working on developing a bluetooth peripheral to work with my iOS device. I need to make the iOS app receive data whilst it's in background and process that data as it comes. Looking through Apple's CoreBluetooth framework, I can see how the background execution modes can be used. Now to save power, I want the iOS device to only connect to the bluetooth peripheral at a certain time (without need of user interaction). I've looked through Local Notifications on iOS and it has very limited functionality and don't think it provides what I need.
So is there anyway to wake up an app at 6pm and ask the application to start scanning for bluetooth devices? And then execute other code once device is connected? All this without user interaction.
Any suggestions would be appreciated!
Thanks!
You can't really schedule operations to occur at a specific time in iOS (aside from local notification, which as you said isn't what you need).
You can use background fetch mode to periodically allow your app to check for new data. You can set an interval (although this is only a guideline to iOS, not a strict schedule) for how often your app is woken.
When iOS calls your app delegate performFetchWithCompletionHandler method you can check the current time and decide whether you want to transfer data. If not then you can quickly return UIBackgroundFetchResultNoData. If you do get new data then you can retrieve it before returning UIBackgroundFetchResultNewData
Here is my scenario ..
I have a device that advertises dynamic data per BLE protocol. There are multiple such devices operating for a user
Questions -
1) Can IOS scan such constantly changing advertising data or does it expect advertising packets to be pretty static?
2) Can we create a service that scans for such packets periodically - maybe 30s every 5 minutes?
3) Can such a service be automatically restarted during bootup without user intervention?
You cannot create a service on a normal (non-jailbroken) phone. Isn't even possible to distribute something like that (read the app review guidelines). Sure, you can scan for BLE data on whatever interval you want, but your app needs to be active, or it needs to be doing something approved by Apple for making connections to BLE devices in the background. Just be aware that like any other background app, iOS might suspend or terminate your app at any time, and there's nothing you can do about it.
What you have described is covered by the standard BLE background mode - it is covered in the Core Bluetooth programming guide.
You can set up a scan for specific service UUIDs and this will continue in the background. Your app will be launched into the background when a device is discovered.
The exact scheduling of the notification can't be controlled - but in my experience you are notified pretty much as soon as a new peripheral is discovered. Once you have discovered a device you can even initiate a connection as soon as it disconnects (ie goes out of range) - iOS will automatically reconnect to the device when it comes back into range
In order for the scan or pending connection to survive across reboots you must configure state restoration. This is also covered in the Core Bluetooth Programming Guide.