76

I have two different activities. The first launches the second one. In the second activity, I call System.exit(0) in order to force the application to close, but the first activity is automatically displayed instead of the application returning to the home screen. How can I avoid this, and get the application to return to the home screen?

Makoto
  • 104,088
  • 27
  • 192
  • 230
Arutha
  • 26,088
  • 26
  • 67
  • 80

21 Answers21

87

Short answer: call moveTaskToBack(true) on your Activity instead of System.exit(). This will hide your application until the user wants to use it again.

The longer answer starts with another question: why do you want to kill your application?

The Android OS handles memory management and processes and so on so my advice is just let Android worry about this for you. If the user wants to leave your application they can press the Home button and your application will effectively disappear. If the phone needs more memory later the OS will terminate your application then.

As long as you're responding to lifecycle events appropriately, neither you nor the user needs to care if your application is still running or not.

So if you want to hide your application call moveTaskToBack() and let Android decide when to kill it.

David Webb
  • 190,537
  • 57
  • 313
  • 299
  • 4
    For more information on Dave's argument, take a look at http://stackoverflow.com/questions/2033914/quitting-an-application-is-that-frowned-upon/2034238#2034238 – CommonsWare Jan 11 '10 at 16:32
  • There are legitimate uses for killing an application - I'm making a closed beta for example, and need to close my app if a user doesn't have the appropriate password. – Matt Lyons-Wood Jul 03 '11 at 09:45
  • 4
    @Matt: Why don't you just stop the user at the password screen? If they can't progress past that point, then why do you need to force the app to shutdown? – idbrii Jul 14 '11 at 00:55
  • A special case would be when the user presses the back button to exit the app. The default onKeyUp() handler for this performs a finish() in this situation. But my experience is that finish() does not always clean up memory adequately, while System.exit(0) does. So in that specific situation in which the user has essentially said goodbye to your app, and implicitly has said that she does not want to preserve any state, I've found that calling System.exit(0) does a much better job of cleaning up. – Carl Nov 06 '12 at 23:52
53

The easiest way for achieving this is given below (without affecting Android's native memory management. There is no process killing involved).

  1. Launch an activity using this Intent:

    Intent intent = new Intent(this, FinActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    finish();
    
  2. In the target activity FinActivity.class, call finish() in onCreate.

Steps Explained:

  1. You create an intent that erases all other activities (FLAG_ACTIVITY_CLEAR_TOP) and delete the current activity.

  2. The activity destroys itself. An alternative is that you can make an splash screen in finActivity. This is optional.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jordi
  • 547
  • 4
  • 2
  • 3
    don't you want the startActivity() before the finish() ? – Someone Somewhere Oct 20 '11 at 18:07
  • `FinActivity` has to be your RootActivity right? Using this flag will restart your `FinActivity.class` as mentioned in documentation http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP I have provided an example in my answer below to overcome this. – Darpan Oct 08 '14 at 13:52
  • Working like a charm :) – Radhey Oct 13 '15 at 11:31
  • This does exit the activities and services, but the debugger still shows threads running in the background and it still shows my app pressing the multitasking button. – Stephen M -on strike- Aug 10 '18 at 14:50
45

You should really think about not exiting the application. This is not how Android apps usually work.

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • 2
    Since there is no exit in an android app. Is there a way I can traverse through all the activities of an app so that I call Finish() on each i.e. finish all the activities that have been started ? – Arutha Jan 11 '10 at 16:59
  • 2
    Why do you need to do this? Are the activities in an improper state because you have logged out or some other condition? You can check for this within `onResume` and then `finish` the activity. – James Jan 11 '10 at 20:08
  • 2
    The problem, as a user and a dev, is that the auto memory cleanup in Android doesn't work that well. There are so many "badly behaved" apps out there that my phone does begin to run out of memory and when it gets low, the UI starts to stutter. This is on a relatively high spec (for this time) HTC Desire. I think this is why I and others sometimes ask this question. – Richard Le Mesurier Jul 08 '11 at 08:05
  • 1
    @Richard: Wouldn't a better solution be to stop all activity when onPause is called on your application? The only way an application should cause slowdown is if you still have AsyncTasks etc running when you're paused when they don't need to be. For example games should exit their main loop after onPause. (And an early exit from the loop doesn't count.) – idbrii Jul 14 '11 at 00:53
  • 2
    @pydave: I agree with you. But there seems to be a lot of debate on this type of topic, and I was sharing some "real world" dev & user experience. The fact of the matter is at the moment my phone slows down noticably as available memory decreases. It seems I have apps "in the background" so to speak, which are using up that memory. If I kill those apps, I have experience that my device speeds up. Which makes me think that it would be nice if either 1) devs could write code to totally kill a process and free its memory, or 2) the android GC ran a bit better than it currently does. ymmv – Richard Le Mesurier Jul 15 '11 at 11:19
  • 1
    It doesn't matter whether you have more available memory or not, each app is limited to a certain amount and Android kill processes when more memory is needed. Background apps may however be using the CPU. – Romain Guy Jul 16 '11 at 22:20
  • What if he finds it exiting? – IazertyuiopI Jul 04 '14 at 09:26
  • 1
    @pydave and others making the same mistake: Application has no onPause, and onPause in Activities and Fragments gets called for so many different reasons (like 'overlayed with a network settings screen') that it's ridiculous. Not to mention you just *cannot* stop some background things as they're uninterruptible or need a persistent connection. Apps are not web pages. – kaay Jul 08 '14 at 13:46
  • @kaay: They're not web pages, they're Android apps and they should [behave like it](http://developer.android.com/guide/components/activities.html). (You don't necessarily need to kill all background processes: a downloader that will complete and exit is fine or my podcast app shouldn't kill the player when I go to my home screen). See also [Quitting an application](http://stackoverflow.com/questions/2033914/quitting-an-application-is-that-frowned-upon/2034238#2034238). – idbrii Jul 11 '14 at 22:19
  • I was referring to other things: 1. That the catch-all 'solution' that almost everything more complex than a web page might have (like a BroadcastReceiver) be cleared in onPause is unreasonable; 2. onPause is a method of the app's smaller components, not the app itself, yet 96% of all tutorials are worded as though there only ever is one Activity, or the Activity is the app. Also, 3. A programmer knows better when a complex app should die, than a complex, automated state/process management system designed for the exact opposite - restoring the previous state when possible. nrn. – kaay Jul 14 '14 at 07:56
20

Android has a mechanism in place to close an application safely per its documentation. In the last Activity that is exited (usually the main Activity that first came up when the application started) just place a couple of lines in the onDestroy() method. The call to System.runFinalizersOnExit(true) ensures that all objects will be finalized and garbage collected when the the application exits. For example:

public void onDestroy() {
    super.onDestroy();

    /*
     * Notify the system to finalize and collect all objects of the
     * application on exit so that the process running the application can
     * be killed by the system without causing issues. NOTE: If this is set
     * to true then the process will not be killed until all of its threads
     * have closed.
     */
    System.runFinalizersOnExit(true);

    /*
     * Force the system to close the application down completely instead of
     * retaining it in the background. The process that runs the application
     * will be killed. The application will be completely created as a new
     * application in a new process if the user starts the application
     * again.
     */
    System.exit(0);
}

Finally Android will not notify an application of the HOME key event, so you cannot close the application when the HOME key is pressed. Android reserves the HOME key event to itself so that a developer cannot prevent users from leaving their application.

Danny Remington - OMS
  • 5,244
  • 4
  • 32
  • 21
9

When you launch the second activity, finish() the first one immediately:

startActivity(new Intent(...));
finish();
David Hedlund
  • 128,221
  • 31
  • 203
  • 222
  • 1
    I dont't want to finish the first activity systematically, only if I call the System.exit(0). It's a normal feature ? How the force close button in the Application manager does work ? – Arutha Jan 11 '10 at 14:15
  • 1
    oh. i misread your question then, sorry. that's not how the standard android app lifecycle looks. the FC button uses something similar `android.os.Process.killProcess(android.os.Process.myPid());` which is not how you normally want your apps to exit. but you might use that, or you might consider looking into `startActivityForResult` and `finishActivity`, and building something where the first activity finishes only if the second one finishes with a certain response code. – David Hedlund Jan 11 '10 at 14:39
9

You can also specify noHistory = "true" in the tag for first activity or finish the first activity as soon as you start the second one(as David said).

AFAIK, "force close" kills the process which hosts the JVM in which your application runs and System.exit() terminates the JVM running your application instance. Both are form of abrupt terminations and not advisable for normal application flow.

Just as catching exceptions to cover logic flows that a program might undertake, is not advisable.

Samuh
  • 36,316
  • 26
  • 109
  • 116
  • There is no way to properly close an application and all activities still open? – Arutha Jan 11 '10 at 14:36
  • 2
    No, there's not really an "application" concept in Android; your apps are a collection of Activities. If you don't want to go back to your first activity after finishing the second, then you should use the `noHistory` attribute as mentioned. – Christopher Orr Jan 11 '10 at 14:56
  • It is more about activities and Tasks... http://developer.android.com/guide/topics/fundamentals.html#acttask – Samuh Jan 11 '10 at 15:01
9

I use this method to close the Activities!

public static void closeAllBelowActivities(Activity current) {
    boolean flag = true;
    Activity below = current.getParent();
    if (below == null)
        return;
    System.out.println("Below Parent: " + below.getClass());
    while (flag) {
        Activity temp = below;
        try {
            below = temp.getParent();
            temp.finish();
        } catch (Exception e) {
            flag = false;
        }
    }
}
McDowell
  • 107,573
  • 31
  • 204
  • 267
amsurana
  • 234
  • 3
  • 11
6

android.os.Process.killProcess(android.os.Process.myPid()); works fine, but it is recommended to let the Android platform worry about the memory management:-)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arnab
  • 181
  • 1
  • 2
  • 4
4

I use this:

1) The parent activity call the secondary activity with the method "startActivityForResult"

2) In the secondary activity when is closing:

int exitCode = 1; // Select the number you want
setResult(exitCode);
finish();

3) And in the parent activity override the method "onActivityResult":

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    int exitCode = 1;
    if(resultCode == exitCode) {
        super.setResult(exitCode); // use this if you have more than 2 activities
        finish();
    }
}

This works fine for me.

molda
  • 41
  • 1
4

You can not do System.exit(), it's not safe.

You can do this one: Process.killProcess(Process.myPid());

Cytown
  • 1,539
  • 9
  • 7
4

Use the finish method. It is the simpler and easier method.

this.finish();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nikhil
  • 41
  • 1
2

Say you have activity stack like A>B>C>D>E. You are at activity D, and you want to close your app. This is what you wil do -

In Activity from where you want to close (Activity D)-

Intent intent = new Intent(D.this,A.class);
intent.putExtra("exit", "exit");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

In your RootActivity (ie your base activity, here Activity A) -

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent.hasExtra("exit")) {
            setIntent(intent);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (getIntent() != null) {
            if (("exit").equalsIgnoreCase(getIntent().getStringExtra(("exit")))) {
                onBackPressed();
            }
        }
    }

onNewIntent is used because if activity is alive, it will get the first intent that started it. Not the new one. For more detail - Documentation

Darpan
  • 5,623
  • 3
  • 48
  • 80
2

Keep in mind that when working with applications that use persistent socket connections, the finish() method does not release the connection. Under normal circumstances, finish() is the best option, but if you absolutely need to exit an app and release all resource it's using then use killProcess. I've had no problems using it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PJ420
  • 21
  • 1
2

Start the second activity with startActivityForResult and in the second activity return a value, that once in the onActivityResult method of the first activity closes the main application. I think this is the correct way Android does it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dayerman
  • 3,973
  • 6
  • 38
  • 54
2

Try the following. It works for me.

ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1); 
ComponentName componentInfo = taskInfo.get(0).topActivity;
am.restartPackage(componentInfo.getPackageName());
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sikandar
  • 21
  • 2
2

You are wrong. There is one way to kill an application. In a class with super class Application, we use some field, for example, killApp. When we start the splash screen (first activity) in onResume(), we set a parameter for false for field killApp. In every activity which we have when onResume() is called in the end, we call something like that:

if(AppClass.killApp())
    finish();

Every activity which is getting to the screen have to call onResume(). When it is called, we have to check if our field killApp is true. If it is true, current activities call finish(). To invoke the full action, we use the next construction. For example, in the action for a button:

AppClass.setkillApplication(true);
   finish();
   return;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Peter
  • 21
  • 1
  • android system will not kill the activity on states such as onStart(), onRestart() and onResume() according to documentation. your suggestion is absolutely wrong! – anonim Jul 07 '12 at 09:50
1

This is what I did to close the application: In my application I have a base activity class, I added a static flag called "applicationShutDown". When I need to close the application I set it to true.

In the base activity onCreate and onResume after calling the super calls I test this flag. If the "applicationShutDown" is true I call finish on the current Activity.

This worked for me:

protected void onResume() {
    super.onResume();
    if(BaseActivity.shutDownApp)
    {
        finish();
        return;

    }}
user1942887
  • 94
  • 1
  • 5
1

It's actually quiet easy.

The way I do this is by saving a flag in a static variable available to all. Then, when I exit, I set this flag and all my activities check this flag onResume. If the flag is set then I issue the System.exit on that activity.

That way all activities will check for the flag and will close gracefully if the flag is set.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

It is not recommended, but you can still use this. Better go with this solution in case you need to quit the app.

According to me, the best solution is to finish every activity in your app like below.

Step 1. Maintain a static variable in mainactivity. Say,

public static boolean isQuit = false;

Step 2. On click event of an button, set this variable to true.

mainactivity.isQuit = true;
finish();

Step 3. And in every activity of your application, have the onrestart method as below.

@Override
protected void onRestart() {
    // TODO Auto-generated method stub
    super.onRestart();
    if(mainactivity.isQuit)
        finish();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shankar Agarwal
  • 34,573
  • 7
  • 66
  • 64
0

I solved a similar problem: MainActivity starts BrowserActivity, and I need to close the app, when user press Back in BrowserActivity - not to return in MainActivity. So, in MainActivity:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "sm500_Rmt.MainActivity";
    private boolean m_IsBrowserStarted = false;

and then, in OnResume:

    @Override
protected void onResume() {
    super.onResume();
    if(m_IsBrowserStarted) {
        Log.w(TAG, "onResume, but it's return from browser, just exit!");
        finish();
        return;
    }
    Log.w(TAG, "onResume");

... then continue OnResume. And, when start BrowserActivity:

    Intent intent = new Intent(this, BrowserActivity.class);
    intent.putExtra(getString(R.string.IPAddr), ip);
    startActivity(intent);
    m_IsBrowserStarted = true;

And it looks like it works good! :-)

0

Run the second activity using start activity for result:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);

//This line is important
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

startActivityForResult(intent, REQUEST_CODE);

Add this function to the first Activity:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(rquestCode == REQUEST_CODE)
        if(resultCode == RESULT_CANCELED)
            finish();
}

And add this to the second Activity:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {

        Log.i(TAG, "Back key pressed");
        setResult(RESULT_CANCELED);
        finish();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
piojo
  • 1,919
  • 4
  • 24
  • 40