iOS: how to detect when the UIApplicationDelegate state becomes "suspended"? - ios

How can we detect when an iOS App has been suspended?
There is no method that mentions this in the official UIApplicationDelegate documentation.
These are the states that an App can have:
(source: apple.com)
Use case:
I want to log when an app stops running subsequently to being woken up due a location event. For example I have got an iBeacon that the app is montioring. I activate the iBeacon and the app gets launched successfuly in background (for 10 seconds). I would like to detect when the App stops running after these 10 seconds have elapsed. However there is no AppDelegate method that seem to allow to intercept this (please consider that I am investigate this specific case.
Previous question:
I had asked a previous similar question which did not get answered. Please find it here.

While I am unaware of any callback, you can query for the amount of background time remaining with:
NSLog(#"background time remaining: %8.2f", [UIApplication sharedApplication].backgroundTimeRemaining);
Theoretically, you can put this in a thread and execute custom code a second or so before your app terminates. See my blog post here for more info:
http://developer.radiusnetworks.com/2014/11/13/extending-background-ranging-on-ios.html

I think you won't get any feedback form Suspended state. Suspended means that app is in memory but no code is executing right now.
Documentation:
The app is in memory but is not executing code. The system suspends apps that are in the background and do not have any pending tasks to complete. The system may purge suspended apps at any time without waking them up to make room for other apps.
So in my understanding, if an app would give you a callback with something like applicationDidEnterSuspendedState it will be a paradox, cause Suspended state means that no code is executed.

Related

applicationWillTerminate vs. applicationWillResignActive vs. applicationDidEnterBackground? When are they triggered exactly? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I know there exists a similar question but I think that question is a lot more general and does not answer on the specific details that I'm trying to find out.
I've read the Apple documents, but still I'm a bit confused on when exactly these methods are triggered. From the Apple documents, it seems there are the following state transitions that are possible for an iOS app:
App terminated in the foreground (for example double tap the Home button and swipe up the app): pretty sure applicationWillTerminate is triggered in this case, actually this is the only case that I'm not too confused about.
App switched to the background while still running in the background (for "apps that support background execution" to quote Apple documents): applicationDidEnterBackground is triggered? applicationWillResignActive is triggered or not?
Background running App gets terminated: applicationWillTerminate may(?) be triggered according to the Apple documents... so it may or may not be triggered at times?
App switched to the background and immediately suspended: applicationDidEnterBackground and applicationWillResignActive are both triggered?
Background running App gets suspended: applicationWillResignActive is triggered? Or nothing gets triggered?
App that "does not support background execution" gets switched to the background: applicationWillTerminate gets triggered according to Apple documents? But what exactly does this actually talk about?
App crashes in the foreground: nothing gets triggered in this case I guess?
Background running App crashes: also nothing gets triggered in this case right?
Background suspended App gets terminated: Again nothing gets triggered I guess?
I think the Apple documents are either somewhat vague or downright confusing in explaining those methods. Sometimes they talk about "apps that support background execution" vs. "apps that do not support background execution", sometimes they talk about "running in the background" vs. "suspended", sometimes they just say things like "the user quits the app and it begins the transition to the background state" or "incoming phone call or SMS message", which are real-world use-cases instead of technical concepts.
So anyone can help explain in more consistent technical terms that when exactly are those methods triggered in specific cases?
EDIT: Not sure why this question is deemed not "focused", as I'm trying to make use of those application delegate methods but after both some personal testing and reading official documents, I'm still at a loss when exactly those methods will be triggered and how may I use them reliably.
Maybe I can elaborate more by borrowing some stuff from PGDev's answer, so there are 5 states an iOS app can be in if I understand correctly:
Not running
Inactive
Active
Suspend
Background
And when the app changes state, some delegate methods may be triggered, but so far from the official Apple documents, it seems very confusing which methods will be triggered during which state transition.
For example I'm not sure what or if any method will be triggered when app goes from state 5 to state 4, and when app goes from state 5 to state 1, and when app goes from state 4 to state 1. Also from the official Apple documents it seems to say that applicationWillTerminate will be triggered if "apps that do not support background execution" are switched to the background, however I have not been able to get any kind of app to trigger applicationWillTerminate by just pressing the Home button.
As it currently stands, I'm not sure if I can reliably utilize those methods to do anything, that's why I hope someone can give a clearer picture on when exactly those methods will be triggered (and not triggered) apart from those vague descriptions in the official Apple documents.
Here is the detailed explanation of how the App Lifecycle methods work.
There exist 5 states in the the lifecycle of the app,
Not running — The app is not running.
Inactive — running in foreground + not receiving events
An iOS app can be placed into an inactive state, for example, when a call or SMS message is received.(Foreground + Not Running)
Active — running in foreground + receiving events
Suspend — running in background + not executing code
Background — running in background + executing code
Next there exist 7 delegate methods that are called whenever the above states are changed in the app's session.
Launch time
application:willFinishLaunchingWithOptions
Method called when the launch process is initiated.
This is the first opportunity to execute any code within the app.
launch process has begun but that state restoration has not yet occurred.
didFinishLaunchingWithOptions
Method called when the launch process is almost done and the app is almost ready to run. Final initialization.
Transitioning to the foreground
applicationDidBecomeActive
app has become active.
Transitioning to the background
applicationDidEnterBackground
This method is called when an iOS app is running, but no longer in the foreground
Transitioning to the inactive state:
applicationWillResignActive
exit from active state to another state
Each time a temporary event, such as a phone call, happens this method gets called
called when app moves to background
applicationWillEnterForeground
about to enter from background -> foreground
Termination
applicationWillTerminate
app is about to terminate.
Force quitting the iOS app, or shutting down the device
This is the opportunity to save the application configuration, settings, and user preferences.
Some flow examples of the order in which the above methods will be called.
Launch app — 1, 2, 3 — willLaunch + didLaunch + didBecomeActive
Press home — 5, 4 — resignActive + didEnterBackground
Open app from background — 6, 3 — willEnterForeground + didBecomeActive
Open task manager — 5 — resignActive
Phone call comes when app in foreground — 5 — resignActive
You can test the execution of the lfecycle methods using the above examples.

What are the different options for running code at a specified time in iOS?

What are the different options for running code on an iOS device at a specified time while the app is in the background? So far I have found that I could possibly use a Timer object, use the Grand Central Dispatch timer, and use CloudKit Push Notification with the Apple Push Notification service.
Any ideas are welcome. I'm having a hard time finding the solution.
Here is the apple documentation for background execution.
Here is the apple documentation for the execution states of an application.
You should understand a few things:
When an app moves into the background you have a very small amount of time (3 minutes approximately) to execute finite-length tasks.
If your application is not running, you could use a notification to wake the application. This requires the user to take an action and will make the application active.
You can also wake an application with a local notification, it doesn't have to be a remote notification.
The code that you want to run really needs to fall into one of the blessed scenarios that apple defines otherwise you run the risk of being deprioritized or ignored entirely.
A block of code scheduled to run with a Timer or GCD will not be invoked while the application is in the background.
Roughly, you should register a background execution mode and follow the guidelines I linked above and while your application is backgrounded the application will be given time to execute code.

Reasons why iOS will terminate an app

We have a GPS tracking type iOS app which runs in the background. We are seeing infrequent cases where the app appears to be getting terminated with the applicationWillTerminate method being called while the tracking process is taking place.
We have more or less ruled out low RAM as the reasons. Also definitely not a battery level issue or users terminating the app.
Any suggestions what would be the next most likely causes for iOS to terminate the app?
Some thoughts we had were CPU usage, phone temperature level or simply because the app is running in the background for extended periods (e.g. days or weeks).
Are any of these likely or even possible causes for iOS to terminate the app?
From Apple's Background Execution docs:
Do minimal work while running in the background. The execution time
given to background apps is more constrained than the amount of time
given to the foreground app. Apps that spend too much time executing
in the background can be throttled back by the system or terminated.
Also, I assume you've verified you're not running afoul of the below (from the same doc):
Each call to the beginBackgroundTaskWithName:expirationHandler: or
beginBackgroundTaskWithExpirationHandler: method generates a unique
token to associate with the corresponding task. When your app
completes a task, it must call the endBackgroundTask: method with the
corresponding token to let the system know that the task is complete.
Failure to call the endBackgroundTask: method for a background task
will result in the termination of your app.

How to get location updates in iOS even if the app is in terminated state or is killed? [duplicate]

This question already has answers here:
IOS Getting location updates when app terminated without using significantChange
(2 answers)
Closed 5 years ago.
I searched a lot for one week. I searched google for the same question and I was able to get something working. But location updates don't work for the suspended state. It only works for foreground and background states.
And I need location updates after terminated state also.
Please refer to applicationWillTerminate
By Apple documentation it says:
This method lets your app know that it is about to be terminated and
purged from memory entirely. You should use this method to perform any
final clean-up tasks for your app, such as freeing shared resources,
saving user data, and invalidating timers. Your implementation of this
method has approximately five seconds to perform any tasks and return.
If the method does not return before time expires, the system may kill
the process altogether. For apps that do not support background
execution or are linked against iOS 3.x or earlier, this method is
always called when the user quits the app. For apps that support
background execution, this method is generally not called when the
user quits the app because the app simply moves to the background in
that case. However, this method may be called in situations where the
app is running in the background (not suspended) and the system needs
to terminate it for some reason. After calling this method, the app
also posts a UIApplicationWillTerminate notification to give
interested objects a chance to respond to the transition.
If you want to have user's location when app is not in memory, short answer: Impossible.

NSURLsession background transfer service for download task, can it work even when App is suspended?

Before asking a question, let me clarify what I understand about iOS App states:
Backgrounded: In this state, your app is not in the foreground anymore but it is still able to run code.
Suspended: Your app enters this state when it’s no longer able to run code.
Now, I wanted to keep downloading going on when App is in background, i.e. it still does exist in multitasking screen. It is working as expected with background transfer service.
But, in some tutorial reference, I have read that you can perform downloading even when App is Backgrounded / Suspended. Can it work even when my App is suspended, i.e. removed from multitasking screen ?
I have been reading many documents including Apple class reference regarding background transfer service with download task, but no one clarifies that the download will not work when App is suspended (killed).
Appreciate your thoughts and advices !!!
If your app has been suspended by the system (without force quiting from multitasking screen) your background session will continue to work.
If you force quit the application all download tasks will be canceled.
The following is from backgroundSessionConfigurationWithIdentifier(_:) documentation :
If an iOS app is terminated by the system and relaunched, the app can use the same identifier to create a new configuration object and session and retrieve the status of transfers that were in progress at the time of termination. This behavior applies only for normal termination of the app by the system. If the user terminates the app from the multitasking screen, the system cancels all of the session’s background transfers. In addition, the system does not automatically relaunch apps that were force quit by the user. The user must explicitly relaunch the app before transfers can begin again.
Apps displayed in the multitasking UI aren’t necessarily executing code or fetching data. Listed apps may be suspended or not running at all
[[UIApplication sharedApplication] applicationState] will check your application state, you can test your app.
NSURLSession class can hand off downloads and uploads to the operating system when the app becomes inactive. As with almost all background execution APIs, if the user force quits from the multitasking UI, the background operation will terminate
In iOS 7, Apple added support for background fetch—a kind of smart, per-app crontab that wakes up at opportunistic times. There is no way to force background fetches to execute at exact intervals. iOS checks how much data and battery power was used during previous background fetches when scheduling future callbacks.
Background fetches can also be triggered by remote push notification and have a very similar delegate method with the same completion handler.
Full Tutorial is here
https://blog.newrelic.com/2016/01/13/ios9-background-execution/

Resources