App terminates after about 5 mins after the pressing lock button - ios

While my app is in the foreground if a user presses the lock button the app will resign from activity but should still be ready to start again when the user unlocks their phone. After about 5 mins or so my application ends up being terminated and when they unlock their phone they are back on the home screen. Is this expected behaviour? As far as I know I havn't experienced this situation until I started a new project. Am I doing something wrong here or forgetting some sort of setting?

The Operating System can terminate your application at any time to free resources for other processes that may need them or to conserve battery life.
"Apps must be prepared for termination to happen at any time and should not wait to save user data or perform other critical tasks. System-initiated termination is a normal part of an app’s life cycle. The system usually terminates apps so that it can reclaim memory and make room for other apps being launched by the user, but the system may also terminate apps that are misbehaving or not responding to events in a timely manner."
(Source: Apple Developer - "The App Life Cycle")
To minimize the likelihood of this happening to your application, look at what processes are running and do what you can to stop/ pause them while the application is not in the foreground.
Regardless how quickly this happens, it's important to design your application to handle the situation where it may be terminated in the background as this is something that can and will happen. Save state and critical information, such that on next launch the user can continue where he left off.

Related

How do "Suspended" and "Not Running" states look like for the user?

I'm trying to work out the lifecycle of an application, but I can't imagine what some of the states look like.
The program goes into a suspended state when there is no code to run in the background, right? It's still in the background (memory) but can't do anything. Now the question arises, how does it look to the average user? It can still be seen in the app switcher, but will the app restart if I want to open it?
But what happens if that app runs out of memory and goes into the "Not Running" state? Is it still visible in the App Switcher, but will the app restart if I try to open it again? What is the difference in Suspended and Not running state to a user?
Could you help me with this question?
Documentation: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
They don't look different to the user at the time. The app is listed in the app switcher regardless of whether it is suspended or not running. The app switcher makes no distinction between "it is suspended" and "it is not running but it was running recently".
However, if the user taps the app in the app switcher, what happens next is different. If the app was suspended, it simply resumes right where it was when it was suspended. But if the app is not running, it launches from a cold start, the same as if the user had killed the app and then tapped its icon in the springboard.
For some apps, this difference is quite noticeable. Apple's Books app is a good example; if it resumes from suspension, the user is instantly still reading the same page of the same book, but if it launches from a cold start, it does an involved dance that takes quite a long time, passing thru the library and visibly opening that book, to eventually get the user back to the same book and the same page.
Apple has said that ideally you should write your app in such a way that both situations look identical to the user, by saving state when you go into the background so that you can quickly restore that state the next time the app is cold-launched; but as I've just demonstrated, Apple itself does not always meet that goal.
Another goal is to try to prevent the app from being killed while suspended in the first place. You can't prevent the user from killing the app from the app switcher, but you can try at least to discourage the system from killing the app while suspended. You can't guarantee this but you can try, by not using very much memory for instance, to fly under the radar so that the system will let your app live when it is looking for apps to kill in order to free up resources. Apple has an interesting video on this topic (which would have answered your question), https://developer.apple.com/videos/play/wwdc2020/10078/.

iOS Memory App Closure

When putting my app in the background, then running a bunch of other apps one after the other, it will eventually close my app due to phone memory management. This is understandable. My question is, can anything be done to notify the user A) The app closed because of memory and needs to be booted back up. OR B) Have some sort memory watcher to when the phone memory is getting low to alert the user?
Are either of these possible? Are any other options available?
This is understandable
Understandable but not necessary in the short term. You cannot prevent your app from eventually being terminated, but you should be doing everything you can to keep it off the "short list" of apps to be terminated when memory is needed, by shedding memory usage as you go into the background.
can anything be done to notify the user A) The app closed because of memory and needs to be booted back up
No. You cannot "notify the user" when your app has been backgrounded and suspended, because it has been suspended — it isn't running. You can't do anything at all. No code is actually being executed. You are like a frozen corpse. Unlike the corpse, you can be revived and brought back to life, but that is entirely up the user, who must summon you to the front again.
Your job in this respect is to make it, as much as possible, not matter whether or not the app was terminated while in suspension. If you were not terminated, you'll be revived in exactly the state you were in when you went into the background. Well, then see to it that if you are launched from scratch because you were terminated, you also return to the state you were in when you went into the background.

Core Bluetooth - Performing Long-Term Actions in the Background

This is from the Core Bluetooth Background Processing for iOS Apps section found in official docs:
Performing Long-Term Actions in the Background
Some apps may need to use the Core Bluetooth framework to perform
long-term actions in the background. As an example, imagine you are
developing a home security app for an iOS device that communicates
with a door lock (equipped with Bluetooth low energy technology). The
app and the lock interact to automatically lock the door when the user
leaves home and unlock the door when the user returns—all while the
app is in the background. When the user leaves home, the iOS device
may eventually become out of range of the lock, causing the connection
to the lock to be lost. At this point, the app can simply call the
connectPeripheral:options: method of the CBCentralManager class, and
because connection requests do not time out, the iOS device will
reconnect when the user returns home.
Okay, we have an app which locks/unlocks doors as appropriate... So as pointed out, this works when app is in the background (most likely in the suspended mode). Now, lets move on (with quoting docs):
Now imagine that the user is away from home for a few days. If the app
is terminated by the system while the user is away, the app will not
be able to reconnect to the lock when the user returns home, and the
user may not be able to unlock the door. For apps like these, it is
critical to be able to continue using Core Bluetooth to perform
long-term actions, such as monitoring active and pending connections.
So, if the user was away from home for a few days, and app has been terminated by the iOS, we will have to implement state preservation and restoration, so that iOS relaunch the app when connection request is detected, and let the app to unlock the door. Related quotes:
In the case of the home security app described above, the system
would monitor the connection request, and re-relaunch the app to
handle the centralManager:didConnectPeripheral: delegate callback when
the user returned home and the connection request completed.
This all make sense, but pay attention to this part again:
Now imagine that the user is away from home for a few days. If the app
is terminated by the system while the user is away, the app will not be able to reconnect to the lock when the user returns home, and
the user may not be able to unlock the door. For apps like these, it
is critical to be able to continue using Core Bluetooth to perform
long-term actions...
Does this means, if the app is forcefully killed by the user at some moment while he was away from home, that this will work as well ? Means when user comes home, the door will unlock anyway, or he must manually relaunch the app to unlock the door?
I am asking this, because of how relaunch of terminated apps works. It is not the same when user kills the app, and when iOS kills the app which supports background execution:
Apps that support background execution may be relaunched by the system
to handle incoming events. If an app is terminated for any reason
other than the user force quitting it, the system launches the app
when one of the following events happens...
Source
So once again, if the user was away for a few days and he has closed the app by double tapping Home button and dragging up, will he be able to enter his home without manually relaunching the app?
No. If the app is forcefully killed by the user then it will not be woken up again. The only scenario where it will be woken up is if the app was terminated by iOS itself, which will happen sooner or later when the app has not been it the foreground for a while. It will also not be relaunched if the device is rebooted.
Having said that, from my experience with Core Bluetooth I have come to the conclusion that State Preservation is way too unreliable. I would believe that the use-case that you are trying to implement will not work well enough, which is ironic since it is exactly the use-case that Apple is promoting it their documentation.
For example, you will have issues with the following:
State restoration will only relaunch your app due to bluetooth related activity if the event originates from a peripheral accessory that you are communicating with, such as connect/disconnect events and characteristics notifications. For other events, most importantly general bluetooth-state-change events, your app will not be relaunched and notified of this. The reason why this is so bad is because any bluetooth-state-change events will cause all pending connections to be tossed, meaning that your pending connections to the door lock will be lost. However, since your app is not relaunched to be notified of this, then it effectively means that your application will still believe that the connections are still pending when in fact they are not. Since your application is terminated at this time, the only way for it to wake up again is by having the user manually launch it again (or alternatively “hack” other background modes for this purpose, which will NOT work very reliably either).
This scenario happens if the user toggles Flight Mode, toggles Bluetooth, power cycles the iOS device, or any other undefined reasons that many cause state changes… And it is very unlikely that a bluetooth-state-change will not happen if "... the user is away from home for a few days.".
This "issue" has been reported by me and others multiple times, but Apple does not appear to want to fix it for some reason.
Apart from this, many other issues exists as well, such as the XPC connection being interrupted at different times for no apparent reason. I have also noticed that the pending connection can go into “limbo” mode where the peripheral state gets set to Connecting, but in fact it will never connect unless you cycle the connection state. Etc, etc, ...
/A

Distinguishing whether an iOS app running in background is terminated by iOS or user

My iOS app is running in background (with location services permissions) and I am trying to determine if the app is terminated by the user or they system. In the case of a user terminating with the app switcher, I'd want to clean up some location region monitoring (ideally immediately, or less ideally on a reload of the app), because I assume the user wants a clean termination. In the case of a system termination, I want to leave the region monitoring in place. The problem is that in both cases (for an app running in background - as opposed to suspended, where one can check if the state change to suspended occurred before termination -), applicationWillTerminate is called for both a user and system termination. In this particular case, that's problematic because I'm unable to determine whether it's system or not. Is there any way to make this differentiation? Or, perhaps another angle: how can one detect if the previous app termination occurred due to a crash (in this case, though not as ideal, at least clean up can be done on reload of the app).
I should clarify as an edit, that what I mean by user force quit, is that the user swipes up in the multitasking screen. This generates a call to applicationWillTerminate. A force quit by holding down the home button after holding down the power off button, doesn't call applicationWillTerminate, but I'm not concerned about this case - What I would ideally like to determine is if the user terminated in the multitasking screen (or whether the os killed that app for, say, memory issues).

Will ios terminate the app running in background after a specific time?

I am using core location framework inside my application and I set the location string in UIBackgroundMode or Required background modes(in Xcode 4.2) for getting the updated location from didUpdateToLocation method when app is running in background and also sending this updated location to server by hitting the specific link inside didUpdateToLocation method of core location framework.
My question is that will the app be terminated after some time when running in background or not?
No, there is no specific time defined for this.But app will definitely terminate based upon certain parameter - battery drain, memory footprint issue etc.
In developer documentation it is clearly mentioned - "The system keeps suspended apps in memory for as long as possible, removing them only when the amount of free memory gets low. Remaining in memory means that subsequent launches of your app are much faster."
Go through this for complete details -
http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
I am sure it is not useful for the author because the question was asked in June 2012 and I am giving an answer in June 2019. This answer maybe is useful for other users.
I am posting this answer because Everyone is said that it is OS default behaviour, We can not change it....bla....bla.
Recently, I was working with the same requirement. After 2-3 week hard
work, I did it. For other users, I create a helper class for it. My
app will never be killed by OS until the location tracking enabled.
You can also verify that OS will never kill this app tracking app
Use HSLocationManager for infinite location tracking in the active and inactive state.
Refer my app which is available in the app store(App will never kill by OS if location tracking is enabled)
Location manager that allows getting background location updates every
n seconds with desired location accuracy.
Advantage:
OS will never kill our app if the location manager is currently
running.
Give periodically location update when it required(range is between 2 -
170 seconds (limited by max allowed background task time))
Customizable location accuracy and time period.
Low memory consumption(Singleton class)
iOS app may get terminated due to following reasons:
Watchdog Timeout
As you’re probably aware, since iOS 4.x, most of the time when you
quit an iOS app, the app isn’t terminated – instead, it’s sent to
the background.
However, there are times when the OS will terminate your app and
generate a crash log if the app didn’t respond fast enough. These
events correspond with the implementation of the following
UIApplicationDelegate methods:
- application:didFinishLaunchingWithOptions:
- applicationWillResignActive:
- applicationDidEnterBackground:
- applicationWillEnterForeground:
- applicationDidBecomeActive:
- applicationWillTerminate:
In all of the above methods, the app gets a limited amount of time
to finish its processing. If the app takes too long, the OS will
terminate the app.
User Force-Quit
iOS 4.x supports multitasking. If an app blocks the UI and stops
responding, the user can double-tap the Home button from the Home
screen and terminate the app.
Note: You may have noticed that when you double-tap the Home button,
you also get a list of all the applications you’ve run in the past.
Those apps are not necessarily running, nor are they necessarily
suspended.
Usually an app gets about 10 minutes to stay in the background once
the user hits the Home button, and then it gets terminated
automatically by the OS. So the list of apps that you see by
double-tapping the Home button is only a list of past app runs.
Low Memory Termination
When subclassing UIViewController, you may have noticed the
didReceiveMemoryWarning method.
Any app that is running in the foreground has the highest priority in
terms of accessing and using memory. However, that does not mean the
app gets all the available memory on the device – each app gets a
portion of the available memory.
When total memory consumption hits a certain level, the OS sends out a
UIApplicationDidReceiveMemoryWarningNotification notification. At the
same time, didReceiveMemoryWarning is invoked for the app.
At this point, so that your app continues to run properly, the OS
begins terminating apps in the background to free some memory. Once
all background apps are terminated, if your app still needs more
memory, the OS terminates your app.
I have seen that the background location updates will work for several hours. But if I go to a place without reception the device will stop to send GPS updates it wont start when I go to a place with reception. This occurs after approximately 30min.
But if I add this, in iOS6, the app won't terminate
[locationManager setPausesLocationUpdatesAutomatically:NO];
Quick answer is pretty much no. Read below though for in depth.
Since multitasking has been enabled on iOS devices that a)your app gets allocated amount of memory and b)the device limits the amount of tasks, that is applications using memory, that occur at any given time. If you take an iOS device and open several apps you'll begin to notice that the app you opened first may have been terminated and reload from the viewDidLoad.
Generally it's safe to say if your app is a recently opened app (or even on a phone where someone clears the multitasking menu often) that the device will not terminate your application in the background.

Resources