How to handle application temporarily killed and then restarted - android

Lets say an application is running with activity B is in top of the stack and activity A is the activity that has the launch intent defined in the manifest. Then my app goes in the background (not visible) and the system temporarily kills my application and brings it back up again.
At that point which activity does the system bring up first, activity A (launch intent defined in the manifest) or activity B ?
Also if the application is temporarily killed then does it restart right away or it might be dead for a while?
My application has a lot of dynamic state, it also logs in to a server, so when the application is temporarily killed then the state of my application can change during that time and when it is restarted I will again have to start my application and re-login and update all its state again. Is there any way this can be avoided?
Thanks.

Sure, If application is killed then it should start from launch activity. If there is login option, then you should keep remember me option too, so that if app is being killed you got the state of app and execute auto login if remember me is set otherwise just launch the app with login process.

I beg to differ from what #Keshav says. I think the Activity that was destroyed last is what is re-created and shown to the user. I base my belief based on what happens when the configuration of the device changes - the current activity is actually destroyed the same is re-created and it's not the very first activity that was launched.
As far as what you should do, guidelines when your app gets terminated or destroyed while it's in background, you have to refer to:
http://developer.android.com/guide/components/activities.html#SavingActivityState

You wrote:
Lets say an application is running with activity B is in top of the
stack and activity A is the activity that has the launch intent
defined in the manifest. Then my app goes in the background (not
visible) and the system temporarily kills my application and brings it
back up again.
The following happens:
A new process is created for your application
Your Application object is instantiated and onCreate() is called on it
An instance of ActivityB (the top activity on the task stack) is instantiated and onCreate() is called on it
Your root activity (ActivityA) will only be instantiated when (and if) ActivityB ends (is finished or the user presses the BACK button).
You cannot prevent Android from killing your app while it is in the background. However, you can determine that this has happened and react accordingly. The easiest way to do this is to have a static member variable *either in the root activity or in a custom Application class) that you set to true when the root activity is created and has performed its initialization. In onCreate() of ActivityB, check if this variable is set to true. If not, your app has been restarted, so you can now react. For example, you could just redirect the user back to the root activity and force start your application from the beginning. Or you could tell the user to wait while you reinitialize your application, etc.

Related

Can Android kill the activity without killing the entire process while the app is in the background?

I'm wondering if Android system is able to kill the activity without the entire application process while the app is minimized. From Android documentation we know that onDestroy is only called when the activity is about to be destroyed and the systems guarantees to call this method whenever it is about to kill the activity, it will not be called only in case the entire application process is killed.
So, imagine such a situation - you send the app to the background(minimize) and after some time the os starts to run low on memory and decides to kill the activity, but since the app is currently suspended and cannot execute code it is not able to call its onDestroy method althought it is guaranteed that it will be called before every activity destruction.
So, this kind of reasoning gives me a thought that while the app is in the background os is only able to kill the entire process but not some specific activities. Is my reasoning correct, or did I miss something?
That's true: while the app is in the background os is only able to kill the entire process but not some specific activities.
Your reasoning is correct.
If the user navigates away from the activity/application (e.g. by pressing the home button) then the activity is said to be in the "Stopped" state. (States being "None-existent", "Stopped", "Paused" and "Resumed"). If android get low in memory and needs to kill some processes it will target those processes whose activities are in the "Stopped" state and it kill the whole process (not the activity). Furthermore, it will not be polite when doing so and therefore, will not call the activity's onDestroy() method.
Edit following comments about the confusion of saved state on process death:
If the activiy's process is killed, the system temporarily saves a set of settings outside the activity and using these settings, it recreates the activity the next time it is launched.
For example, just before moving to the "Stopped" state the system calls onSaveInstanceState(Bundle) on an activity that is not "finished" and saves this Bundle outside the activity. The system also does remember that it killed activity's process while it was not finished. Using these two along with other settings (saved outside the activity), the system recreates the activity.
If, However, the activity is finished (e.g. user presses the back button, swipes away the activity's card from the overview window, Activity.finish() is called explicitly, etc), onSaveInstanceState() is not called and the system doesn't save any settings to recreate the activity next time it's launched. It simply creates a fresh one.
This is good news, why? Becuase if it wasn't the case, the developer would have had to stash key state properties manually outside activities and reinstate them when activities are relaunched (that would've been a nightmare)
Since there's been much confusion on this issue, in large part due to the confusing state of the official docs in the past, here's what the docs say
at present:
The system never kills an activity directly to free up memory.
Instead, it kills the process in which the activity runs, destroying
not only the activity but everything else running in the process, as
well.
This as well as real world observation yields that the answer is no.
https://developer.android.com/guide/components/activities/activity-lifecycle#asem

activity's life cycle is beyond its application process?

I got a main-activity, then it opened a new-activity. After putting it to background by clicking home button. If I killed the process using adb shell commands, then I reopen my app.
The new-activity is shown by default instead of starting from the first activity.
My question is that activity's life cycle is beyond its application process?
As the sample shows, even activity's application process is killed, the saved activity still is there. Is this correct? And will android system recycle the saved activities later?
If you reopen the app via the activities list, it will attempt to restart via the last open activity. It's a "feature" of Android that can be incredibly annoying (and frequently just wrong)- Android assumes every app can serialize its entire state when exited for later reopening. You either need to do that (via onSaveInstanceState and onRestoreInstanceState) or you need to catch when you're relaunched and explicity launch your main activity.
This shouldn't happen if you're relaunched via the app launcher, as that should always launch your specified activity.
Android remembers the state of recent tasks and activities. Android can kill your application's process at any time (if it is in the background). If your application was killed while in the background, Android remembers what activities were in the task and how they were started (Intents). If the user now returns to the task (either by selecting from the list of recent tasks, or by tapping the application's icon in the list of applications), Android will create a new process for the task and recreate the activity that was on the top of the stack (ie: the activity that was in front when the task was sent to the background). This allows users to open an applicaton, use it, leave it to do something else, and then return to the application where they left off.
In order for this to work properly, you must save and restore any necessary state (using onSaveInstanceState() and onRestoreInstanceState().
If a task goes to the background and is idle (unused) for some period of time (device manufacturers can change this, usually the value is something like 30 or 60 minutes), Android will reset the task. In this case, if the user returns to the task, the previous saved state will be ignored and the user will start from the beginning. However you can prevent this from happening by setting alwaysRetainTaskState="true" on the root (starting) activity.

Activity life cycle in jelly bean is different

I have a strange behavior in my app when running in jelly bean 4.1.1 , when i start an Activity and press the back button to go back to the First Activity it re-create it by calling onCreate also , what i did also i handle the configuration change with the first activity so it won't recreated on configuration change but thats didnt make anything . !!!! why Activity life cycle in jelly bean have a strange behavior. You can see what i mean , just create a simple Android project and create two activity , navigate from the first one to activity to and press back button and see the logs onCreate on Activity 1 will be called !!!!
There is no guarentee that the OS won't kill your background Activities at any time if it determines that it needs the resources. Just a guess, but onCreate may get called in these cases because the system kills the first Activity before you get back to it.
Edit: http://developer.android.com/guide/components/activities.html#Lifecycle
If an activity is paused or stopped, the system can drop it from memory either by asking it to finish (calling its finish() method), or simply killing its process. When the activity is opened again (after being finished or killed), it must be created all over.
Here is another reference for you:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
http://developer.android.com/training/basics/activity-lifecycle/starting.html
In the first link:
The system may also destroy your activity if it's currently stopped and hasn't been used in a long time or the foreground activity requires more resources so the system must shut down background processes to recover memory.
...
However, if the system destroys the activity due to system constraints (rather than normal app behavior), then althought the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a Bundle object.
Open Phone setting screen
click on developer option(if not present then press about phone 5-6 times)
In developer option in App category uncheck Do not keep Activities flag

How to kill app once focus is lost?

I'm trying to get the main activity for my app to finish (not remain an active application in background) while keeping the process alive for a service.
If the user presses the home button and leaves my app or another activity is launched from outside of my app, I want the activity to be closed and NOT listed as an active application.
It is important, however, that the process stays alive. I don't want my background service to die as well.
What's the best way to go about doing this?
You should not forcibly close the application as the system does well in handling this itself. Instead you should call finish() to signal that the app is done and can be disposed of(your service will continue running).
By default Services don't have a UI. Once started they run until they crash or are killed . The user can close your app and launch a new one and the Service will persist.
Activities on the other hand are only running when they are visible. When the user navigates to another activity the previous activity is paused, stopped, or killed.
A simple way to do what you've briefly described above would be to create an Activity that starts a Service. That way when use navigates away form your Activity the Service will keep running in the background.
If you want your activity to die completely whenever a new Activity comes into view simply put a call to finish() in the onPause() or onStop() methods for your activity (which ever is more appropriate for your app).

Android Application Class Lifecycle

The android app I am working on overrides the Application class to store lightweight state (username, gps location, etc) in static vars. Most of this state is set in OnCreate of the launch activity (username retrieved from prefs, location listener runs). Is it safe to rely on the launch activity to initialize the Application class? Are there any cases where the Application class might be re-created without the Launch activity also being created?
The question comes up because I ran into a null pointer exception accessing a variable in the Application class on resuming the app after the phone was asleep for several hours (the app was left in the foreground before phone went to sleep). Is it possible that the process was killed while the phone was asleep and on waking the phone, the Application class was re-created, the top activity in the stack was resumed, but the launch activity.onCreate wasn't run thus the Application class wasn't initialized?
Note that I have tried to test these kinds of scenarios by Forcing the App to stop using Settings / Manage applications. However, I'm not able to recreate the problem. On the next run, the Application class is created, followed by the launch activity.onCreate.
Is it safe to assume that the Application class instance will exist as long as the process, and that when the Application class is created it is equivalent to "restarting" the application ie. start with a new activity stack (and first activity on stack is the launch activity)?
No. Your entire application can be killed and recreated with the task stack intact; this lets the system reclaim memory on devices that need it while still presenting a seamless illusion of multitasking to the end user. From the docs:
A background activity (an activity
that is not visible to the user and
has been paused) is no longer
critical, so the system may safely
kill its process to reclaim memory for
other foreground or visible processes.
If its process needs to be killed,
when the user navigates back to the
activity (making it visible on the
screen again), its onCreate(Bundle)
method will be called with the
savedInstanceState it had previously
supplied in
onSaveInstanceState(Bundle) so that it
can restart itself in the same state
as the user last left it.
That is, the process (which the Application is tied to) can be killed off but then restarted, and the individual activities should have enough info to recreate themselves from what they've saved before being killed, without relying on global state set in the process by other Activities.
Consider storing persistent shared state that needs initialization by an Activity in either a SharedPreference or SQLite database, or passing it to Activities that need it as an Intent extra.
You can test the scenario by killing the process of your running application.
Step 1. Open your app, and then press Home button to hide it into background.
Step 2. Invoke adb shell
Step 3. Enter command su (you have to get ROOT permission in order to kill process)
Step 4. ps (list all running process ID and find yours)
Step 5. kill 1234 (assume your application running on process 1234)
Step 6. Then, go back to your device and click the launch icon again. You may find the last activity on activity stack is reopen. You may also find onRestoreInstanceState() method is called for the activity.
In short: do initilization in YourApplication.onCreate, not some LaunchActivity
Docs to check:
- Processes and Threads
- API Guides > Activities
Is it safe to rely on the launch activity to initialize the Application class?
Yes, as long as you remember that Application can exist longer that Activity and the Activity may be killed and recreated. I am not sure what Intent will resurrected Activity get: LAUNCH or VIEW
(For scenario when activity was killed as too heavy, while there was long running service binded to app )
Are there any cases where the Application class might be re-created without the Launch activity also being created?
yes, if the last visible activity was not LaunchActivity
check Android application lifecycle and using of static
Is it possible that the process was killed while the phone was asleep and on waking the phone, the Application class was re-created, the top activity in the stack was resumed, but the launch activity.onCreate wasn't run thus the Application class wasn't initialized?
If there were several different Activities launched A, B, C and them whole process killed, then I think Android OS is good with only creating Application and C activity, while A and B would be re-creted on access, that is on returning to them.
Is it safe to assume that the Application class instance will exist as long as the process,
yes
and that when the Application class is created it is equivalent to "restarting" the application ie. start with a new activity stack (and first activity on stack is the launch activity)?
I not sure when restarting the launch activity would be called first,
but the last, i.e. the one that user should see.
"I ran into a null pointer exception accessing a variable in the Application class on resuming the app"
Check this link..
http://www.developerphil.com/dont-store-data-in-the-application-object/

Categories

Resources