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.
Related
I’m putting an app into background.
Assuming that I’m not doing anything to keep the app alive in the background, then the app goes through suspended state in a matter of 5 seconds. Right?
What happens if I then tap on the app icon? That’s not suppose to trigger a didFinishLaunch right? It will just bring me back to the last screen I was at and also trigger didbecomeActive & willenterforeground notifications. I won't be getting any other callback. Right?
Assuming there is no restart of the phone, point 2 is true even if there are hours between me tapping home and then tapping back the app icon. Right? Does it also persist device restarts but not force-restart?
The only time I won’t be brought back to the screen I was at (before hitting home) is if the device receives a memory warning and my app is flushed out of suspended state. At this point tapping on the app icon will result in didFinishLaunch. Right?
(I’m asking all of this because sometimes after putting the app in the background and tapping the app icon again (e.g. 10 minutes later), the app is going through it’s launch phase. Most of the time it just goes back to its previous screen)
I've already seen Will ios terminate the app running in background after a specific time? but that doesn't address all aspects I want.
It will just bring me back to the last screen I was at and also trigger didbecomeActive & willenterforeground notifications.
Right, if your app was not terminated in the background.
I won't be getting any other callback.
Not necessarily true. If you were summoned to the front by a local notification, for example, you'll also get an event about that.
Assuming there is no restart of the phone, point 2 is true even if there are hours between me tapping home and then tapping back the app icon.
Not necessarily. The app might well be terminated silently in the background.
Does it also persist device restarts but not force-restart?
Absolutely not. How can the app run when the device is off? Shutting down the app terminates every app.
I’m asking all of this because sometimes after putting the app in the background and tapping the app icon again (e.g. 10 minutes later), the app is going through it’s launch phase
It's not a matter of time. The watchdog process is constantly combing the suspended apps looking for the ones that take up too much memory so that other apps can run. You must not be surprised if yours is one of them.
You can come back to the front launching from scratch or by coming back to life from suspension; it's the most basic fact of iOS app life! You just need to accept it.
But there are lots of things you can do to reduce your chances of being terminated in the background. Giving up memory-consuming objects as you background is first on the list.
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
My app needs the device location with an accuracy of about 10 meters. If the app is launched, it usually takes e.g. 10 sec to get the required accuracy. This delay is OK. However when the app is „in use“ (see below), the delay should be less, e.g. 1 sec.
The problem is the following:
When the user switches off the display, the app transits from the active state to the background state (and the delegate methods applicationWillResignActive and applicationDidEnterBackground are called).
Normally, location updates are not done in background. So, next time the app transits from background to active state (delegate methods applicationWillEnterForeground and applicationDidBecomeActive are called), the location manager needs again e.g. 10 sec to reach the required accuracy. This delay in unfortunately not OK.
To avoid it, the app could do location updates in the background. This works fine.
The disadvantage is that these background location updates continue, even if the app is no longer used, because the user pressed the home button and switched to another app. This is disturbing at least for 2 reasons: The GPS hardware is unnecessarily active and uses power, and the user is notified that my app is using the device location although this is no longer required.
My question thus is:
Is it possible to determine if another app becomes active?
If so, background location updates could be switched off.
Is it possible to determine if another app becomes active?
No, your app only knows if it's in background or in foreground handling delegate events. Know if user opened another app or is in the home screen is not possible.
These background location updates continue, even if the app is no longer used, because the user pressed the home button and switched to another app.
I think you're right. You could start a timer when application goes in background and update localization only for an estabilished period (one minute?). Then, at the end of timer count save last localization coordinates. Timer is used to avoid unnecessary updates, then if user doesn't open again your app after a reasonable time, maybe it's because he's using other apps or he locked the device.
When the app comes to the foreground again, if timer is still active you're good. Otherwise show last localization saved and show a small "banner" to advise user that localization could not be accurated for the first 10 seconds (until when required accuracy has been reached)
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?
What delegate is called in this situation if I have an app running.
Over time, if iPad is set to lock after 2 mins, what is its state? Does the app still run? or does it suspend?
I'd like to know thanks
If the iOS device automatically locks after a period of inactivity, the same thing happens as when it's locked by pressing the lock button: the app briefly goes into the background before being suspended. (Unless of course it is an audio-playing app or other app that requests extra execution time, in which case it may stay in the background longer, or indefinitely, without being suspended).
In terms of UIApplicationDelegate methods, applicationWillResignActive: will be called first, followed by applicationDidEnterBackground:.