11

I need to finish all the activities running in an Android application when an exit button is clicked. How can I do that?

What I want:

  1. An option menu on screen with an EXIT option.
  2. When I click the Exit menu, the application should close.
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
jennifer
  • 8,133
  • 22
  • 69
  • 96

7 Answers7

38

How to make a button for the user to immediately finish all Activities

When the user wishes to exit all open activities, have them press a button which loads the first Activity (passing in an intent to clear out all the other activities) that runs when your app starts. Then inside the one remaining activity (LoginActivity), place some code in onCreate to have it choose to self destruct.

Details:

Create a button and call it "exit", make a buttonlistener for that button, and put the following code in there. What it does is load the activity, makes it the only remaining activity by clearing all activities underneath it.

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

The above code clears all the activities under LoginActivity. The LoginActivity must be the first activity your app runs. So now we are left with only LoginActivity activated. Now we have to get LoginActivity to check the putExtra parameter, and if it has the value "EXIT" then destroy itself as well.

Put the following code inside the LoginActivity's onCreate and onResume, to check the "EXIT" parameter and finish when it is seen:

    if (getIntent().getBooleanExtra("EXIT", false)) {
         finish();
    }

Why is this so hard, why isn't there just an exitAllActivites() function?

Android OS Developers make this hard because they don't want you to give the user an Exit button. They want the user never to care if their App is running or not. If they want it, they run it, if they don't want it, they stop using it. There are benefits to this model, because then an app can be destroyed to make room for a phone call and heavy map-usage, and then they re-run your app, they pick up right where they left off, rather than having to restart from scratch.

So if you use this code, try to cooperate with the Android Developers vision for Android and make it so that the App can be destroyed/recreated at any point, and the user always picks up where they left off. Requiring a user to 'exit' is a hassle.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • 1
    "What it does is load the activity, makes it the only remaining activity, and clears out all the others. " Not exactly accurate. According to the docs, say your user's gone from Activity A to B to C to D, then from D you showActivity(b) via Intent.FLAG_ACTIVITY_CLEAR_TOP, then all activities AFTER B will be finished, namely C and D. A will still be in memory. – ajacian81 Aug 18 '12 at 14:20
  • 1
    If LoginActivity is already on the stack, then this code will call it's onResume() method instead of onCreate(). – IgorGanapolsky Oct 25 '12 at 21:16
  • @ajacian81 Still not correct. Using your example, if you start activity B with `FLAG_ACTIVITY_CLEAR_TOP`, Android will finish all activities on top of B and it will also finish the current instance of B and create a new instance of B (unless activity B has declared `launchMode="singleTop" in the manifest, in which case it will just call `onNewIntent() on the existing instance of B). – David Wasser Feb 27 '13 at 08:25
  • @IgorGanapolsky That isn't correct. If `LoginActivity` is already in the stack, this code will call `finish()` on that instance of `LoginActivity` and create a new instance of `LoginActivity` and call `onCreate()` as usual ((unless `LoginActivity` has declared `launchMode="singleTop"` in the manifest, in which case it will just call onNewIntent() on the existing instance of `LoginActivity`). – David Wasser Feb 27 '13 at 08:27
7

use StartActivityForResult function for starting a new Activity and when user presses EXIT button, send a unique value as a resultcode. Check for this resultcode in onActivityForResult func and if you find the same unique code then finish the activity.

mudit
  • 25,306
  • 32
  • 90
  • 132
6

I don't understand the people who say that this should not be done. Closing an activity can be done quite easily using the built in method to do so.

There is no place in the official documentation that says this should not be done.

For those who think it should not be done for any purpose, maybe you can't think of a reason to do so. There are plenty of legitimate reasons to do this. And since it is a method built in to the Android code.. Google has also decided that you might need to depending on your use. Not all of us only create consumer applications for Android.

So to accomplish this task..shutting down all of the activities in your stack

public void quitApp(){
      this.finishAffinity();
}

I created a kiosk app that was run as the default launcher. So I needed a way to exit the app to get to settings or other apps on the device. So in an admin Activity, I placed a pin number pad.. after the user inputs the correct pin, the app needed to exit to the original launcher. I used above code.

user2914118
  • 61
  • 1
  • 1
  • Thanks! This is a big help. Google's first time setup wizard has a forced exit, so I don't buy into their whole experience of not endorsing explicit finish() for my app. I certainly need it. – Cookster Apr 15 '14 at 00:46
5

You should not implement an Exit button in an Android application.

Read http://groups.google.com/group/android-developers/browse_thread/thread/1bf0f7a4a9c62edd/a0a4aedf21ae5f76?pli=1

Cheers

metter
  • 1,434
  • 11
  • 22
  • 8
    I really dislike "answers" like this. Yes, _in general_ the application should not be explicitly closed. But that doesn't mean that there are no cases when this can come in useful, and it's very annoying to come to a question and find this instead of a proper solution. Of course, it is not a bad idea to include a disclaimer that this usually shouldn't be done in a real answer, but a disclaimer alone is not an answer. – Malcolm Nov 06 '15 at 21:54
  • Yes, I agree that you have a point. However, I've come across so many instances where project owners request functionality that simply doesn't make any sense and I think that im some instances it is important to point that out prominently instead of posting a solution plus a small disclaimer that probably won't be read. – metter Nov 17 '15 at 10:10
  • And you are welcome to do that in the comments where everything that doesn't answer the question belongs. Besides, if you don't answer the question, someone else will, and you won't always be lucky to have your "answer" accepted. If you are worried about the disclaimer not being read, make it large [like this](http://stackoverflow.com/questions/1512045/how-to-disable-orientation-change-in-android). I've even seen [an answer](http://stackoverflow.com/a/582585/45668) where the explanation of why this shouldn't be done is far larger than the solution itself. – Malcolm Nov 17 '15 at 10:23
4

How to close all activities in Android:

Why are the Android OS devs telling me not to create an Exit button?

If you give developers a hammer, they will use it, and everything becomes a nail, so don't give them a hammer. This is why there is no one-liner to exit all activities.

Why is an Exit button so bad?

You may be frustrated wondering why killing all activities in Android is so difficult. It's hard to do because you've got to bite the bullet and understand how you created the stack, and what it looks like. In what order should the Activities be destroyed? What if the user gets a phone call and needs to nuke your app ASAP? You NEED to have a plan for unwinding. It can't rely on the Activity Manager to babysit your app. If you want to kill your app, the OS devs are twisting your arm to create a unwinding plan because they don't want your application to have any errors when the Activity Manager nukes it.

This self destruct mechanism I go on to describe cooperates with the Activity Manager and causes a cascade effect that causes all activities to finish themselves no matter how they are organized.

To add this cascading self destruct to your app, do these three things:

If you are newbie to android and have never done this before, I suggest you create a brand new bare bones android project to test this out and get a feel for how it behaves. Only when you get the "aha" moment of understanding why this works, then can you extract the usefulness of the code below to delight the user.

  1. Put this override method inside each one of your activities:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        //onActivityResult is called when a launched activity exits, giving 
        //you the requestCode, 1234, that you started it with. The resultCode 
        //it returned, 900, and any additional Intent data from it. The 
        //resultCode will be RESULT_CANCELED if the activity explicitly 
        //returned that, didn't return any result, or crashed during its 
        //operation.
    
        switch(resultCode)
        {
            case 900:         //Make 900 a final global variable if you want.
                              //900 means CLOSE_ALL_ACTIVITIES to me.  It is 
                              //a signal that the self destruct button has 
                              //been initiated and all activities should end.
    
              setResult(900); //setResult sets the resultCode that will be passed
                              //to onActivityResult in the activity that called
                              //this activity.  this will immediately tell the 
                              //parent to self destruct even before the next 
                              //command, finish(), is run.
    
              finish();     //Now stop this activity.
              break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
    

    If you have more than 3 activities, consider having each activity extending a "MyAppActivity" with the above code in there. If you catch yourself copy/pasting the above method into 15 different activities, slap yourself once, and take a class on good Object Oriented Programming. Then read this.

    ( Details about onActivityResult. ), ( Details about setResult. )

  2. Whenever you have the user start a new activity, you must do it exactly this way:

    Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
    startActivityForResult(myIntent, 1234);
    
    //The 2nd parameter of startActivityForResult is what is sent to 
    //resultCode in the onActivityResult method.  The code `1234` 
        //doesn't do anything here because it is a flag that is 
        //ignored in onActivityResult.  
    

    More information about startActivityForResult.

    If you don't use startActivityForResult, then the self destruct unravelling won't work.

  3. When you want to exit your application, initiate self destruct like this:

    setResult(900);    //900 is the self destruct code.
    finish();
    

Then the activity stack unwinding plan cascades through the entire app.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
1

Another solution to finish all activities works for me:

Somewhere in my Controller class, there is a method to initiate the shutdown:

/**
 * Ask for application shutdown.
 * 
 * <p>
 * After the call, the system shall wipe the entire task and activities and
 * then call {@link #onTaskWiped()} to finish the cleaning.
 * </p>
 */
public void attemptShutdown() {
    // wipe the task and its activities.
    Application app = getApplication();
    Intent intent = new Intent(app, ShutdownActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    app.startActivity(intent);
}

The ShutdownActivity is just performing data cleanup before finishing itself like it was told before.

/**
 * This activity is started by {@link Controller#attemptShutdown()} to wipe the
 * entire task and activities. It calls {@link Controller#onTaskWiped()} in
 * {@link #onCreate(Bundle)} and finish immediately after.
 */
public class ShutdownActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // this is where you release the application data.
        Controller.controller.onTaskWiped();

        finish();
    }
}

And finally the Manifest part. I have set the transparent style to avoid the small flash when the activity appears but it does not seem to work well.

<activity android:label="Exiting..."
android:name=".ShutdownActivity"
android:excludeFromRecents="true"
android:theme="@style/Theme.Transparent" />
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
slash33
  • 899
  • 1
  • 11
  • 17
1

you should do this on yourself. read this good blogpost: http://blog.radioactiveyak.com/2010/05/when-to-include-exit-button-in-android.html

alosdev
  • 384
  • 2
  • 14