onSaveInstanceState() not called on custom view when app is moved to background - android

In an app I am developing, I have a custom view in which I need to save the instance state when either the screen configuration changes or the app is moved to the background. I implement onSaveInstanceState() and onRestoreInstanceState(Parcelable savedInstanceState) and in the case of screen configuration changes, the instance state is saved and restored perfectly. However, when the app is moved to the background, onSaveInstanceState() is not called. This means I have no saved instance state when the activity is brought to the foreground again. My question is then:
Why is onSaveInstanceState() not called when the app is moved to the background, and is it possible to make my view call onSaveInstanceState() when the app is moved to the background?

It occurs when you press the back button to leave the activity. –
Zero
When using the Back button to leave the application the onSaveInstanceState method is not called by the Android system, this is expected system behavior. The back button is meant to stop your app (Read: activity).
The Back button finishes your Activity and there is no need to save app state. But if there is reason to to this then you should override the onStop method for example and save data to the file system there.
Sources:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
(Recomended read)
There are a few scenarios in which your activity is destroyed due to
normal app behavior, such as when the user presses the Back button or
your activity signals its own destruction by calling finish().

As per my knowledge, when app enter into background, on Activity it calls onPause() method. So please try by moving your code to onPause() method.

Related

Programmatically put an Android activity in its "Stopped" state, without destroying it?

I'm creating a music app in Android with a background service playing the music, and a Home activity that has various fragments and is the UI of the app.
When I press the home button on my phone, this app gets put in the background of course, and the lifecycle methods get called down to onStop(), in which the UI gets disconnected from the Service in order to allow background playback, the user can keep using their device and do other things. When I get back to my UI Activity, onStart gets called and the UI and Service reconnect together, giving me back controls over the music. onStart gets me the same activity in the foreground, it doesn't create another instance of the same activity.
I'm trying to implement also a function for when I press the back button on my device, so the UI activity can have the same behavior as with the home button, i.e. simply put the UI in the background (onStop). Instead, the default behavior of the back button is to finish(), killing the current activity it's called from (thus calling onDestroy).
What could I do for that? Couldn't really find anything online. Seems such a simple function that every music app has (not killing the app when pressing back, but just send it into background)
You can override onBackPressed and move the Activity Task to back. Based on the documentation Activity'r order in the Task will also remain unchanged:
#Override
public void onBackPressed() {
this.moveTaskToBack(true);
}

Stashed Activity means activity object does not exist?

I was looking at this page from "Android Programming" by big nerd ranch, and I was confused by the sentence beneath. It states that "when the activity is stashed, an activity object does not exist." This is confusing to me because when I open an app and press the home button, onPause() is called and the activity reaches a "Paused" state with its activity stashed in the OS, as shown in the figure. It must be still running in the background because onDestroy() is not called when I press the home button. In fact, when I open my task manager, I can see how the activity looked like when I pressed the Home button. What exactly do they mean by "activity object does not exist?" when it is clearly on paused state in the background?
THeir documentation looks to be a bit wrong and confusing. The official Android documentation doesn't talk about a "stashed" state, it would be the block "App process killed" in the documentation here
Basically, from the STOPPED state only, the OS may destroy your activity at any time. If it does this, is will call onSaveInstanceState. The Activity variable would then be invalid. At any time, it may then recreate a new Activity and call onCreate then onRestoreInstanceState on it, passing in the Bundle you save previously, to recreate the activity.
This is confusing to me because when I open an app and press the home
button, onPause() is called and the activity reaches a "Paused" state
with its activity stashed in the OS, as shown in the figure.
I would not say that this is "stashed". Your activity is alive and well, just paused.
It must be still running in the background because onDestroy() is not
called when I press the home button.
That's right. When you are hitting the home button you are saying to the OS "Hey I'm going somewhere else, but I'm not necessarily done with this activity."
If you instead hit the back button, then you'll see onDestroy called. Here you are saying to the OS "Ok I'm done with this activity, do with it what you want."
What exactly do they mean by "activity object does not exist?" when it
is clearly on paused state in the background?
The stashed state is entered when the OS needs to destroy your activity without you "telling" it to do so (i.e. hitting back button). This happens when your device goes through a device configuration change. A classic example is rotation. This also happens if the OS needs to free up memory. In this case onSaveInstanceState will be called to capture the state of your activity in a Bundle. The stashed state is then the preservation of this Bundle and the class name of your activity. The actual Activity object is marked for garbage collection. Then given just the Bundle object and the class name of your activity, the OS can create a new instance of your activity if the user returns to it.
One take away is that you don't have to implement onSaveInstanceState yourself unless there is specific information you want preserved. Some components of the view hierarchy will automatically add information about themselves to the Bundle because the super Activity.onSaveInstanceState will still be called. From the docs:
The default implementation takes care of most of the UI per-instance
state for you by calling onSaveInstanceState() on each view in the
hierarchy that has an id, and by saving the id of the currently
focused view (all of which is restored by the default implementation
of onRestoreInstanceState(Bundle)). If you override this method to
save additional information not captured by each individual view, you
will likely want to call through to the default implementation,
otherwise be prepared to save all of the state of each view yourself.
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
You can check the source here:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/Activity.java#1371

Using onSaveInstanceState With Multiple Activities

I have three activities in my application.
From the first one i started the second, and from the second i started the third. When the process of my app is killed by the system and i launch it again i see only the last active activity is being created. And it seems the only one that gets Bundle object as a parameter to its onCreate method.
There are two things I am curious of:
If the activity at the top of the stack is the only one that gets its bundle, why each of my activities got their callback (onSaveInstanceState) called just before their onStop() method.
If only one of my activities can retain original state, what about the others? Did they lose all their state just because system decided to kill my app process? Should i restore them manually? What about views on them? (normally views get their state back without needing me to put something into the bundle and later restore if i am not mistaken)
The default behavior is this (tested on 4.1.1):
When you start a new activity, onSaveInstanceState of the previous activity is being called
When the system kills the app, the state of activities back-stack is being saved
When you restart the app, the last seen activity is being shown and its onRestoreInstanceState is being called
When you navigate back and pop activities from the back stack, state of each of them will be restored with a call to onRestoreInstanceState passing the bundle that was obtained from the first step above.
Therefore, the answers to your questions are:
All activities will be restored, but not at once - the last one seen is restored immediately, while the others will be restored when you navigate back.
All simple views (e.g. EditText) will automatically restore their state. In order for this to happen, you need to make sure that a) you did not override onSaveInstanceState or onRestoreInstanceState without call to super implementations b) the views that should be restored have unique IDs in view hierarchy
onStop is called on previous activity when you create a new activity, so you are saving the state! Your previous activity's onCreate will be called, if it's destroyed, so don't worry about recreating views. Are you sure app is killed? An app is not killed when it loses view. Android will keep it in memory as long as it doesn't need to free memory.

When to save the state of an app

I am building an Android game. Now, I am saving all changes of the user state (matches in SQLite, user's preferences in SharedPreferences, and other data in files) in the onDestroy() method of the main fragment (that fragment should be alive all the time and can open other activities, such as a the account fragment or playing fragment).
If I exit the app via Back button, everything works fine since onDestroy() of main fragment is called.
The problem is when I exit via Home button, or when main fragment is killed from OS. In these cases, onDestroy() isn't called, so the state of the game isn't saved.
I know that I can resolve that if I save the game in the onPause() instead of onDestroy(), since it is always called. But the storage operation, in my case, is very big (SQLite + SharedPreferences + files, a lot of data) and do that in onPause() means inefficiency.
Is there any other way to manage this?
Have you tried this solution - http://nisha113a5.blogspot.com/2012/01/intercept-home-key-android.html?
Try to hook Home button pressing, and at this moment save user state.

Reload application data when the android app comes into foreground..?

Here is the scene what i am facing..when i press home key it saves the current state of the current activity..so when my app comes in foreground, onResume() of that particular activity gets called who's state was saved. So if an app with say 10 activities are there then, we will need to write reload of app data in each activity's onResume()..is there a way to specify a reload of app data in one activity only..?
Jitesh,
Yes, this is possible. You will probably want to perform the reloading of application data in your Activity's onResume() function. See Android Activity Lifecycle.

Categories

Resources