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
Related
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
I'm working on a device that keeps count when a door is closed. What I'd like to do is when I walk through the door, my iPhone automatically syncs the data on the device and sends that count to the server (via iPhone) without me opening the app or having it in the background. Is this possible, if so how?
Here's a diagram of what I'm thinking:
Door closes -> BLE notifies iPhone -> BLE sends count to iPhone ->
iPhone sends that value to server
All without the user (me) touching my device or opening the installed iOS application.
Your app has to be running in the background to do something, but that is OK, because Core Bluetooth background mode will take care of that for you.
First, you need to select "Uses Bluetooth accessories" background mode in your project.
Now, your program flow will be something like this:
Your user runs your app which scans for available doors and displays them to the user
Your user selects a door that they want to connect to
You save the identifier of the selected peripheral somewhere like NSUserDefaults
You connect to the peripheral
Once you get a call to the didConnectPeripheral delegate method you can read the count and update your server once you get the value
The user can now suspend your app and do something else
Eventually the peripheral will go out of range and you will get a call to didDisconnectPeripheral. In this method you immediately re-issue the connect to the peripheral.
Since you have Core Bluetooth background mode, when the peripheral is eventually seen again you will get another call to didConnectPeripheral in the background, and you can proceed as per step 5 (In this case your app is already in the background so it will just go back to suspended state after you have read the data without the user doing anything).
You update the server in step 5. This step executes regardless of whether the app is in the foreground or background. The user doesn't need to open your app.
Now eventually iOS may remove your app from the suspended state, say due to memory pressure. In order to still be able to connect to the peripheral when it is seen you need to opt in to state restoration as described in the Core Bluetooth Programming Guide
If you are up for building your own circuit board and Bluetooth LE firmware, this is pretty straightforward:
Add a contact switch that sends a voltage level change to the circuit board whenever the door opens.
Increment a counter on the microcontroller when the level changes.
Write firmware that advertises an iBeacon packet with the counter as the least significant part of the iBeacon identifier (32 bit major and minor).
A phone can then pick up this counter by using CoreLocation APIs to both monitor for the beacon (for fast background wakeups) and range for it (to read the specific identifier), then sending the counter value to the server based on the identifier read.
The advantage of using CoreLocation instead of CoreBluetooth as #paulw11 suggests in his very good answer is faster background wakeups of the app, allowing an app to reliably read the counter in the background. With CoreBluetooth, this background wakeup can be much slower, and door open events are more likely to be missed.
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!
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.
We were looking for a few roles regarding the Bluetooth LE in iOS, but we could not find them. I have a few questions for anyone who is already using it:
I have read here that there is the ability to listen in the background for the signals, is that right? if so, can i get a signal and open that app from background ?
The other way, can my app run in the background and at some point (lets say when the app gets a notification from alarm) send LE signal without even open the app ?
(Its reasonable that yes, because the iPhone DOES call delegate function, that i can write a LE into it, isn't it?)
Does LE Bluetooth control any iPhone operation(s) outside the relevant app?
Does the Apple docs has some kind of ordered roles for the LE?
Yes. But you can't bring the app to the foreground. You can do some background processing and post a local notification.
Not from an alarm, because the alarm would notify the user, not the app. Possibly from a push notification but that would be a bit weird.
Depends. iPhone can act as Central and Peripheral so it could.
? (You mean Central and Peripheral roles?).