Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreBluetooth in Background at Scheduled Time

Problem: I need to remain disconnected from a BLE peripheral but send data it's data to a server for processing as often as possible, as it is potentially time-critical. In other words, I want to connect every so often and send the synced data to an API, while remaining disconnected at all other times to save battery life.

Failed Attempt: Setting the UIBackgroundModes field of my app's Info.plist file to bluetooth-central only gives me background execution while I am connected. I want to remain disconnected, but reconnect at predefined intervals, as well as schedule an alarm from background mode.

It's possible: I've noticed that the FitBit Flex app has an option in the settings to enable syncing in the background. I am not sure if it ever disconnects from my Flex while it is in range, but judging its so-small-I'd-lose-it battery size, I'm guessing it does not remain connected.

like image 687
cbh2000 Avatar asked Oct 30 '13 22:10

cbh2000


People also ask

What is background Bluetooth?

The bluetooth-central Background Execution Mode plist file, the Core Bluetooth framework allows your app to run in the background to perform certain Bluetooth-related tasks. While your app is in the background you can still discover and connect to peripherals, and explore and interact with peripheral data.

What is background fetch in IOS?

The Background Fetch API provides a method for managing downloads that may take a significant amount of time such as movies, audio files, and software.

How do I put background mode in Xcode?

Select your app's target in Xcode and select the Capabilities tab. Under the Capabilities tab, set the Background Modes switch to ON and select the “Audio, AirPlay, and Picture in Picture” option under the list of available modes.


3 Answers

I know I've already accepted an answer for this (sorry!), but I've found a solution:

[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:60*5]; // Every 5 minutes, minimum

in:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

and adding fetch to UIBackgroundModes, which iOS then calls:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler

every 15-240 minutes (yeah, it varies a lot, but it's better than nothing). Every time I am called to perform a fetch, I connect to the peripheral, sync and send its data to the server, then disconnect. Since I'm sending this data from the BLE peripheral to a server for processing/storage, I'm presuming that this is a legitimate (AppStore worthy) use of fetch.

CAVEAT: application:performFetchWithCompletionHandler: will not be called until iOS establishes a user usage pattern for the app. In other words, you need to keep the app around (not delete it) for about 24 hours or so before the application:performFetch... method gets called. Boy, did it take a while to figure that out!

UPDATE: Apple has accepted my app that used this solution (approved May 2014).

like image 147
cbh2000 Avatar answered Oct 11 '22 12:10

cbh2000


You can't. A backgrounded app cannot start any transactions, it can only react to incoming requests (data notifications, connection events...) In the background the application is effectively not running and even in case of BLE events it has only 8 seconds to go back to sleep, otherwise it is completely terminated for breaking the policy.

The only case when your app can stay alive for a while is when it uses the beginBackgroundTaskWithName:expirationHandler: API. But even in that case it has only 10 minutes to complete or it gets killed.

If you want to synchronize while in background, then the transaction must be started on the external peripheral's side. Easiest is to stay connected and send a notification to the central every once in a while. That will wake it up and it can proceed with reading the characteristics it needs. But there are several other ways to implement it. The final solution has to be designed to best meet your needs. If you have a concrete idea, then please submit it as a separate question.

like image 31
allprog Avatar answered Oct 11 '22 14:10

allprog


https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf

I'm pretty sure you guys have seen this, but just in case you haven't. Perhaps on the BLE Peripheral end you can save power by increasing the connection interval (page 22).

like image 1
David Chu Avatar answered Oct 11 '22 13:10

David Chu