Suppose I have activities A, B, C, D, E.
when I open application with activity A and switch to activity B and further to activity C. Suppose, somehow B gets destroyed by system. and when I press back button, I came out of app. What I really wanted was to be able to go to B if it exists otherwise A (landing page). In normal cases it's working smoothly but it's some cases where I have to interact with other apps/interfaces for eg. open url in browser. After sometime if I go back to app, I see latest page as it is but when I press back button app exits.
I have searched for solutions but couldn't find one so posting it as a question.
I know the idea of passing extra in intent and starting new intent on back press but these would not work in some cases or requires creating a backstack handler of own.
There is no guarantee that your activities will stay in memory and this is an intentional behaviour.
Your option is use to onRestoreInstanceState and onSaveInstanceState so that user do not lose critical data.
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// Get data
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// Save data
super.onSaveInstanceState(outState);
}
One way which I have used in the past to validate activity state is to add e.g. a boolean attribute in your activity, set this true when activity starts, if your activity is destroyed after some time this will be false. Check state by overriding the activities onBackPressed method?
e.g.
onBackPressed(){
if status{
/*activity live*/
}
else{
/*activity destroyed/*
}
}
This might work If I understand you issue correctly.
Related
This is a follow up question to this question:
How to resume activity instead of restart when going "up" from action bar
I got 2 activities, both are defined in the manifest with android:launchMode="singleTop".
Activity A calls activity B. Activity B got a back button:
backButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
finish();
}
});
On some devices there is no problem and the previous activity resumes. Other devices are restarting the previous activity instead of resuming it. Why is that?
This could be because on some devices your activity is being garbage collected to save memory. If you want to resume instead of restart even in the case of android killing your activity override the onSaveInstanceState method, and save all your variables in the bundle.
Now when you go back to your activity, if it was killed then in on create a bundle will be passed called savedINstanceState. If savedInstanceState is not null then use the data present in it to bring your activity back to the previous state.
more details here: How to use onSaveInstanceState() and onRestoreInstanceState()?
I have application and when I navigate back using Intent and startActivity(), views are null, onCreate() is called and activities are re-initialized. Why is that and how to bypass it?
I navigate back to activity like that:
#Override
public void onBackPressed() {
if (this.getClass() == XXX.class) {
Intent i = new Intent(this, YYY.class);
startActivity(i); //<-- activity restarts
return;
}
}
super.onBackPressed();
}
I use ActionbarSherlock, so I have activity with ActionBar initialization and every single activity just extends it. The way I navigate back to activity is described in this activity.
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
initUIComponents();
setListeners();
resetProgress();
}
and initUI() initializes UI.
EDIT
What I mean, how can I go back to previously created activity (not the one that is called via onBackPressed) and not recreate it? I use startActivity(), but apparently it recreates the whole thing
If you want that when you press back, you want to show the previous screen, then you don't have to do it in your code. Android Runtime internally maintains the stack, and will take care of showing the last-shown-activity when you press back. No need to handle it via onBackPressed()
However, if you want something other than this default action, that is when you should use onBackPressed(). Else, just let Android handle it.
So, in your application, if Activity 1 calls Activity 2, and user presses back, then the default action would be to show Activity 1 again. Don't override the onBackPressed() method
Edit:
For a custom flow of activities, you'll have to build the logic yourself. You need to override onRestart() in Activity 1, and onStop() in Activity 3. That way, onCreate won't be called again. By your logic, I mean, flags to keep track of which activity you're in, checking those flags, and calling the desired activity from there.
Edit 2:
This previous SO question, answers what you need:
Android Activity management , which suggests setting the flag FLAG_ACTIVITY_REORDER_TO_FRONT on the intent, and then calling startActivity()
Check out Android activity stack management using Intent flags for other stack reordering options: Stack management
I am developing an application in which i am overriding the back button. I created a check box. On click of which i am calling intent for:
startActivityforResult();
And also maintaining the state of activity as :
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putBoolean("checkbox", checkbox.isChecked());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
checkbox_state = savedInstanceState.getBoolean("checkbox");
}
which run fine and the state is maintained.
Means i am entering value in edit text. and on check box click calling new activity for result and while return on first activity the state is maintain.
Now but from second activity if i click on device back button the state is not maintained.
So what should i do to maintain the state on back button. I searched but not found satisfied solution. Please suggest me.
When You start the new Activity then the current Activity gets hidden and new Activity is placed on top of the stack. Now if you press the back button on the new Activity then the first activity should come up in its current state (If it wasn't destroyed, calling finish()) where it was left i.e. if the check box was checked then it should remain checked. You don't need to save the activity state unless the orientation is changed or the activity is destroyed.
Are you sure you are not doing any thing in the onActivityResult or onResume() method which effects the state of the check box? I would recommend to first comment out all the code in both the methods and see if your check box retains the state. Also can you also make sure that the code itself doesn't uncheck the checkbox before starting the new Activity?
Now but from second activity if i click on device back button the state is not maintained.
onSaveInstanceState() is mostly used for configuration changes (e.g., rotating the screen).
So what should i do to maintain the state on back button
Most likely, there is no "state" that needs to be "maintained", outside of your data model. Your activity needs to update its data model: files, database, preferences, ContentProvider, some singleton that is your in-memory data model manager, whatever.
This is a very basic question, I have a few screens, now when you go from one to another you can then press back and cycle back through all the windows.
I'd rather that when you pressed back it took you to a specific window for instance:
Menu Screen
---->User clicks Info
Info Screen
---->User clicks Ride Info
Ride Info
---->User clicks back
Info Screen
Now is this to do with the hierarchical parent, will this define where it goes back to?
The second part of my question is if I don't have any resources to release or information to store for an on-resume what should I do when the user pauses my app? At the moment if you go back to the menu screen and re-select the app it will start a new instance rather than resuming. Do I just simply implement:
#Override
public void onPause() {
super.onPause(); // Always call the superclass method first
}
and
#Override
public void onResume() {
super.onResume(); // Always call the superclass method first
}
Apologies if this is a bit basic!
You might want to look in to setting FLAGS for your intent while opening new activity Android Dev
Something like this -
Intent a = new Intent(this,A.class);
a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(a);
There is no basic questions here :)
Easiest way to do this is to override the onBackPress() function.
Sample :
#Override
public void onBackPressed() {
//Do what you want here
}
For saving variables when users leave the app, you need to override onSaveInstanceState(Bundle bundle)
#Override
protected void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(outState);
bundle.putInt("sample", 1);
}
For your two parts:
1) It's almost always best to let Android handle the back button, the order of which is determined by the back stack: see here for an explanation. If you want hierarchical navigation, I would recommend looking into the up button - see this developer page for a good explanation of how to use the different navigation tools.
Additionally, if you don't want to have an activity appear in your back stack, you can set the attribute android:noHistory="true" in your manifest, which will mean that the user can't return to it using the back button.
2) If the user has left your app, it's automatically paused, you don't need to implement onPause or onResume for this to happen. However, it's also up for collection to be terminated by the OS. If this happens, then it will be restarted when the user opens it from the launcher again. Any previously running instances of the app should automatically be opened.
Sorry for my incomprehension, but I am new in the android development.
I have an application with activity A and activity B in it, and I go from activity A to activity B. When I left activity A, the onSaveInstanceState method was called, but when I went back to activity A (from activity B in the same application), the bundle in the onCreate method was null.
What can I do, to save the activity A's previous state? I only want to store the data for the application lifetime.
Can someone help me with this?
Here is my code for Activity A:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null)
{
Log.v("Main", savedInstanceState.getString("test"));
}
else
{
Log.v("Main", "old instance");
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
Log.v("Main", "save instance");
savedInstanceState.putString("test", "my test string");
super.onSaveInstanceState(savedInstanceState);
}
public void buttonClick(View view)
{
Intent intent = new Intent(this, Activity2.class);
startActivity(intent);
}
Here is my code for Activity B, when I press a button to go back to activity A:
public void onBack(View view)
{
NavUtils.navigateUpFromSameTask(this);
}
To answer your question, have a look at the android doc: https://developer.android.com/reference/android/app/Activity.html#onRestoreInstanceState(android.os.Bundle)
It says that onRestoreInstanceState is called after onStart() method in the activity lifecycle.
Saving and restoring state is meant to save the current temporary data that is obsolete when user exits the application.
When you minimize or leave the Activity by opening next one it might be killed by the system due to lack of resources and restarted with savedInstanceState when you get back to it. So use onSaveInstanceState() only for saving minimize-restore session data or data that should be preserved on rotation.
So if you start a new Activity in front and get back to the previous one (what you are trying to do), the Activity A might not be killed (just stopped) and restarted without going being destroyed. You can force killing it and restoring by checking Don't keep activities in developer options menu.
If you call finish() or remove the Activity from recent task list the savedInstanceState will not be passed to onCreate() since the task was cleared.
If the value must be persistent consider using SharedPreferences.
This happens because you are navigating the hard way. If you used the phone's default back button navigation, your onCreate would get the bundle passed in.
To circumvent this issue, I suggest you save your state to shared preferences as well as a back up. When the bundle is null, restore it from the shared preferences.
reference
onSaveInstanceState
... onPause()-> onSaveInstanceState() -> onStop() -> onDestory()
onRestoreInstanceState
onCreate()-> onStart()-> onRestoreInstanceState()-> onPostCreate(Bundle) ...
Or You can use LiveData. Save the states in it and observe.If the device rotates it'll update the views accordingly.
After onStart() which is after onCreate()
I used in this case a flag and SharedPreferences. This should work, and when you change the screen orientation.