¿Cómo mostrar un cuadro de diálogo para confirmar que el usuario desea salir de una actividad de Android?

He estado tratando de mostrar un “¿Quieres salir?” tipo de diálogo cuando el usuario intenta salir de una Actividad.

Sin embargo, no puedo encontrar los enlaces API adecuados. Activity.onUserLeaveHint() inicialmente parecía prometedor, pero no puedo encontrar la forma de detener la Actividad.

En Android 2.0+ esto se vería así:

 @Override public void onBackPressed() { new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle("Closing Activity") .setMessage("Are you sure you want to close this activity?") .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }) .setNegativeButton("No", null) .show(); } 

En versiones anteriores, se vería así:

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //Handle the back button if(keyCode == KeyEvent.KEYCODE_BACK) { //Ask the user if they want to quit new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle(R.string.quit) .setMessage(R.string.really_quit) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //Stop the activity YourClass.this.finish(); } }) .setNegativeButton(R.string.no, null) .show(); return true; } else { return super.onKeyDown(keyCode, event); } } 
 @Override public void onBackPressed() { new AlertDialog.Builder(this) .setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { ExampleActivity.this.finish(); } }) .setNegativeButton("No", null) .show(); } 

Han modificado el código @ user919216 … y lo han hecho compatible con WebView

 @Override public void onBackPressed() { if (webview.canGoBack()) { webview.goBack(); } else { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } } 

Prefiero salir con un doble toque en el botón Atrás que con un Diálogo de salida.

En esta solución, muestra un brindis cuando regresa por primera vez, advirtiendo que otra pulsación cerrará la aplicación. En este ejemplo, menos de 4 segundos.

 private Toast toast; private long lastBackPressTime = 0; @Override public void onBackPressed() { if (this.lastBackPressTime < System.currentTimeMillis() - 4000) { toast = Toast.makeText(this, "Press back again to close this app", 4000); toast.show(); this.lastBackPressTime = System.currentTimeMillis(); } else { if (toast != null) { toast.cancel(); } super.onBackPressed(); } } 

Token de: http://www.androiduipatterns.com/2011/03/back-button-behavior.html

Si no está seguro de si la llamada para “volver” saldrá de la aplicación o llevará al usuario a otra actividad, puede ajustar las respuestas anteriores en un cheque, isTaskRoot (). Esto puede suceder si su actividad principal se puede agregar a la stack de respaldo varias veces, o si está manipulando su historial de back-stack.

 if(isTaskRoot()) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { YourActivity.super.onBackPressed; } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } else { super.onBackPressed(); } 

Usando Lambda:

  new AlertDialog.Builder(this).setMessage(getString(R.string.exit_msg)) .setTitle(getString(R.string.info)) .setPositiveButton(getString(R.string.yes), (arg0, arg1) -> { moveTaskToBack(true); finish(); }) .setNegativeButton(getString(R.string.no), (arg0, arg1) -> { }) .show(); 

También necesita establecer el lenguaje de nivel para admitir java 8 en su gradle.build:

 compileOptions { targetCompatibility 1.8 sourceCompatibility 1.8 } 

Primero elimine super.onBackPressed(); del método onbackPressed() que está debajo del código:

 @Override public void onBackPressed() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MyActivity.this.finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } 

en China, la mayoría de las aplicaciones confirmarán la salida haciendo clic dos veces:

 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().postDelayed(new Runnable() { @Override public void run() { doubleBackToExitPressedOnce=false; } }, 2000); } 

Me gusta un enfoque @GLee y usarlo con un fragmento como el de abajo.

 @Override public void onBackPressed() { if(isTaskRoot()) { new ExitDialogFragment().show(getSupportFragmentManager(), null); } else { super.onBackPressed(); } } 

Diálogo usando Fragmento:

 public class ExitDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(R.string.exit_question) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { getActivity().finish(); } }) .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { getDialog().cancel(); } }) .create(); } } 

esto funciona bien

 @Override public void onBackPressed() { if (mExitOnBackPress) finish(); else { Toast.makeText(this, R.string.msg_confirm_exit, Toast.LENGTH_SHORT).show(); mExitOnBackPress = true; new android.os.Handler().postDelayed(new Runnable() { @Override public void run() { mExitOnBackPress = false; } }, 2000); } } 
 Just put this code in your first activity @Override public void onBackPressed() { if (drawerLayout.isDrawerOpen(GravityCompat.END)) { drawerLayout.closeDrawer(GravityCompat.END); } else { // if your using fragment then you can do this way int fragments = getSupportFragmentManager().getBackStackEntryCount(); if (fragments == 1) { new AlertDialog.Builder(this) .setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { finish(); } }) .setNegativeButton("No", null) .show(); } else { if (getFragmentManager().getBackStackEntryCount() > 1) { getFragmentManager().popBackStack(); } else { super.onBackPressed(); } } } } 

Otra alternativa sería mostrar un Toast / Snackbar en la primera AlertDialog y pedir que vuelva a pulsar Exit , lo cual es mucho menos intrusivo que mostrar un AlertDialog para confirmar si el usuario quiere salir de la aplicación.

Puede usar la DoubleBackPress Android Library para lograr esto con unas pocas líneas de código. Ejemplo de GIF que muestra un comportamiento similar.

Para empezar, agregue la dependencia a su aplicación:

 dependencies { implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1' } 

Luego, en su Actividad, implemente el comportamiento requerido.

 // set the Toast to be shown on FirstBackPress (ToastDisplay - builtin template) // can be replaced by custom action (new FirstBackPressAction{...}) FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this); // set the Action on DoubleBackPress DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() { @Override public void actionCall() { // TODO : Exit the application finish(); System.exit(0); } }; // setup DoubleBackPress behaviour : close the current Activity DoubleBackPress doubleBackPress = new DoubleBackPress() .withDoublePressDuration(3000) // msec - wait for second back press .withFirstBackPressAction(firstBackPressAction) .withDoubleBackPressAction(doubleBackPressAction); 

Finalmente, establezca esto como el comportamiento en retroceso.

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