iPad app become inactive after locking screen - ios

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

Related

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

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.

Is there anyway to check when an app will be suspended?

Is there a universal time of iOS app suspension time (i.e when it goes out of background mode and terminates).
Background
The app is in the background and executing code. Most apps enter this
state briefly on their way to being suspended. However, an app that
requests extra execution time may remain in this state for a period of
time. In addition, an app being launched directly into the background
enters this state instead of the inactive state. For information about
how to execute code while in the background, see Background Execution.
Suspended
The app is in the background but is not executing code. The system
moves apps to this state automatically and does not notify them before
doing so. While suspended, an app remains in memory but does not
execute any code. When a low-memory condition occurs, the system may
purge suspended apps without notice to make more space for the
foreground app.
No, there is not any possibility to know about that, according to this:
Suspended: ...The system moves apps to this state automatically and does not notify them before doing so...
Link: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html

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.

App restarts when woken from background

G'day iOS Guru's,
I have searched extensively for an answer, but can't find one (I bet the first response to my question will be to another similar question, but I cant find it).
Anyway, my problem is that I am running a simple map app that the user can drop pins on the map with a customised circle overlay around the dropped pin.
When the app goes into the background (iphone locked or home button pressed), if I re-enter the app within ~ 5 mins, the pins are still there and the app reopens to the last screen.
All good.
However, if I leave the app in the background for longer than 5 mins, the app restarts and all the pins are lost.
I have "Application does not run in background = NO" in the plist, and also enabled "App registers for location updates" under Required background modes.
How can I prevent the app from restarting after it enters the background and load the last opened view?
iOS can, and will, terminate your app while it's in the background if it needs additional resources to carry out whatever's going on in the foreground.
You need to ensure that your data is saved/archived when your app is terminated, and unpacked when re-launched so as to go back to where the user last was. The traditional way to do this is to use the applicationDidEnterBackground method, which is called when your app is suspended. You can then save all the data you need in order to resume cleanly in case your app is later terminated.
However, if you're targeting iOS 6 and upwards you can take advantage of a new feature - State Presumption & Restoration (link to documentation). State restoration off-loads some (but not all) of the heavy lifting onto iOS, and it can automatically snapshot your UI and provides easier ways to preserve and restore data.
in your AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
// Save your data
}

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?

Resources