CoreBluetooth background execution 10sec? - ios

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];

Related

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.

Background Bluetooth with iOS device

I am working on developing a bluetooth peripheral to work with my iOS device. I need to make the iOS app receive data whilst it's in background and process that data as it comes. Looking through Apple's CoreBluetooth framework, I can see how the background execution modes can be used. Now to save power, I want the iOS device to only connect to the bluetooth peripheral at a certain time (without need of user interaction). I've looked through Local Notifications on iOS and it has very limited functionality and don't think it provides what I need.
So is there anyway to wake up an app at 6pm and ask the application to start scanning for bluetooth devices? And then execute other code once device is connected? All this without user interaction.
Any suggestions would be appreciated!
Thanks!
You can't really schedule operations to occur at a specific time in iOS (aside from local notification, which as you said isn't what you need).
You can use background fetch mode to periodically allow your app to check for new data. You can set an interval (although this is only a guideline to iOS, not a strict schedule) for how often your app is woken.
When iOS calls your app delegate performFetchWithCompletionHandler method you can check the current time and decide whether you want to transfer data. If not then you can quickly return UIBackgroundFetchResultNoData. If you do get new data then you can retrieve it before returning UIBackgroundFetchResultNewData

is iOS background mode needed if app works when suspended?

I need my iPhone app to do some tasks in the background when it's suspended, but I don't need to do any tasks after it's turned off. Do I need to settle UIBackgroundMode?
Yes, to execute code continuously in the background state, you need to register for a given UIBackgroundMode.
See here or here for a good source on this.
However if you just wish to perform a single background task (task completion), you don't need a background mode.
In response to your comment below, I will try to be clear:
In iOS, even in iOS 7, it's not possible to run arbitrary code when your application is in a background state indefinitely.
In simple English, - you can't just run any code you like in the background for as long as you like.
There are rules.
These rules have been relaxed somewhat in iOS 7, but it's still not totally unrestricted.
Consider your situation: You have a timer that wants to call a method on a continuous basis.
Now consider the UIBackgroundModes available (which allow you to run in the background in various situations):
audio - Only for audio based apps.
location - Only if you app is location aware, does specific location tasks
voip - VOIP (Skype etc)
fetch (Background fetch - a new iOS 7 API where the system gives you application moments to grab new content when it sees fit.
remote-notification - new in iOS 7, when the device receives a remote push notification with a certain payload, it will resume and execute a certain block of code.
newsstand-content - Only for newsstand apps
external-accessory - Only for external accessories to communicate with the device
bluetooth-peripheral Only for external BT accessories to communicate with the device (fitbit)
As you can see if you don't fall into one of these categories you can't use these modes.
If you misuse the modes Apple won't approve your application.
Finally we have 'Background task completion'
This is a way to use a UIBackgroundTask to execute any code you want in the background! Including timers that call methods! - One problem though...
This is supposed to be for 'task completion' (Facebook uploads that aren't complete, saving or processing data that should be done before the app suspends even though the user pressed the home button).
Sounds good, but you can only run in the background using this method for a maximum of 10 minutes. If you go over this time limit iOS will immediately kill your application.
So as you can see, there is no way for your application to be approved on the store and constantly run in the background with a timer that calls your method.
Sorry about that.
If you want to learn more check this out.
Use the location service and set NO location manager "pausesLocationUpdatesAutomatically" property.

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.

Implementing Long-Running Background Tasks in iOS

my client asks me to develop some app that periodically retrieves the user location & the phone battery status, and then send them to our backend server for data analysis, then feed back by push notification.
But through the app doc, I get to know that from apple ios dev doc:
For tasks that require more execution time to implement, you must
request specific permissions to run them in the background without
their being suspended. In iOS, only specific app types are allowed to
run in the background:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that keep users informed of their
location at all times, such as a navigation app
Apps that support
Voice over Internet Protocol (VoIP)
Newsstand apps that need to
download and process new content
Apps that receive regular updates
from external accessories
I'm wonder if this would be feasible if we wrap this app as some navigation app so we can have long-running background tasks? Does appstore will reject on our app?
BTW, what is the definition of navigation app by Apple?
You might consider using:
[CLLocationManager startMonitoringSignificantLocationChanges];
This will cause your app to be restarted if it has been killed whenever the location changes significantly, allowing you to update the details on the server at fairly regular intervals, assuming the user is moving. This does not require any special background permission. From the docs:
If you start this service and your application is subsequently terminated, the system automatically relaunches the application into the background if a new event arrives. In such a case, the options dictionary passed to the locationManager:didUpdateLocations: method of your application delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your application was launched because of a location event.
Your other option is to configure the app as requiring continuous location updates in the background, but without knowing the primary function of the app it is hard to know if this will pass store submission or not.
https://github.com/yarodevuci/backgroundTask Check my code here I am using audio player that plays blank wav file Works perfectly on IOS 8 Battery usage around 10% in 24 hour period How to use:
var backgroundTask = BackgroundTask()
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background.
backgroundTask.stopBackgroundTask() //Stops the task

Resources