402

My app shows a signup activity the first time the user runs the app, looks like:

  1. ActivitySplashScreen (welcome to game, sign up for an account?)
  2. ActivitySplashScreenSignUp (great, fill in this info)
  3. ActivityGameMain (main game screen)

so the activities launch each other in exactly that order, when the user clicks through a button on each screen.

When the user goes from activity #2 to #3, is it possible to wipe #1 and #2 off the history stack completely? I'd like it so that if the user is at #3, and hits the back button, they just go to the homescreen, instead of back to the splash screen.

I think I can accomplish this with tasks (ie. start a new task on #3) but wanted to see if there was simpler method,

Thanks

MiguelHincapieC
  • 5,445
  • 7
  • 41
  • 72
Mark
  • 39,551
  • 15
  • 41
  • 47
  • After being in home screen, when user resumes your app does it take him to ActivitySplashScreen or ActivityGameMain? – Tamil Oct 30 '17 at 18:57

16 Answers16

668

You can achieve this by setting the android:noHistory attribute to "true" in the relevant <activity> entries in your AndroidManifest.xml file. For example:

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />
Riot Goes Woof
  • 3,504
  • 5
  • 20
  • 35
Aitor Gómez
  • 7,317
  • 3
  • 20
  • 28
  • 13
    This is the best way to do it. – shkschneider Jul 24 '12 at 09:50
  • 24
    Equivalently you can use `FLAG_ACTIVITY_NO_HISTORY`. – Timmmm Oct 30 '12 at 18:34
  • 38
    How can I achieve this from code? Because I don't want to do this all the time. I would like to remove a given activity from history only under some conditions. – Namratha Jan 31 '13 at 10:07
  • 9
    Just be aware that using the noHistory attribute will make that activity finish, which might cause unexpected behavior with G+ login for example. See: https://stackoverflow.com/questions/20383878/android-app-crashes-without-any-exception-when-trying-to-sign-in-with-google-pl Took me a while to find this bug as my app kept crashing without any trace. – Acapulco Mar 16 '14 at 07:45
  • 7
    using this, if u press home button and again start app, instead of resuming activity, it wl finish activity! – Braj Jun 24 '14 at 10:59
  • Thank you for the suggest.But this is just show the activity when the activity doesnt destroyed.it means, when the app or activity killed, after that, this not work. – ʍѳђઽ૯ท Jul 02 '15 at 06:53
  • I have applied this attribute still is not working in-case of when app was not in recent app list. Any one please suggest how to remove activity when app was not in background previously. – Ajit Kumar Dubey Aug 04 '15 at 09:10
  • For more information please open this link. http://stackoverflow.com/questions/31693570/application-should-not-display-in-recent-app-list-after-finish-the-new-activity?noredirect=1#comment51330227_31693570 – Ajit Kumar Dubey Aug 04 '15 at 09:11
  • 13
    It is difficult to copy the needed flag as it is a link, so here one that can easily be copied. `android:noHistory="true"` – MirroredFate Sep 28 '15 at 21:47
  • Note: `android:noHistory="true"` will make it impossible to use things like the [`AccountPicker`](https://developers.google.com/android/reference/com/google/android/gms/common/AccountPicker) within the Activity; as when it opens your Activity will close. – David Murdoch Dec 17 '15 at 18:11
  • 5
    One problem. In new version of android M, when you call requestPermissions, your activity will disappears. This is a big problem ;) – Eliasz Kubala Jan 06 '16 at 18:40
  • what happens if I press back from B? – desgraci Oct 23 '17 at 20:55
  • Suppose we have four activities Checkout, Login, Otp, Payment. If user is already loged in then the flow will be Checkout --> Payment. But if user is not logged then the flow will be Checkout--> Login --> Otp --> Payment. In this case if user press back button from "Payment", user should directed to Checkout screen screen directly. Your answer works well in this situation. But what if user press back button on Otp screen, he must be directed to Login screen(this is the requirement). In this case your solution wiil not work because instead of Login user will directed to Checkout screen. – harshita Jul 21 '18 at 13:17
  • This is not a good solution. It works fine when you get to Activity #3 - pressing Back closes the app. Pressing Back in Activity #2, however, should return you to #1 - but with this solution it just closes the app. Plus, as was already pointed out, when you for example request some permission on runtime, the Activity from which you were requesting it closes and doesn't reopen after the permission is granted/denied. I believe the OP's problem can't be solved statically by some Manifest value like this. It has to be done programmatically. Keep the backstack until you reach #3, then clear it. – Vratislav Jindra Apr 22 '19 at 09:38
139

You can use forwarding to remove the previous activity from the activity stack while launching the next one. There's an example of this in the APIDemos, but basically all you're doing is calling finish() immediately after calling startActivity().

Giovanni Cappellotto
  • 4,597
  • 1
  • 30
  • 33
Dan Lew
  • 85,990
  • 32
  • 182
  • 176
  • 1
    Hi Daniel, I read through the example, but that will only clear the history stack by 1 activity, won't it? If my stack looks like A, B, and I'm launching C, I want C to be the new root and completely clear A and B. In the sdk example, calling finish() from B would leave me with a stack of A, C, wouldn't it? Thanks. – Mark Dec 14 '09 at 07:34
  • 1
    You could clear A as you launch B, and clear B as you launch C; however, I suppose then you wouldn't be able to back out from B to A if that's what you desire. I'll have to think on this more if that's a problem. – Dan Lew Dec 14 '09 at 14:17
  • 3
    Mark, to achieve what you want, you have to use the flag: FLAG_ACTIVITY_CLEAR_TOP. I hope it helps. – Francisco Junior Jun 12 '11 at 19:17
  • 3
    `FLAG_ACTIVITY_CLEAR_TOP` won't work because C isn't already in the back stack. – Timmmm Oct 30 '12 at 18:35
  • You made my day, i was looking for some way one time dialog between activities, so i needed to disable the dialog on back button. +1 – Frederic Yesid Peña Sánchez Apr 15 '13 at 14:57
  • Yeah this is the method I use. I use complex custom dialogs and require to use the `android:label="@string/activity_name_chat_add_dialog"` the `nohistory` option cannot be used in my case for various reasons. `Finish()` works perfectly after calling `startActivity()` – wired00 Jan 26 '14 at 19:44
  • @DanielLew you can override onBackPressed() in B to start A – Marian Paździoch Aug 13 '14 at 10:21
  • 1
    @DanielLew There are so many examples in the APIDemos. You'd have the name of the example suggested ? – Stephane Jul 04 '15 at 07:27
  • As @user8269411 mentioned, in some cases this should be just before startActivity() – ninbit Aug 17 '18 at 19:57
55

Yes, have a look at Intent.FLAG_ACTIVITY_NO_HISTORY.

mxk
  • 43,056
  • 28
  • 105
  • 132
  • 47
    Note that this sets no history for the activity you're launching to. To have no history for the activity you're launching from, I just set it `android:noHistory="true"` in the manifest. – georgiecasey Jan 30 '12 at 13:13
  • 1
    This work well. Use the `intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)` to set this flag. – vovahost Jan 13 '16 at 09:35
  • 1
    @georgiecasey this is useful when sometimes you want to keep it in history and at times you don't want it in history. – Vihaan Verma Jan 29 '19 at 08:08
25

This is likely not the ideal way to do it. If someone has a better way, I will be looking forward to implementing it. Here's how I accomplished this specific task with pre-version-11 sdk.

in each class you want to go away when it's clear time, you need to do this:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

then the one that needs to set off the chain of pops from the stack needs to just call this when you want to initiate it:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

Then the activities aren't on the stack!
Remember folks, that you can start an activity, and then begin cleaning up behind it, execution does not follow a single (the ui) thread.

Travis
  • 3,737
  • 1
  • 24
  • 24
  • In case anyone comes across this later, I thought it may prove to be important to know, if you've rotated the screen, android will helpfully restart your application for you when you pop the last activity off of the stack. Just be aware of this! – Travis Jan 13 '12 at 15:43
  • This is a good answer if you only want to remove an activity from the stack conditionally depending on what the user does in the next activity +1 – theMothaShip Aug 19 '13 at 16:19
23

One way that works pre API 11 is to start ActivityGameMain first, then in the onCreate of that Activity start your ActivitySplashScreen activity. The ActivityGameMain won't appear as you call startActivity too soon for the splash.

Then you can clear the stack when starting ActivityGameMain by setting these flags on the Intent:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

You also must add this to ActivitySplashScreen:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

So that pressing back on that activity doesn't go back to your ActivityGameMain.

I assume you don't want the splash screen to be gone back to either, to achieve this I suggest setting it to noHistory in your AndroidManifest.xml. Then put the goBackPressed code in your ActivitySplashScreenSignUp class instead.

However I have found a few ways to break this. Start another app from a notification while ActivitySplashScreenSignUp is shown and the back history is not reset.

The only real way around this is in API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mxcl
  • 26,392
  • 12
  • 99
  • 98
20

I use this way.

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
Smiderle
  • 447
  • 4
  • 12
  • Thanks. I found this helpful in the case that there was a Home button in my menu, and I didn't want stacked activities to appear once user clicked home from there. – ghitesh Jun 20 '16 at 13:27
8

In the manifest you can add:

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

You can also call

finish()

immediately after calling startActivity(..)

Anubhav
  • 1,984
  • 22
  • 17
8

I know I'm late on this (it's been two years since the question was asked) but I accomplished this by intercepting the back button press. Rather than checking for specific activities, I just look at the count and if it's less than 3 it simply sends the app to the back (pausing the app and returning the user to whatever was running before launch). I check for less than three because I only have one intro screen. Also, I check the count because my app allows the user to navigate back to the home screen through the menu, so this allows them to back up through other screens like normal if there are activities other than the intro screen on the stack.

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}
alphonzo79
  • 938
  • 11
  • 12
6

Just set noHistory="true" in Manifest file. It makes activity being removed from the backstack.

Remees M Syde
  • 2,564
  • 1
  • 19
  • 42
4

It is crazy that no one has mentioned this elegant solution. This should be the accepted answer.

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

The key here is to use intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); for the intermediary Activity. Once that middle link is broken, the DashActivity will the first and last in the stack.

android:noHistory="true" is a bad solution, as it causes problems when relying on the Activity as a callback e.g onActivityResult. This is the recommended solution and should be accepted.

Otieno Rowland
  • 2,182
  • 1
  • 26
  • 34
  • 2
    That flag sounded too good to be true. FLAG_ACTIVITY_NO_HISTORY works nicely and as one would expect until one puts the app to background and then foreground again while having the activity with the flag on top of the stack. When going to background, the activity is destroyed. When returning to the app, one will see the previous activity from the stack. I definitely didn't want such behaviour. – NeverwinterMoon Oct 23 '18 at 07:03
4

It's too late but hope it helps. Most of the answers are not pointing into the right direction. There are two simple flags for such thing.

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

From Android docs:

public static final int FLAG_ACTIVITY_CLEAR_TASK Added in API level 11

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

activity to be cleared before the activity is started. That is, the activity becomes the new root of an otherwise empty task, and any old activities are finished. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.

Nouman Ghaffar
  • 3,780
  • 1
  • 29
  • 37
2

Just call this.finish() before startActivity(intent) like this-

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);
1

Removing a activity from a History is done By setting the flag before the activity You Don't want

A->B->C->D

Suppose A,B,C and D are 4 Activities if you want to clear B and C then set flag

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

In the activity A and B

Here is the code bit

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
Abhishek Gurjar
  • 7,426
  • 10
  • 37
  • 45
ricky
  • 11
  • 1
0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.finishAndRemoveTask();
        }
        else {
            super.finish();
        }
eagerprince
  • 115
  • 1
  • 5
0

Here I have listed few ways to accomplish this task:

  1. Go to the manifest.xml- and put android:noHistory="true", to remove the activity from the stack.

  2. While switching from present activity to some other activity, in intent set flag as (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK). It is demonstrated in the example below.

    Intent intent = new Intent(CurrentActivity.this, HomeActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) startActivity(intent);here

Note :Putting the intent flags can cause blank screen for sometime (while switching activity).

-7

Try this:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

it is API Level 1, check the link.

Alécio Carvalho
  • 13,481
  • 5
  • 68
  • 74