7
votes

When developing an app that uses Bluetooth Low Energy, there comes a time when the iOS device loses connection to the peripheral. (Sometimes for hours.)

In order to reconnect to an existing peripheral, the app must constantly scan in the background at a specific rate throughout the day(s), even when the app is backgrounded.

The problem is, iOS will not guarantee that your app will not get killed, due to memory constraints, etc.

Information found in the iPhone OS Programming guide states that:

Apps that work with Bluetooth peripherals can ask to be woken up if the peripheral delivers an update when the app is suspended. This support is important for Bluetooth-le accessories that deliver data at regular intervals, such as a Bluetooth heart rate belt. When an app includes the UIBackgroundModes key with the bluetooth-central value in its Info.plist file, the Core Bluetooth framework keeps open any active sessions for the corresponding peripheral. In addition, new data arriving from the peripheral causes the system to wake up the app so that it can process the data. The system also wakes up the app to process accessory connection and disconnection notifications.

The problem does not arise when the phone is connected to a device and the application is background. It does happen, however, when the device is disconnected and the app is backgrounded. In this specific case, the phone is no longer connected to the peripheral, and therefore no longer getting notifications.

Many people have discussed this before, either on Stack Overflow or the Apple forums, and I believe one of the Apple developers has responded saying:

We're aware of this issue and are trying to come up with a solution. Currently, there is no workaround."

My question is, is there a way to at least improve your chances of not getting killed by iOS due to memory constraints?

For example, an instant messaging app (IMO) seems to run quite nicely in the background. After days and days of not being used, the app will wake up and display a gChat message.

I’m questioning things such as

  • Strong pointers
  • Overall memory size
  • Reducing memory size when app is backgrounded or minimized
  • Reducing frequency of background operation
  • Etc.
3

3 Answers

1
votes

Why do you need background execution even when the bluetooth hardware is disconnected? I don't think that you need to "rescan continuously" to reconnect again, if the hardware is "paired" with the iPhone/iPad, it will reconnect itself. Like a bluetooth headset. Or not?

AFAIK you have no chances to accomplish what you are asking for. A normal App is always suspended when the user go back to home. The app has approx. 5 secs of background time to stop timers, save state ecc ecc. There are special background modes that allows you to have more background time, and each of this mode (explained in the page you linked) has a different behavior.

About the bluetooth mode: The descripted behavior is not an issue, but it's by design:

  • the app is suspended

  • when the app is suspended, it can be killed by the OS to free ram (and there are no tricks to avoid this), but the system will wake up if needed.

  • the app is then awaken every time a notification is received (awaken from suspended state or lauched from "previously-killed" state)

  • the app has 10 seconds to do tasks (save informations, ecc ecc). Moreover, can request +10 mins. of background time for a particular task

  • after the 10 secs (or 10 min) the app is suspended again

The example you wrote about the chat app is incorrect: chat apps usually doesn't use any background mode, simply they forward you messages using push notifications. When you open the app, the app connect to a server that stores all your messages and download it.

You can get "more uptime" using location background mode (routing app can work in background), or using a combination of significative location changes (the app is awaken) and the 10 minutes background time, but I think that Apple will reject an app that "abuse" this.

Shortly, you have to design your app to support this behavior.

0
votes

I found this in some more Apple documentation:

Memory Usage for Background Apps

Every app should free up as much memory as is practical upon entering the background. The system tries to keep as many apps in memory at the same time as it can, but when memory runs low it terminates suspended apps to reclaim that memory. Apps that consume large amounts of memory while in the background are the first apps to be terminated.

Practically speaking, your app should remove strong references to objects as soon as they are no longer needed. Removing strong references gives the compiler the ability to release the objects right away so that the corresponding memory can be reclaimed. However, if you want to cache some objects to improve performance, you can wait until the app transitions to the background before removing references to them.

Some examples of objects that you should remove strong references to as soon as possible include:

Image objects

Large media or data files that you can load again from disk Any other objects that your app does not need and can recreate easily later To help reduce your app’s memory footprint, the system automatically purges some data allocated on behalf of your app when your app moves to the background.

The system purges the backing store for all Core Animation layers. This effort does not remove your app’s layer objects from memory, nor does it change the current layer properties. It simply prevents the contents of those layers from appearing onscreen, which given that the app is in the background should not happen anyway. It removes any system references to cached images. (If your app does not have a strong reference to the images, they are subsequently removed from memory.) It removes strong references to some other system-managed data caches.

0
votes

From the apple documentation i have always assumed the following:

connectPeripheral:options:
Establish a connection to the peripheral.

- (void)connectPeripheral:(CBPeripheral *)peripheral options:(NSDictionary *)options;
Parameters
peripheral
The peripheral to connect to.

options
A dictionary to customize the behavior of the connection. See CBConnectPeripheralOptionNotifyOnDisconnectionKey.

Discussion
**This never times out**. Use cancelPeripheralConnection: to cancel a pending connection.'

With the important part being on the fact that this never times out. I would assume this would hand off to the system so that it will connect automatically to the peripheral when it comes into range, thus removing the need for full backgrounding. Someone correct me if im wrong though!