I have the following model:
MainActivity navigates (through a button) to ActivityA.
ActivityA displays list of records as a ListView (from SQLite database).
If I click on any record, an intent will start ActivityB which displays the data of the selected record to be edited.
If I press on the device back button it will take me back to ActivityA.
ActivityB has a 'save' button, which if clicked will open new intent of ActivityA with the updated records (after edit), also, this button will finish() ActivityB.
Here if I press the device back button (after saving ActivityB and opening ActivityA), it will take me to the old ActivityA with the data before update (the older version of ActivityA), then on the second click on device back button, it will go back to MainActivity.
The question is: How can I let the device back button always go back to the hierarchical parent, instead of going to previous open activities?
OR
How can I kill the old instance of ActivityA if the user clicks on the save button in ActivityB?
Your help is appreciated.
In ActivityB, after the save, you should call finish() instead of opening a new instance of ActivityA. You should have ActivityA re-query and update the ListView.
You can specify FLAG_ACTIVITY_CLEAR_TOP flag in the Intent used to launch ActivityA.
Intent intent = new Intent(this, ActivityA.class);
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
startActivity(intent);
If ActivityA being launched is already running in the current task, then all of the other activities on top of it will be closed including ActivityA and ActivityA is restarted with the new Intent. There will be no need to call finish() on ActivityB explicitly.
Just add finish() in OnPause() of ActivityA and
add this method to ActivityB.
#Overrride
public void onBackPressed(View v) {
Intent MainActivityIntent = new Intent(ActivityB.this, ActivityA.Class);
startActivity(MainActivityIntent);
super.onBackPressed();
}
just try this, it really works...
Related
I have gone through android docs on FLAGS and Affinity (Link)
and tried different combinations that I thought would help achieve my requirement but it seems that I'm missing something.
I need to initiate activityA from from BroadcastReceiver and then finish activityA and start activityB. so when the user presses back it wont go back to activityA; when user presses back on activityB it will stop the activityB and it will go to back stack however when the user opens app back from task manager it will start up from activityA.
Note: this does not happen when there is another activity of the app in the background.(only happens when the app is entirely force closed/killed).
also when user presses home button in activityB it behaves as intended.
I use the following code to lunch activityA from BroadcastReceiver.
Intent intent = new Intent(context, ActivityA.class);
intent.putExtra(EXTRA_TAG, new Gson().toJson(remoteMessage));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
I use the following code to lunch activityB from ActivityA.
Intent intent = new Intent(this, ActivityB.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(intent);
finish();
Is there a different FLAG that I need to use to achieve this requirement?
Actually I have a direct issue with android custom tabs.
But nevertheless I will generalize my question. Let's assume that I have ActivityA and ActivityB. ActivityA - is an external one, so that we launch it from an Intent :
Intent intent = customTabsIntent.intent;
intent.setData(requestUri);
intent.putExtra(CustomTabsIntent.EXTRA_TITLE_VISIBILITY_STATE, CustomTabsIntent.NO_TITLE);
mContext.startActivity(intent);
From here we see that ActivityA - is actually a custom tab activity. When things get done I launch ActivityB. I want ActivityA dissaper from task history, I can achieve this by aplying flag Intent.FLAG_ACTIVITY_NO_HISTORY to my intent. But this approach is causing problems, because when user switches to recents,or goes to other app - ActivityA disappears forever. Of course - that's how flag no history works. But I want a different flow, I want ActivityA disappear only when ActivityB was launched. Any ideas how to achieve this?
P.S. I need to finish ActivityA, which gets launched via intent, I don't have access to its code and I don't have the ability to call finish().
I don't think you can do this by using the NO_HISTORY flag since ActivityA is doing the launching and you have no control over it.
However, you should be able to achieve your goal (not being able to go from ActivityB back to ActivityA by overriding the BACK button in ActivityB and having it go back to whatever is underneath ActivityA in the task stack.
Assuming that ActivityC is the one that starts ActivityA, you could do something like this in ActivityB:
#Override
public void onBackPressed() {
// Direct user back to ActivityC
Intent intent = new Intent(this, ActivityC.class);
// Add flags to ensure that we reuse the existing instance of
// ActivityC and that we clear any other activities above ActivityC
// from the stack.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
You can use finish() method to clear any activity. so before starting another activity finish that.
Intent intent = customTabsIntent.intent;
intent.setData(requestUri);
intent.putExtra(CustomTabsIntent.EXTRA_TITLE_VISIBILITY_STATE, CustomTabsIntent.NO_TITLE);
mContext.startActivity(intent);
finish(); //add this to clear that activity
I have two activities, A y B. A is the parent activity of B.
A initialise the second one with this code:
Intent intent = new Intent( this, B.class );
startActivity( intent );
this.finish();
and the B goes back to A (like a logout) with this code:
Intent intent = new Intent( B.this, A.class );
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
startActivity( intent );
Giving you some more context, the app has a sliding menu and each list item shows a ListFragment within a ListView. On each of those views the back stack has been cleaned and the idea is when the user press onto the back button, he should go to the phone home screen as Google documentation says and when the user press on the app icon from the phone home screen, it needs to re-init where the user was working on.
What the app is currently doing is going to the phone home screen, but when you press onto the app icon, it starts again from the activity A, which is the launch and main activity.
Any idea why?
Try adding after startActivity() finish().
That will make the provius activity to safely close itself.
You use this code to go to phone Home screen
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Override onBackPressed and write the above code. It should work.
According to my understanding, You have 2 activities A & B.
You are starting Activity A & moving to Activity B same timing calling A.this.finish()
It means there is only 1 activity present in your stack which is Activity B.
And when you press "Back" button, it means its closing your app that removing remaining Activity B from stack, so your stack gets empty. So you need to press "Center" button of your device which will keep your app activity B in background (in onStop() state) & when you start your app again so it will open activity B only (by calling onRestart()).
I hope above explanation is highly sufficient to understand above problem.
I have 3 activities in my application
ActA
ActB
ActC
Suppose I am in activity ActB and I am loading ActC with out finish(); ActB
Then when press a button in ActC , need to redirect the application to ActB . But this time when I press back from redirected ActB , another ActB ( previously loaded ) is showing.
Is there any way to kill all the activities which are previously loaded when we press the button in ActC ?
I am new to android and its ruining my time
Please help
thanks in advance
When you launch ActC from ActB, do so with this flag on the intent:
Intent intent = new Intent (this, ActB.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Javadoc:
"If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent."
Just going from ActB to ActC, use Intent and finish() after calling the Intent
Intent intent = new Intent(this, ActC.class);
startActivity(intent);
finish();
And then if you want to go back to B from C, then do the same in reverse, so switch
Intent intent = new Intent(this, ActB.class);
And the rest is the same.
Suppose you move like this
A -> B -> C
All the previous instances will be there in backstack for previous activities.
until and unless it is your requirement to create new instance of activity then only do so.
when you press button in you want to come to B but if you don't need new instance of B you can go with backstack item and according to me you should.
in button click you can simply call onBackPressed() of activity which is called when you press back button of device.
Also as Vee said you can use that flag to clear activities above your current activity.
If you want to "kill" the activity you should call finish();
To achieve your goal you can do the following thing.
When starting ActB from ActA, after calling startActivity(...); put finish();
This way you killed Activity A, do the same in ActB when calling ActC. Then when you call ActB from ActC again, it will start a completely new activity.
If you don't need a new instance of B then you can simply call finish() in your onClick() of C and this will take you back to B and no need for Intent or any other code.
If you need a new instance of B then you can use Vee's suggestion, keeping in mind that this will clear Activities off of the stack if you add more in between.
If you don't need a new instance of B but want to pass data back to it then you can use the flag FLAG_ACTIVITY_REORDER_TO_FRONT
Intent i = new Intent(ActC.this, ActB.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
// can send data to ActB if needed with putExtras()
startActivity(i);
finish(); // if you want to destroy C and take it off the stack
this will not create a new instance of B but bring it to the top of the stack so when you press the "Back" button, you will not have the second instance on there.
When user presses button in ActC to goes back to ActB (by creating a new ActB) do this:
Intent intent = new Intent(this, ActB.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
This will finish both ActC and the previous ActB and create a new ActB.
I have two activities, A and B. I have a button in A,when pressed starts a new intent to B.
However whenever I press the back button while in B, than click the button again is restarts Activity.I do not want to do that,I want it to resume Activity B.
Actually I am doing some networking in Activity B and I want to save unless the user wants to refresh.
How can I do it? Thanks in advance
Use
#Override
public void onBackPressed(){
moveTaskToBack(true);
}
Hope, It must help you
You need to Overrider the
onBackPressed
method and start there the activity like this:
#Override
public void onBackPressed() {
Intent intent = new Intent(this, activityA.class);
startActivityForResult(intent, PICK_CONTACT_REQ);
}
This sounds like you need to rethink your architecture. You say:
Actually I am doing some networking in Activity B and I want to save
unless the user wants to refresh.
If this is the case, you probably don't want to do your networking in ActivityB. Maybe you should start a Service from ActivityB to do the networking. The service and the activity can communicate with each other so that the activity can keep the user up-to-date about the state of the networking. If the user presses BACK in ActivityB, it can finish (as usual) and return to ActivityA. In this case, the Service is still managing the networking. When the user again starts ActivityB (from ActivityA), the new instance of ActivityB can communicate with the service to see if there is any networking going on, and if so it can get the current status of that networking or start it or stop it or whatever.
I guess I'm too late but I had a similar problem.
I had two activities A,B and a next button in A.
Whenever I tried to do: A->press next button ->B->press back button->A->press next button->B, B screen got destroyed when I pressed the back button. So when I came back to B for the second time it was a newly created B (all the information I had put in was gone).
So it was like A->B->A->new B when I just wanted to go back to the original B! :(
So what I did was, in activity B, I overrode the onBackPressed() function so it doesn't destroy the activity. I also set the flag so that if there is a A activity already running, it would just pull it up to the front instead of creating a new A activity.
#Override
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), ActivityA.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
Then, for the onclicklistener function for the next button in activity A, I set the flags similarly.
public void onClickNextbutton(View v){
Intent intent = new Intent(getApplicationContext(), ActivityB.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}