19

I've written an app that needs to get informed when a certain Bluetooth Low Energy device comes within range. If the BLE device gets noticed my app just stores a timestamp.

As stated in the WWDC 2012 Core Bluetooth videos, there are two possibilities for apps for acting in background mode when working with Core Bluetooth:

Event Backgrounding

Event backgrounding is probably what most Apps will use when interacting with Bluetooth Low Energy devices. This mode does not allow for direct communications to the accessory when the App is in the background, but does provide for a notification from the accessory when it wants to communicate with the app. iOS will stay connected to the BTLE accessory when your App is in the background and will continue to monitor for notifications. When the connected BTLE accessory has a notification available, iOS will notify the user that the accessory would like to talk to your App, allowing the user to load your App and interact with the accessory. As many devices need to conserve power, only providing information at deterministic times will greatly enhance the battery life of the accessory and the iPhone 4S.

  • No info.plist entries are required for this mode.

Session Backgrounding

There are times where an App must interact with an accessory even if it is running in the background. Consider a running app that needs to monitor heart rate real-time. There is a clear START and STOP to this model. The user STARTS their run in the App. While the run is active, the App reads heart rate information until the run is completed or STOPPED. Session backgrounding also allows for scanning and connection to BTLE accessories while the App is in the background. A scanForPeripheralsWithServices or connectPeripheral call will continue, even when the App is in the background. CoreBluetooth will continue to monitor for specific peripherals or peripherals that match the services your App is looking for and call your Apps delegate when found or connected. Be mindful, that every time a BTLE peripheral or iPhone 4S uses its radio, it is depleting the respective devices available power. App developers using session based backgrounding must be mindful of power usage.

  • Session backgrounding requires a backgrounding mode entry to UIBackgroundModes, bluetooth-central, in your Apps info.plist.

Until now I Session Backgrounding (with the according info.plist entry). The app asks iOS to retrieve all known devices and then gives the connect command to the device I'm looking for. The connection callback comes even after minutes after my app was backgrounded.

But: the app gets suspended after - let's say - one hour. This means that the next time my app gets launched by the user, it cannot tell if there have been any sightings of the BLE device of interest.

So my question is: Is it possible for my app to get notified without user interaction even days after being sent to background when a certain BLE device comes in range so I can store my time stamp?

Norbert
  • 3,999
  • 6
  • 33
  • 57

3 Answers3

15

As of iOS 7, your use case is now easy to support. Before iOS 7, your application could register for notifications about that peripheral, and it would be woken up in the background when the system had notification to deliver. However, if the system came under memory pressure while your app was backgrounded, or was rebooted, it wouldn't be relaunched. iOS 7 added state restoration to CBCentralManager and CBPeripheralManager, so now the OS will relaunch your application in a limited capacity even if it wasn't running due to either of the aforementioned conditions. See the CoreBluetooth guide for more info.

In short, for your use case, you could do the following:

  • Continue to support bluetooth-central as a background execution mode.
  • Opt into state preservation and restoration, as documented here under "Adding Support for State Preservation and Restoration".
cbowns
  • 5,932
  • 4
  • 41
  • 63
  • Hi @cbowns I have a question here...I have added Adding Support for State Preservation and Restoration but Since I am not able to test when the app terminates on its own and system relaunches app..What i am doing is killing my app and than when i am launching the app again I get BluetoothCentralKey as nil..Is it pretty sure that the the i will get my keys array if the system restarts the app on its own?? – sheetal Dec 06 '13 at 13:28
  • @sheetal Hmm. I've not yet implemented it myself, so I don't know how precisely to test it. Everything I've read on Apple's forums and the `bluetooth-dev` list suggests it's very difficult to test. – cbowns Dec 06 '13 at 18:34
  • 1
    @sheetal There is note important thing to note if you're killing the app to test things: https://devforums.apple.com/message/908637#908637 As of iOS 7.0, any app that's quit in the multitasking UI is *not* relaunched by the OS for any reason other than a user taking action to open the app (i.e. selecting the icon on the home screen or selecting a push notification). (https://devforums.apple.com/message/921969#921969 is another way of putting it. I'm still looking for where I read this behaviour described by someone from Apple.) – cbowns Dec 06 '13 at 18:41
  • 1
    @sheetal Found it! https://devforums.apple.com/message/886796#886796 from Paul Marcos. – cbowns Dec 06 '13 at 18:43
  • @cbowns thankyou so much...I have doubts on is it sure than when system kills my app and relaunches my app again i will get the BluetoothCentralKey array for sure ?? Can u help me with how can i make apple kill my app without me explicitly killing it?? – sheetal Dec 07 '13 at 12:42
  • So that i can test on the relaunch thing..What best i can do is put Logs..But its difficult to search my logs..Is this the only way??? Thanks – sheetal Dec 07 '13 at 12:52
  • @sheetal Re: "How can I make iOS kill my app without me explicitly killing it?" it seems that hitting the "stop" button in Xcode will work (per https://devforums.apple.com/message/908637#908637) – cbowns Dec 09 '13 at 23:40
3

No, iOS gives no guarantee that your app keeps alive in the background. The docs say:

However, this method may be called in situations where the application is running in the background (not suspended) and the system needs to terminate it for some reason.

(Documentation of applicationWillTerminate)

  • That being said there is little to no chance that your app will remain active after days of background use. – Kyle Richter Mar 19 '13 at 15:57
  • This answer is incorrect. Check the app "Dark Sky" in App Store. It's an location based weather app. It's been running in background in my phone for months and continously notifies me when it's going to rain. – Penghe Geng May 28 '13 at 20:15
  • 3
    That app probably uses Push Notifications. For that the app doesn't have to be running in the background. – allprog Aug 08 '13 at 06:53
  • Note that iOS7 is going to introduce new features to overcome this issue. It's gonna be tough to handle though. – allprog Aug 08 '13 at 06:55
  • @PengheGeng Some apps use core location and set triggers to be notified when the user changes location. This way they can get some processing time. Dropbox does this for file upload as far as i know. But that's a hack. – Christoph Wimberger Aug 12 '13 at 14:09
  • 1
    @ChristophWimberger I doubt your suggestion of Dropbox using location service for 1) it should have asked user's permission to use location service and I am not aware of it has ever done that. 2) I think using location service in such way is a breach of App Store policies. -- Can you give a link for the source of your information? – Penghe Geng Aug 12 '13 at 15:05
  • @PengheGeng instapaper for example: http://blog.instapaper.com/post/24293729146 "[...] iOS doesn’t yet permit apps like Instapaper to automatically download new content in the background on a regular schedule, but Background Update Locations can get most of the way there for a lot of people. [...] Instapaper stores these locations only within the app itself, only for this purpose, and does not share them or send them to any web service (not even its own servers). [...]" – Christoph Wimberger Aug 14 '13 at 10:50
3

Use IOS7 BLE State Preservation & Restoration

If your app is terminated by IOS, due to memory pressure(this is why your app can't work after days), it can't handle bluetooth delegates anymore. In this case, if you used State Preservation & Restoration, your app can be relaunched to background to run again, also for only 10s. After 10s, it would move to suspended state. Only in this situation, CBCentralManager's willRestoreState can be triggered.

Good luck.

Roy Zhang
  • 231
  • 2
  • 5