iOS Background Task does not remain alive if launched when phone is locked (screen off) - ios

I have an iOS application which interacts with BLE devices. The Bluetooth LE accessories background mode is active so that the application is able to connect and interact with BLE devices even when it's put in the background.
When a BLE device is connected, the application executes code in background responding to BLE-related callbacks, but after the BLE device disconnects the application can't run code in background anymore (the application remains alive only for a few seconds after BLE device disconnection).
What I need is a way to perform a finite-length task (1-2 min duration roughly) after the BLE device disconnects.
Reading Apple Documentation I tried using the beginBackgroundTaskWithExpirationHandler: method. Calling this method, the application should request some additional execution time (roughly 3 minutes).
Calling either of these methods delays the suspension of your app temporarily, giving it a little extra time to finish its work.
I tried to register the background task by calling the beginBackgroundTaskWithExpirationHandler responding to the BLE disconnection callback and I found out a strange behavior which depends on wether the phone is locked or not when the beginBackgroundTaskWithExpirationHandler is called:
If the phone is not locked (i.e., screen is on, app can be both visibile or in background) when beginBackgroundTaskWithExpirationHandler is called, the background task works as expected and remains alive for roughly 3 minutes when the application is later put in background and the screen is turned off.
If the phone is locked (screen off) when beginBackgroundTaskWithExpirationHandler is called, the background task do not remain active in background while the screen is off and it's somehow resumed when the screen is turned on again
(I tried with iPhone 6, iPhone 8 Plus, iPhone 5s all with iOS 12.1.4)
The approach I'm using is very similar to that described here, I also found here another similar problem.
Is that the intended behavior for background tasks? Do the OS suspend a background task if launched when the phone is in locked state?
Is there another way to start a finite-length task, with 1-2 minutes duration, from a callback which is triggered when the app is in background and the phone is locked?
Thank you in advance,

According to :
application(_:performFetchWithCompletionHandler:)
When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. In practice, your app should call the completion handler block as soon as possible after downloading the needed data. If you do not call the completion handler in time, your app is terminated. More importantly, the system uses the elapsed time to calculate power usage and data costs for your app’s background downloads. If your app takes a long time to call the completion handler, it may be given fewer future opportunities to fetch data in the future.
So you have 30 seconds to finish any task you need in background.

Related

IOS: Detecting lock after the app has entered background?

Is there a way to detect lock after the app has entered background? For example,
I have my app (A) open at the foreground
Then I bring another app (B) to the foreground
Then lock the screen
Is it possible for (A) to detect the lock?
The answer is "In theory yes, but usually not."
Apps actually have more states than active and background.
The states are:
Active
Background (still running, but another app is in the foreground)
Suspended (in memory, but not getting any CPU time)
Not running. (no longer running or in memory.)
When the user swaps apps, presses the home button, or locks their device, your app gets notified that it is going into the background, but it actually only runs in the background for a VERY short time. It transitions to suspended almost immediately. Once you're suspended, you can be terminated at any time without further notice.
If you need more time to finish a task when you get notified that you are being moved to the background, you can ask for it using the beginBackgroundTaskWithExpirationHandler call. However, as of this writing you get at most 3 minutes, and then your expiration handler fires and your app is suspended.
As a result of this, you don't actually get to run in the background for very long and it's likely that by the time the user locks the screen (or it locks automatically) you are already suspended and don't get notified.
Is it possible for (A) to detect the lock?
No, for two reasons:
You cannot detect, under any circumstances, that the screen has been locked. Even if your app is frontmost when the screen is locked, all you learn is that your app was backgrounded, without your being able to learn why.
In your scenario, by the time the screen is locked, your app isn't even running — it has been suspended. So it cannot "detect" anything.

How to continue monitoring iBeacon when screen is off in iOS?

I am developing an iOS app to monitor iBeacons. It works well in both foreground and background. I also need it to keep monitoring even when the screen is off. Now my problem is, when I turn off the screen with the shoulder button, NSLog shows that the iBeacon signal goes off (RSSI=0, beacon.accuracy=-1.0) accordingly, and 10 seconds later, there is no beacon found at all, while the delegate method locationManager:didRangeBeacons:inRegion: is called continuously. It seems that the app is running when the screen is off but iOS turns off the location service for iBeacon ranging. I tried to set "locationManager.pausesLocationUpdatesAutomatically = NO;" but still doesn't work. Is there any advice on this issue? Thanks in advance.
It seems that you're doing ranging instead of monitoring. Ranging only works when the app is active—either in the foreground or in the background. The catch is, iOS will automatically put an app to sleep a few seconds after you navigate away from it, or lock the screen.
What you have to keep in mind is, there's really no such thing as "permanent background state" on iOS. Apps run in the background for some limited time while transitioning to the suspended state (to let them, e.g., finish uploads/downloads), and there are also Background Modes that sometimes enable an app to run in the background, but these are usually reserved for very specific apps—e.g., the "audio" Background Mode means an app can be running in the background as long as it plays music, etc. There is a Background Mode for "location" services, but it's reserved for turn-by-turn navigation apps.
Beacon monitoring however continues running even if your app goes to sleep, or gets terminated by the iOS due to memory pressure. When you go in or out of range of a beacon, iOS will launch your app into the background to handle the event, giving it a few seconds (which you can extend up to a few minutes with a Background Execution Task) to do so (you can range during that time), but then it's back to sleep.
You might also want to take a look at this question:
Receive signal from beacon while app is in the background

iOS long-running background timer with "location" background mode

I want to implement long-running background timer which sends user's location to server periodically.
To do this, I set location mode for UIBackgroundModes, and call beginBackgroundTaskWithExpirationHandler when the application goes to background.
And for CLLocationManager, I use startUpdatingLocation method (don't want to use significant change, because I need high precision location).
But around 26minutes after the app goes to background, it stops to send location to the server. But the app isn't crashed, so after I bring the app to foreground, it can resume its timer.
26minutes is from experiments, with iOS 6.1, iPhone 5.
Here are some questions,
I can't understand why it suspends after 26mins not 10mins, which is known as time limit for background task.
Before 16mins, backgroundTimeRemaining methods returns double max value. But after 16mins, it decreases from 600, so it suspends the background task after 10mins.
I already tried to call beginBackgroundTaskWithExpirationHandler inside of expiration handler, but no use.
If there's anyone who has a clue for this problem, will be greatly appreciated.
https://github.com/voyage11/Location
Use this code.you can set time interval you want to call it. I have tried many codes, but i found this as most accurate and least battery issue.This is also awesome for background location service. :)
if you have set UIBackgroundModes successfully,the App can run a long time in the background while you are moving. But, if you stop moving for over 10 minutes(maybe more), the App will be suspended by the system. Your App will be awake if the location updates,but this awake time will be very short,so you must cal
beginBackgroundTaskWithExpirationHandler method to handle location update.

Keep app running while iOS device locked?

I have an app that makes heavy use of video out. In a typical use-case, I'll have an iPad connected to an external monitor. I just want the external monitor on; the iPad display does not need to stay on.
The ideal case would be for someone to connect to an external monitor, then lock their iPad. But that pauses my app. (Currently, I'm calling setIdleTimerDisabled to keep the iPad from locking up and pausing my app.)
I'd like to give the user the option of locking the iPad, but still having my app running and sending images to video out. (Note: I'm not talking about keeping my app running when it's not in the foreground. I just want to keep it running while it's in the foreground, but the device is locked.)
Is this possible?
I would say no, it is not possible. Here's why:
The docs read:
Pressing the Sleep/Wake button is another type of interruption that causes your app to be deactivated temporarily. When the user presses this button, the system disables touch events, moves the app to the background but sets the value of the app’s applicationState property to UIApplicationStateInactive (as opposed to UIApplicationStateBackground), and finally locks the screen.
Something interesting to note in the docs above is that a bit further down under "What to do when an interruption occurs" Apple recommends that you stop doing certain tasks.
In response to this change, your app should do the following in its applicationWillResignActive: method:
Stop timers and other periodic tasks.
Stop any running metadata queries.
Do not initiate any new tasks.
Pause movie playback (except when playing back over AirPlay).
Enter into a pause state if your app is a game.
Throttle back OpenGL ES frame rates.
Suspend any dispatch queues or operation queues executing non-critical code. (You can continue processing network requests and other time-sensitive background tasks while inactive.)
This tells me that Apple doesn't want or expect your app to be doing much of anything in this state, other than preparing to be fully backgrounded.
On a related note here's a thread that shows how to determine whether you've hit the Sleep/Wake button or not:
Is it possible to distinguish between locking the device and sending an app to background?

iPad app become inactive after locking screen

In my application, I'm downloading and uploading data at some point of time on a separate thread using NSOperation. Both process take approx. 2-3 min. If application remains active then everything works fine. But if the iPad screen is locked (automatically or manually), the app becomes inactive and download/upload get paused and when screen is unlocked after some time process failed with timeout error.
I have "App plays audio" for "Required background modes" in plist file. Do I need to set any other flag for running app while screen is locked?
Please help me what is going wrong.
When the screen is locked, your app becomes inactive. Per "Responding to Interruptions" in iOS App Programming Guide:
Pressing the Sleep/Wake button is another type of interruption that causes your app to be deactivated temporarily. When the user presses this button, the system disables touch events, moves the app to the background but sets the value of the app’s applicationState property to UIApplicationStateInactive (as opposed to UIApplicationStateBackground), and finally locks the screen.
You can get extra time for background tasks according to "Executing a Finite-Length Task in the Background" in the same guide:
Apps that are transitioning to the background can request an extra amount of time to finish any important last-minute tasks. To request background execution time, call the beginBackgroundTaskWithExpirationHandler: method of the UIApplication class. If your app moves to the background while the task is in progress, or if your app was already in the background, this method delays the suspension of your app. This can be important if your app is performing some important task, such as writing user data to disk or downloading an important file from a network server.
You can refer to the document to implement a finite-length download task in the background.
Other references:
Download data in background with iOS4
iOS Application Background Downloading

Resources