Clicking the back button twice to exit an activity

2019-01-01 11:33发布

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 :)

30条回答
无与为乐者.
2楼-- · 2019-01-01 12:21

Here is the full working code. And also don't forget to remove the callbacks so that it don't cause a memory leak in the app. :)

private boolean backPressedOnce = false;
private Handler statusUpdateHandler;
private Runnable statusUpdateRunnable;

public void onBackPressed() {
        if (backPressedOnce) {
            finish();
        }

        backPressedOnce = true;
        final Toast toast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT);
        toast.show();

        statusUpdateRunnable = new Runnable() {
            @Override
            public void run() {
                backPressedOnce = false;
                toast.cancel();  //Removes the toast after the exit.
            }
        };

        statusUpdateHandler.postDelayed(statusUpdateRunnable, 2000);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (statusUpdateHandler != null) {
        statusUpdateHandler.removeCallbacks(statusUpdateRunnable);
    }
}
查看更多
有味是清欢
3楼-- · 2019-01-01 12:23

I use this

import android.app.Activity;
import android.support.annotation.StringRes;
import android.widget.Toast;

public class ExitApp {

    private static long lastClickTime;

    public static void now(Activity ctx, @StringRes int message) {
        now(ctx, ctx.getString(message), 2500);
    }

    public static void now(Activity ctx, @StringRes int message, long time) {
        now(ctx, ctx.getString(message), time);
    }

    public static void now(Activity ctx, String message, long time) {
        if (ctx != null && !message.isEmpty() && time != 0) {
            if (lastClickTime + time > System.currentTimeMillis()) {
                ctx.finish();
            } else {
                Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show();
                lastClickTime = System.currentTimeMillis();
            }
        }
    }

}

use to in event onBackPressed

@Override
public void onBackPressed() {
   ExitApp.now(this,"Press again for close");
}

or ExitApp.now(this,R.string.double_back_pressed)

for change seconds need for close, specified miliseconds

ExitApp.now(this,R.string.double_back_pressed,5000)

查看更多
步步皆殇っ
4楼-- · 2019-01-01 12:24

Here, I have generalized write the code for N tap counts. The code is similarly written for the Enable Developer option in android device phone. Even you can use this to enable features while developer testing the app.

 private Handler tapHandler;
 private Runnable tapRunnable;
 private int mTapCount = 0;
 private int milSecDealy = 2000;

onCreate(){
 ...
tapHandler = new Handler(Looper.getMainLooper());

 }

Call askToExit() on backpress or logout option.

private void askToExit() {
   if (mTapCount >= 2) {
    releaseTapValues();
    /* ========= Exit = TRUE  =========  */
   }

   mTapCount++;
   validateTapCount();
  }


  /* Check with null to avoid create multiple instances of the runnable */
  private void validateTapCount() {
   if (tapRunnable == null) {
    tapRunnable = new Runnable() {
     @Override
     public void run() {
      releaseTapValues();
      /* ========= Exit = FALSE  =========  */
     }
    };
    tapHandler.postDelayed(tapRunnable, milSecDealy);
   }
  }

  private void releaseTapValues() {
   /* Relase the value  */
   if (tapHandler != null) {
    tapHandler.removeCallbacks(tapRunnable);
    tapRunnable = null; /* release the object */
    mTapCount = 0; /* release the value */
   }
  }


  @Override
  protected void onDestroy() {
   super.onDestroy();
   releaseTapValues();
  }
查看更多
长期被迫恋爱
5楼-- · 2019-01-01 12:25

Zefnus's answer using System.currentTimeMillis() is the best one (+1). The way I did it is not better than that, but still posting it to add to the above ideas.

If the toast is not visible when the back button is pressed, the toast is displayed, whereas, if it is visible (back has already been pressed once within the last Toast.LENGTH_SHORT time), then it exits.

exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT);
.
.
@Override
public void onBackPressed() {
   if (exitToast.getView().getWindowToken() == null) //if toast is currently not visible
      exitToast.show();  //then show toast saying 'press againt to exit'
   else {                                            //if toast is visible then
      finish();                                      //or super.onBackPressed();
      exitToast.cancel();
   }
}
查看更多
回忆,回不去的记忆
6楼-- · 2019-01-01 12:26

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.

查看更多
一个人的天荒地老
7楼-- · 2019-01-01 12:27

For this purpose I have implemented the following function:

private long onRecentBackPressedTime;
@Override
public void onBackPressed() {
    if (System.currentTimeMillis() - onRecentBackPressedTime > 2000) {
       onRecentBackPressedTime = System.currentTimeMillis();
       Toast.makeText(this, "Please press BACK again to exit", Toast.LENGTH_SHORT).show();
       return;
     }
   super.onBackPressed();
}
查看更多
登录 后发表回答