10

I'm new to Android development and I want it so when the user presses the back button on the main activity, a toast message appears with a "confirm exit by pressing the back button again" message. How would I do this? This is what I have so far:

@Override
public void onBackPressed() {
    // TODO Auto-generated method stub
    super.onBackPressed();
    Toast s = Toast.makeText(getBaseContext(), "Press back again to exit", Toast.LENGTH_LONG);
    s.show();
    wait();

    public boolean onBackPressed() {
        finish();    
    }
}
Michał Šrajer
  • 30,364
  • 7
  • 62
  • 85
  • Is the toast showing? What is/isn't working? It may be better to have a counter in there and if the counter = 2 then finish. Or use a dialog instead of a toast – codeMagic Dec 22 '12 at 20:52
  • Best solution in: http://stackoverflow.com/questions/8430805/android-clicking-twice-the-back-button-to-exit-activity – Codelaby Feb 17 '16 at 15:21

6 Answers6

21

I would just save the time of the backpress and then compare the time of the latest press to the new press.

long lastPress;
@Override
public void onBackPressed() {
    long currentTime = System.currentTimeMillis();
    if(currentTime - lastPress > 5000){
        Toast.makeText(getBaseContext(), "Press back again to exit", Toast.LENGTH_LONG).show();
        lastPress = currentTime;
    }else{
        super.onBackPressed();
    }
}

You can also dismiss the toast when the app the back press is confirmed (cred @ToolmakerSteve):

long lastPress;
Toast backpressToast;
@Override
public void onBackPressed() {
    long currentTime = System.currentTimeMillis();
    if(currentTime - lastPress > 5000){
        backpressToast = Toast.makeText(getBaseContext(), "Press back again to exit", Toast.LENGTH_LONG);
        backpressToast.show();
        lastPress = currentTime;
    } else {
        if (backpressToast != null) backpressToast.cancel();
        super.onBackPressed();
    }
}
Heinrisch
  • 5,835
  • 4
  • 33
  • 43
  • Thank you, this is what I was wanting to do! With a toast rather than a dialogbox :) –  Dec 22 '12 at 20:58
  • this is the proper solution for those who are wandering on many other topics! – sandalone Jul 11 '13 at 07:01
  • 1
    Also see user8218's enhancement of this, which removes the toast as soon as user presses back the second time: http://stackoverflow.com/a/18654014/199364 HOWEVER user8218's answer is WRONG as written; submitting a change that I explain in a comment on that; hopefully my change will be accepted. – ToolmakerSteve Sep 22 '16 at 08:44
  • @ToolmakerSteve updated my answer, please verify that it looks good. – Heinrisch Sep 22 '16 at 09:30
  • 1
    Looks great! Thanks. (No need for people to look at user8218's answer now; this answer is complete. Thanks to user8218 for the idea. If you like that addition, consider upvoting that answer also.) – ToolmakerSteve Sep 22 '16 at 09:56
  • An alternative answer to consider [here](http://stackoverflow.com/a/15728990/199364). I haven't decided yet which approach I prefer. – ToolmakerSteve Sep 22 '16 at 10:22
  • I have 2 remarks about this solution. First, the toast duration is 2000ms for `LENGTH_SHORT` and 3500ms for `LENGTH_LONG`. So maybe it would be better to use the corresponding value instead of 5000. The documentation says that _this time could be user-definable_. I couldn't find how to retrieve the actual value, which would have been better. Second, if you use a Drawer Menu for example, `super.onBackPressed()` will go back to the previous fragment and won't exit the app. So it's better to explicitly close the app with `finish()` instead of relying on `super.onBackPressed()`. – Thomas Feb 02 '21 at 13:51
3
private long mLastPress = 0;
const int TOAST_DURATION = 5000;
Toast onBackPressedToast;
@Override
public void onBackPressed() {
    long currentTime = System.currentTimeMillis();
    if (currentTime - mLastPress > TOAST_DURATION) {
        onBackPressedToast = Toast.makeText(this, R.string.press_once_again_to_exit, Toast.LENGTH_SHORT);
        onBackPressedToast.show();
        mLastPress = currentTime;
    } else {
        if (onBackPressedToast != null) {
            onBackPressedToast.cancel();  //Difference with previous answer. Prevent continuing showing toast after application exit.
            onBackPressedToast = null;
        }
        super.onBackPressed();
    }
}
ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
resource8218
  • 1,445
  • 1
  • 20
  • 33
  • In the previous answer the toast is only created on the first back press and that toast is not canceled in your answer. – Heinrisch May 22 '15 at 15:16
  • [Submitted as an edit] Can fix this (per @Heinrisch' comment) by holding toast in a field outside the method: `Toast onBackPressedToast;` before the method. Then move `onBackPressedToast = Toast...` INSIDE the `if`. In the `else`, protect the cancel with `if (onBackPressedToast != null)`. – ToolmakerSteve Sep 22 '16 at 08:50
  • Also need `const int TOAST_DURATION = 5000;` – ToolmakerSteve Sep 22 '16 at 09:07
  • ... and might as well set toast variable to null, when we cancel it. – ToolmakerSteve Sep 22 '16 at 09:42
  • @ToolmakerSteve Why should we set the toast to null if the app will quit anyway? – Thomas Feb 01 '21 at 17:56
  • @Thomas - you are right, that is not necessary, given that we know the app is exiting. (Its a habit to clean up resources of variables outside of the method.) – ToolmakerSteve Feb 01 '21 at 18:11
1

work perfectly in my case

private static long back_pressed;

@Override
public void onBackPressed()
{
        if (back_pressed + 2000 > System.currentTimeMillis()) 
               super.onBackPressed();
        else 
             Toast.makeText(getBaseContext(), "Press once again to exit!", Toast.LENGTH_SHORT).show();
        back_pressed = System.currentTimeMillis();
}
Bhavesh Jethani
  • 3,891
  • 4
  • 24
  • 42
  • Please explain the differences from the most-upvoted answer that existed two years before this. What is different, and how is this an improvement over that answer? Also, what justifies making this a new answer, rather than a comment on that answer? (IMHO, it better serves future readers to suggest *small* changes in comments on an existing answer, rather than creating a whole new answer.) – ToolmakerSteve Sep 22 '16 at 09:46
0

In newer version you can use the snackbar instead of toast.

import android.support.design.widget.Snackbar;
...
Snackbar.make(content, "Click BACK again to exit", Snackbar.LENGTH_SHORT).setAction("Action", null).show();
...
MobileOS
  • 13
  • 6
0

After having to implement the same behaviour many a times, decided to go aboiut building a library for the same : DoubleBackPress Android Library. It provides many easy to use templates and the double back press behaviour without all the hassle.

Just do :

// set the ToastDisplay to be shown on FirstBackPress
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);

// set the Action on DoubleBackPress
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
    @Override
    public void actionCall() {
        finish();
    }
};

// setup DoubleBackPress behaviour
DoubleBackPress doubleBackPress = new DoubleBackPress()
        .withDoublePressDuration(3000)
        .withFirstBackPressAction(firstBackPressAction)
        .withDoubleBackPressAction(doubleBackPressAction);

Finally, override the onBackPressed with DoubleBackPress behaviour for the back press.

@Override
public void onBackPressed() {
    doubleBackPress.onBackPressed();
}

Example GIF for similar behaviour

Kaushik NP
  • 6,733
  • 9
  • 31
  • 60
0

Best and simple solution with Toast

In Java

private Toast exitToast;

@Override
public void onBackPressed() {
    if (exitToast == null || exitToast.getView() == null || exitToast.getView().getWindowToken() == null) {
        exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_LONG);
        exitToast.show();
    } else {
        exitToast.cancel();
        finish();
    }
}

In Kotlin

private var exitToast: Toast? = null

override fun onBackPressed() {
    if (exitToast == null || exitToast!!.view == null || exitToast!!.view.windowToken == null) {
        exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_LONG)
        exitToast!!.show()
    } else {
        exitToast!!.cancel()
        finish()
    }
}
Karthik Kompelli
  • 2,104
  • 1
  • 19
  • 22