How to BLE device will invoke the app, when app has terminated - ios

I have a one BLE Device(Peripheral) and iOS Application which communicate to each other using CoreBluetooth.framework( connect, disconnect, subscribe, notify services). Here are the few scenario:
The app is foreground -> I am very easily connected with BLE device.
The app is in the background -> I get the callback and connect with the BLE device
The app is removed from the background (Kill the app) -> I am not getting any callback even I connect the device from iPhone Device-> Settings-> Bluetooth on -> Select Ble Device -> Connect.
I google and get State Preservation and Restoration will be invoked the app. After deep drive :
This also showing App Force Quit by the user , app will not relaunch or active using state preservation and restoration.
I read from this, this and this, have some points :
"If you need to execute code when your app isn’t running, there are several options open to you depending on what you’re trying to do.
- Background fetch will let your app run in the background for about 30 seconds at scheduled intervals. The goal of this is to fetch data and prepare your UI for when the app runs next.
- Push notifications let your app fetch fresh data from your server. You can make a message appear on the device if you want, but it’s not required – silent push notifications let you skip that part.
- Local notifications let you display an alert to the user, along with any media attachments you want and some options for the user to select from. If they choose those options then your app can be launched in the foreground or background to handle them."
I tried with Background Fetch, but it's also not awake when the application has been terminated.
My single objective to achieve is "When the application has terminated or killed by the user, Whenever BLE Device is connected the app should be invoked in foreground/background so that I will perform some operation like get the data from BLE Device and save it"
Using background modes in a project:
Other BackgroundModes also not gives any clue:
How can achieve this without using push notification or silent notification?
if anything in CoreBluetooth framework where the application awake after the termination, let me know?

The short answer is, you can't.
The documentation clearly states that your app will not be relaunched when it is explicitly killed by the user.
This is true for silent notifications as well - these will not wake your app up if the user had forced terminated your app (or the device battery state is below 20%, btw).
Your options for this are limited, and may include advising the user not to force kill your app, or using location based region detection to re-launch your app.
One of the tutorials you've linked shows an iBeacon example to detect going in and out of range of iBeacons, and when combined with background permission can relaunch your app, but again - this isn't explicitly what you've asked for and is not a real solution to the problem you describe.
Apple's logic is simple - if the user kills your app, the user doesn't want it to run again, which makes allot of sense.
The thing is, many users think that killing apps is the standard way to make their device more responsive, there's a big debate on this (what's worse? having the OS cold start apps or allowing apps to do funny stuff in the background with silent notifications, etc.) I won't go into that debate, that's just the way it is.

This is Abstract code to highlight the solution. You might need to tweak few things.
1> Create CLBeaconRegion with UUID start monitoring for that beacon
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
if let uuid = UUID(uuidString: "B9407F30-F5F8-466E-AFF9-25556B57FE6D") {
let beaconRegion = CLBeaconRegion(proximityUUID: uuid,identifier:"iBeacon")
beaconRegion.notifyOnExit = true
beaconRegion.notifyOnEntry = true
locationManager.startMonitoring(for: beaconRegion)
}
2> As per the document
If you begin monitoring a region and your app is subsequently
terminated, the system automatically relaunches it into the background
if the region boundary is crossed
Reference
3> Your peripheral should transmit as ibeacon who transmit same UUID (Same UUID for which you have created CLBeaconRegion)
You might need to play with few parameters of CLLocationManager and CLBeaconRegion but this should work in my opinion because in the past my apps have been successfully woken up from terminated state on iBeacon detection ....

Related

wake up app after terminate

i want to wake up my app after app terminated using background modes...
i know using location update and push notifications we can do.but i don't to use those. apart from those is their any way to wakeup my app.
actually i need to connect my app with websocket even app was terminated.
is their any way to wakeup app using core motions. or using microphone(i mean if app catches any data of voice(sound))..
can any one explain app life cycle (when it will wakeup and when it will sleep)
thanks u
Even if there is a way (actually there are some tricks with beacons but user would have to be in the range of beacon specified by you) it shouldn't be used like so.
If your app is kind of weather service or newsfeed, iOS device will be woken up at intervals specified by you (not less than 1h) to check for necessary data.
Using microphone or core motion to wake up your app probably won't pass apple review.
To fully answer your question I would have to know reason for background mode.
According to your requirement "i need to track device motion activity", you could use the queryActivityStarting() provided by apple API's.
This gathers and returns historical motion data for the specified time period:
let activityManager = CMMotionActivityManager()
activityManager.queryActivityStarting(from: lastTimeAppCollectedData, to: now, to: queue) { (activities, error) in}
This returns you an array of activities/error that happened in the given period
It still wont wake your app up, but will allow you to query the events after they happened.
You can use CLRegion for geofencing as soon as user exit the region boundary, your app will get open with didExit delegate of CLRegion and after that you can use startActivityUpdates of CMMotionActivityManager to keep your app open till you want.
Resources:
Region Monitoring
No once app is terminated you don't have any access to app until app is opened by user. Even location update and push notifications only work in background.

CoreBluetooth background execution 10sec?

Because the apple doc is quite vague concerning this point :
Upon being woken up, an app has around 10 seconds to complete a task
Does this mean that after 10 sec the app will go back to its "suspended" state ? Theoretically, is it possible to "force" the app to stay awake after these 10 sec ? (private app).
In my case the device would be connected to a car.
Does this mean that after 10 sec the app will go back to its
"suspended" state ?
If you read carefully :
Upon being woken up, the app has around 10 seconds to process the
data. Ideally, it should process the data as fast as possible and
allow itself to be suspended again. However, if more time is needed,
the app can use the beginBackgroundTaskWithExpirationHandler: method
to request additional time; it should do so only when absolutely
necessary, though.
Apps generally awake by Background modes(like location service, audio, push notification and so on) and for some modes like location service it will stay awake until the location data is being captured and for some, it doesn't stay awake for much time like push notification. So it depends on the task that is being performed. For Bluetooth, if it's connected with another Bluetooth device then it will stay awake.
Theoretically, is it possible to "force" the app to stay awake after
these 10 sec ? (private app).
Yes, it's possible.
Each of the preceding modes lets the system know that your app should
be woken up or launched at appropriate times to respond to relevant
events. For example, an app that begins playing music and then moves
to the background still needs execution time to fill the audio output
buffers. Enabling the Audio mode tells the system frameworks that they
should continue to make the necessary callbacks to the app at
appropriate intervals. If the app does not select this mode, any audio
being played or recorded by the app stops when the app moves to the
background.
Note : If you need it for your private app then you can check this here. Your app will be rejected if you add the solution and apply for appstore.
In XCode, go to your project->Capabilities->Background Modes and mark the Background Modes to On. Mark also Uses Bluetooth LE accessories:
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. You enable
support for using bluetooth accessories from the Background modes
section of the Capabilities tab in your Xcode project. (You can also
enable this support by including the UIBackgroundModes key with the
bluetooth-central value in your app’s Info.plist file.) When you
enable this mode, 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.
For more detail you can refer Apple documentation.
Try this:
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];

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.

Receive signal from beacon while app is in the background

I have a iOS app that interact with a beacon.
Also have a function to detect the signal from a beacon and if the signal is out of range I want to store something in the database (in this case core data)
func updateDistance(distance: CLProximity) {
UIView.animateWithDuration(1.0) { [unowned self] in
switch distance {
case .Unknown:
self.view.backgroundColor = UIColor.grayColor()
self.distanceReading.text = "No Beacon Signal Detected"
updateDatabaseWithLocation()
}
}
}
So the app works fine as long as the app is running in foreground.
My understanding is I can also have the app in the background when user not actively using the app and still get signal from beacon.
If so, how can I accomplish this task? I added the following to info.plist and still didn't work.Also is it possible to update the database as well?
You can only range beacons (which is what gives you access to the distance approximations) when the app is running. As soon you leave the app (press the home button, navigate to another app, etc.), iOS will suspend the app, and ranging will stop working. Continuous usage of Bluetooth radio in the background would drain the smartphone's battery quickly.
You can, however, have your app subscribe to be woken up into the background when the smartphone enters and exits range of a beacon (or a group of beacons). This is called region monitoring, and it's the same mechanism that geofencing uses.
Now, "enter" and "exit" events in and on themselves won't give you access to distance approximations. However, since iOS will wake your app into the background for a few seconds to handle these events, ranging will actually resume for the duration (assuming you haven't stopped it before the app got suspended), before iOS puts the app back to sleep again.
You can even extend the "few seconds" into up to a few minutes with a background execution task.
All of the above doesn't require the use of background modes—only the "always" authorization to use Location Services.
You can't ordinarily keep the app running in the background indefinitely with beacons. Background support is heavily regulated by Apple, and is only allowed, e.g., for navigation apps, or music apps. People do on occasion try using the "location" background mode to keep the app alive in the background (and thus capable of ranging beacons), and some even reported being able to get it past the review process, but that seems to be more of an exception than a rule.
Should you decide to give it a try anyway, you need to:
enable the "location" background mode,
set allowsBackgroundLocationUpdates to true on your CLLocationManager instance,
start regular location updates: startUpdatingLocation.
This should keep the app running in the background even if you leave it.

How to wake up iOS app with bluetooth signal (BLE)

When using the BLE with CoreBluetooth (no iBeacon), is there a way to wake an app that is not running when the device receives a Bluetooth signal?
I'm simulating a beacon with the RedBearlab's BLE Shield (http://redbearlab.com/bleshield/).
Thanks,
DAN
* UPDATE 03/05/14 *
It looks like Apple has introduced a major update with iOS 7.1: now iOS will open your app for you if it detects a UUID that matches your app. The app only needs to be installed, it doesn't have to be running (logic in AppDelegate needed to answer the wake-up call).
If the app was running in the background and then closed (I mean here terminated - and you do not see it anymore in the list of background apps when you double click the home button) due to memory pressure from other apps, then the iOS will take care of waking it up again when a delegate is called (assuming you have background modes listed in .plist).
If the app was running in the background and then closed by the user (again I mean here terminated. So the user double clicked to get the list of apps running in the background and then clicked on your app in the background list until it wiggled and then pressed the 'x' next to the app to kill it) then this is a clear indication that the user does not want the app running in the background and the app will not be re-launched. The user has to relaunch the app for its delegates to start functioning again in the background (new in iOS7).
Update:
I am not sure if this is in the documentation but it is in CoreBluetooth WWDC 2013 Video. I recommend you watch it. They spent a good portion of the video on how CoreBluetooth behaves in the background.
From what I understand, if your app has not previously connected with the BLE Peripheral, then no.
If your app has previously connected with the BLE Peripheral, then use:
-connectPeripheral:options
Connection requests don't time out. The best place to call this method is when your app loses connectivity with the BLE peripheral. You will get notified when you lose connection to the peripheral in the CBCentralManagerDelegate Protocol:
-centralManager: didDisconnectPeripheral: error
So the next time your App comes in range of the BLE Peripheral, it will trigger this method. Also note that you will need to set up State Preservation and Restoration when you initialize a CBCentralManager.
https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html
the system wakes up your app when any of the CBCentralManagerDelegate or CBPeripheralDelegate delegate methods are
invoked, allowing your app to handle important central role events,
such as when a connection is established or torn down, when a
peripheral sends updated characteristic values, and when a central
manager’s state changes.
To perform certain peripheral role tasks while in the background, you
must include the UIBackgroundModes key with the bluetooth-peripheral
value in your app’s Info.plist file. When this key-value pair is
included in the app’s Info.plist file, the system wakes up your app to
process read, write, and subscription events.
You could try to declare voip in info.plist. For the time being, my application was automatically relaunched after a time, even user terminated it.

Resources