2
votes

I am trying to create an app that wakes up to background mode whenever it detects a new peripheral that advertises a pre-defined service. I want the wakeup to happen even if the user minimized the app, the app was suspended, the app was killed by the user or the app was killed by the system. Obviously I also want the app to be accepted to the app store (so don't suggest solutions like adding all possible UIBackgroundModes and run in the background forever...).

I can add bluetooth-central to the UIBackgroundModes because my app fits the description here - it needs to communicate with a peripheral in the background.

I found some documentation here about State Preservation and Restoration. It describes a scenario where an app connects to a bluetooth door lock, and the connection breaks because the user went far away from the door. From what I understand, when the user returns to the door and the iPhone detects the door lock (by its MAC address, I suppose), it reconnects to the door lock and wakes up the app in Background mode (please correct me if I am wrong).

I don't want to preserve a connection to the peripheral (and waste its battery). I want the app to run scanForPeripheralWithServices that will wake up the app when a new peripheral is detected, even if the app was killed\suspended by the user\system.

I found a relevant answer here to a different question, saying I could simulate an app-termination-by-the-OS using kill(getpid(), SIGKILL); and then, if my app uses State Preservation & Restoration, it should wake up (right?).

When my app detects a new\old peripheral, I want it to create a quick connection, read some characteristics and disconnect. Unforetunately this is not possible with iBeacon Monitoring that does not give a Peripheral object (only a region). I know I can detect the peripheral by running scanForPeripheralsWithServices after my app enters the iBeacon region, but this feels strange - a direct continuous scanForPeripheralsWithServices that survives suspension & kill, would make much more sense.

Any ideas?

If you know for sure that this is not possible, and depending on iBeacon Monitoring is the only way, please let me know.

1
If the user kills your app then there is nothing you can do. Your app won't run until the user relaunches your app. The other part is straightforward. You can scan for a peripheral offering a particular service in the background and you can also have a pending connect for known peripherals which will automatically complete when that peripheral is seen.Paulw11
Here is some sample code that demonstrate background scanning and connection github.com/paulw11/BTBackgroundPaulw11
So you're saying that even if a connection is made, if the user killed the app from the app switcher it will not be relaunched? Not even after a reconnection? (will there be any reconnection?).Oren
What happens if I call kill(getpid(), SIGKILL) on willResignActive right before the user even has a chance to kill it from the app switcher? Will it mean that the app never gets killed by the user, and therefore will wake up?Oren
In general in iOS if the user kills the app from the app switcher then it is assumed that the user wanted it dead and iOS will not relaunch the app until the user taps the iconPaulw11

1 Answers

0
votes

The key part of the question is:

I want the app to run scanForPeripheralWithServices that will wake up the app when a new peripheral is detected, even if the app was killed\suspended by the user\system.

Unfortunately, this is not possible with CoreBluetooth alone. If the user kills an app, it will not get new OS launch events from CoreBluetooth unless the user manually launches the app again.

Fortunately, CoreLocation does not have this restriction. Since iOS 7.1, it will launch a killed app to notify it of a Bluetooth beacon detection. This would allow you a few seconds of background running time to scan for peripherals.