Clear the entire history stack and start a new activity on Android

Is it possible to start an activity on the stack, clearing the entire history before it?

The situation

I have an activity stack that either goes A->B->C or B->C (screen A selects the users token, but many users only have a single token).

In screen C the user may take an action which makes screen B invalid, so the application wants to take them to screen A, regardless of whether it is already in the stack. Screen A should then be the only item on the stack in my application.

Notes

There are many other similar questions, but I haven't found anything that answers this exact question. I tried calling getParent().finish() - this always results in a null pointer exception. FLAG_ACTIVITY_CLEAR_TOP only works if the activity is already on the stack.


Solution 1:

In API level 11 a new Intent Flag was added just for this: Intent.FLAG_ACTIVITY_CLEAR_TASK

Just to clarify, use this:

Java

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Kotlin

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

Unfortunately for API lvl <= 10, I haven't yet found a clean solution to this. The "DontHackAndroidLikeThis" solution is indeed pure hackery. You should not do that. :)

Edit: As per @Ben Pearson's comment, for API <=10 now one can use IntentCompat class for the same. One can use IntentCompat.FLAG_ACTIVITY_CLEAR_TASK flag to clear task. So you can support pre API level 11 as well.

Solution 2:

Case 1:Only two activity A and B:

Here Activity flow is A->B .On clicking backbutton from B we need to close the application then while starting Activity B from A just call finish() this will prevent android from storing Activity A in to the Backstack.eg for activity A is Loding/Splash screen of application.

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();

Case 2:More than two activitiy:

If there is a flow like A->B->C->D->B and on clicking back button in Activity B while coming from Activity D.In that case we should use.

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);

Here Activity B will be started from the backstack rather than a new instance because of Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_NEW_TASK clears the stack and makes it the top one.So when we press back button the whole application will be terminated.

Solution 3:

With Android's Newer Version >= API 16 use finishAffinity()

approach is suitable for >= API 16.

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
  • Its is same as starting new Activity, and clear all stack.
  • OR Restart to MainActivity/FirstActivity.

Solution 4:

I spent a few hours on this too ... and agree that FLAG_ACTIVITY_CLEAR_TOP sounds like what you'd want: clear the entire stack, except for the activity being launched, so the Back button exits the application. Yet as Mike Repass mentioned, FLAG_ACTIVITY_CLEAR_TOP only works when the activity you're launching is already in the stack; when the activity's not there, the flag doesn't do anything.

What to do? Put the activity being launching in the stack with FLAG_ACTIVITY_NEW_TASK, which makes that activity the start of a new task on the history stack. Then add the FLAG_ACTIVITY_CLEAR_TOP flag.

Now, when FLAG_ACTIVITY_CLEAR_TOP goes to find the new activity in the stack, it'll be there and be pulled up before everything else is cleared.

Here's my logout function; the View parameter is the button to which the function's attached.

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}

Solution 5:

Immediately after you start a new activity, using startActivity, make sure you call finish() so that the current activity is not stacked behind the new one.