Activating an iOS app when Bluetooth connection connects - ios

Is such a thing possible? I know certain apps such as VOIP apps have permission to run constantly, but I'm uncertain my app idea would be allowed to always run.

It depends on what you mean by "Activating an app".
You can operate as a Bluetooth Central in background mode and your app can receive notifications that a Bluetooth Low Energy service has been detected (if you are scanning for that service) or a device has connected (if you have a pending connect for that device).
You can then interact with the peripheral briefly (transfer a small amount of information for example) or display a notification to the user, but you cannot bring your app to the foreground preempting whatever the user is currently doing.
This project demonstrates CoreBluetooth background connection - https://github.com/paulw11/BTBackground

Related

How to keep scanning for BLE sensors and Identify sensor keyEvent while iOS App is terminated

How to keep scanning for BLE Sensors while App is in the terminated status in IOS App. While App is running I am able to manage multiple sensors. However, when App is terminated, how to keep listening to an advertisement and connect the Sensor to App not running status.
State preservation and State Restoration is implemented. Background mode Bluetooth-Central is turned on
I want to achieve it like Tile and Chipolo are doing in the terminate state.
What you are trying to achieve is not possible with normal ble capabilities:
Apps that support background execution may be relaunched by the system to handle incoming events. If an app is terminated for any reason other than the user force quitting it, the system launches the app when one of the following events happens:
Refer to Understanding When Your App Gets Launched into the Background
The way tile works is by using the iBeacon standard (my best guess).
An iBeacon is substantially a BLE. Your app can start a Region Monitoring for an iBeacon receiving region events (enter, exit). These events would wake your app also if the user killed it. When your app is awaken by a region enter event you have 8 seconds (give or take) to execute code and react to the event. Within this time you can start a standard BLE connection to use your iBeacon as peripheral and keep your app reactive to BLE events.
Of course your peripheral must be designed to support such behaviour.

Syncing data over BLE via iOS without App Open (or in the background)

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.

iOS Bluetooth monitoring without iBeacon monitoring

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.
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.

iOS: Can a BLE device (not an iBeacon) wake up my app?

Is it possible to associate a regular Bluetooth Low Energy device (not an iBeacon!) with my iPhone app so that when the device sends data my app gets woken up by the iPhone even if the iPhone is locked and the app is terminated (not even in the background)?
As long as your app specifies Bluetooth Central background mode then it will be woken if
Your app has a current connection to the device and it sends data (i.e. the device is in range and it notifies or indicates on a characteristic)
Your app has a pending connection to the device and it comes into range(i.e. the device was out of range, but you have called connect to automatically reconnect when it comes into range)
Your app was scanning for specific service types and a device advertising one of these service types comes into range
The case where you app is terminated is slightly different. For these scenarios to work in this case your app must implement state preservation and restoration
Core Bluetooth supports state preservation and restoration for apps
that implement the central role, peripheral role, or both.
When your
app implements the central role and adds support for state
preservation and restoration, the system saves the state of your
central manager object when the system is about to terminate your app
to free up memory (if your app has multiple central managers, you can
choose which ones you want the system to keep track of). In
particular, for a given CBCentralManager object, the system keeps
track of:
The services the central manager was scanning for (and any scan
options specified when the scan started)
The peripherals the central
manager was trying to connect to or had already connected to
The
characteristics the central manager was subscribed to
The Apple guide talks about the situation where your App is terminated due to memory pressure. It doesn't specify what happens if the app is terminated by the user "swiping up" in the app switcher - In many cases iOS takes this as an indication that the user doesn't want the app to run at all and won't restore it in this case.
There are two states for a bluetooth device to interact with your app:
It has never interacted with your app before
It has already connected to the use's device once and to the app once
In either case, an iBeacon device will be able to interact with your app.
If the device hasn't connected with your app before, I'm not entirely certain if there is a way to make it work. I have tried and failed to get it to wake up the app.
However, if the bluetooth device has connected before, then you can use CBCentralManager and its delegate methods to communicate between the device and your app.
Core Bluetooth should wake up your app from the OS if registered. Once awake, it's running in the background like normal. You have up to 3 minutes to perform whatever tasks you need to.

IOS: Can I periodically scan for dynamically changing BLE advertisement records in background?

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.

Resources