Clicking the back button twice to exit an activity
I've noticed this pattern in a lot of Android apps and games recently: when clicking the back button to "exit" the application, a Toast
comes up with a message similar to "Please click BACK again to exit".
I was wondering, as I'm seeing it more and more often, is that a built-in feature that you can somehow access in an activity? I've looked at the source code of many classes but I can't seem to find anything about that.
Of course, I can think about a few ways to achieve the same functionality quite easily (the easiest is probably to keep a boolean in the activity that indicates whether the user already clicked once...) but I was wondering if there's something already here.
EDIT: As @LAS_VEGAS mentioned, I didn't really mean "exit" in the traditional meaning. (i.e. terminated) I meant "going back to whatever was open before the application start activity was launched", if that makes sense :)
In Java Activity:
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
In Kotlin Activity:
private var doubleBackToExitPressedOnce = false
override fun onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed()
return
}
this.doubleBackToExitPressedOnce = true
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show()
Handler(Looper.getMainLooper()).postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
}
I Think this handler helps to reset the variable after 2 second.
Sudheesh B Nair's has a nice (and accepted) answer on the question, which i think should have a better alternative such as;
What's wrong with measuring time passed and checking if TIME_INTERVAL
miliseconds (say 2000) passed since the last back press. The following sample code uses System.currentTimeMillis();
to store the time onBackPressed()
is called;
private static final int TIME_INTERVAL = 2000; // # milliseconds, desired time passed between two back presses.
private long mBackPressed;
@Override
public void onBackPressed()
{
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
super.onBackPressed();
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
Back on accepted answer critique; Using a flag
to indicate if it was pressed in last TIME_INTERVAL
(say 2000) milliseconds and set - reset is via Handler
's postDelayed()
method was the first thing to come in my mind. But the postDelayed()
action should be cancelled when activity is closing, removing the Runnable
.
In order to remove the Runnable
, it must not be declared anonymous, and be declared as member along with the Handler
aswell. Then removeCallbacks()
method of Handler
can be called appropriately.
The following sample is the demonstration;
private boolean doubleBackToExitPressedOnce;
private Handler mHandler = new Handler();
private final Runnable mRunnable = new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
};
@Override
protected void onDestroy()
{
super.onDestroy();
if (mHandler != null) { mHandler.removeCallbacks(mRunnable); }
}
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mRunnable, 2000);
}
Thanks to @NSouth for contributing; In order to prevent toast message appearing even after the application is closed, Toast
can be declared as a member - say mExitToast
- and can be cancelled via mExitToast.cancel();
just before super.onBackPressed();
call.
Just thought I would share how I did it in the end, I just added in my activity:
private boolean doubleBackToExitPressedOnce = false;
@Override
protected void onResume() {
super.onResume();
// .... other stuff in my onResume ....
this.doubleBackToExitPressedOnce = false;
}
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, R.string.exit_press_back_twice_message, Toast.LENGTH_SHORT).show();
}
And it just works exactly as I want. Including the reset of the state whenever the activity is resumed.