Borre toda la stack de historial y comience una nueva actividad en Android

¿Es posible comenzar una actividad en la stack, borrando todo el historial anterior?

La situación

Tengo una stack de actividades que va A-> B-> C o B-> C (la pantalla A selecciona el token de los usuarios, pero muchos usuarios solo tienen un token).

En la pantalla C el usuario puede realizar una acción que invalide la pantalla B, por lo que la aplicación desea llevarlos a la pantalla A, independientemente de si ya está en la stack. La pantalla A debería ser el único elemento en la stack en mi aplicación.

Notas

Hay muchas otras preguntas similares, pero no he encontrado nada que responda esta pregunta exacta. Intenté llamar a getParent().finish() : esto siempre da como resultado una excepción de puntero nulo. FLAG_ACTIVITY_CLEAR_TOP solo funciona si la actividad ya está en la stack.

En el nivel 11 de API, se agregó una nueva bandera de intención solo para esto: Intent.FLAG_ACTIVITY_CLEAR_TASK

Solo para aclarar, usa esto:

 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 

Desafortunadamente para API lvl < = 10, aún no he encontrado una solución limpia para esto. La solución "DontHackAndroidLikeThis" es en realidad piratería pura. No deberías hacer eso. :)

Editar: Según el comentario de @Ban Pearson , para API < = 10 ahora uno puede usar la clase IntentCompat para lo mismo. Uno puede usar el indicador IntentCompat.FLAG_ACTIVITY_CLEAR_TASK para borrar la tarea. Por lo tanto, también es compatible con el nivel pre API 11.

Caso 1: Solo dos actividades A y B:

Aquí el flujo de actividad es A-> B. Al hacer clic en el botón A desde B, debemos cerrar la aplicación y al iniciar la actividad B desde A simplemente llamar a finish () esto evitará que android almacene la actividad A en Backstack.eg para la actividad A es Pantalla de aplicación Loding / Splash.

 Intent newIntent = new Intent(A.this, B.class); startActivity(newIntent); finish(); 

Caso 2: más de dos actividades:

Si hay un flujo como A-> B-> C-> D-> B y al hacer clic en el botón Atrás en la Actividad B mientras proviene de la Actividad D. En ese caso deberíamos usar.

 Intent newIntent = new Intent(D.this,B.class); newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(newIntent); 

Aquí la actividad B se iniciará desde la backstack en lugar de una instancia nueva debido a Intent.FLAG_ACTIVITY_CLEAR_TOP y Intent.FLAG_ACTIVITY_NEW_TASK borrará la stack y la convertirá en la superior. Así que cuando presionemos el botón Atrás, toda la aplicación finalizará.

Con la versión más nueva de Android> = API 16 use finishAffinity()

enfoque es adecuado para> = API 16.

 Intent mIntent = new Intent(mContext,MainActivity.class); finishAffinity(); startActivity(mIntent); 
  • Es lo mismo que iniciar una nueva actividad y borrar toda la stack.
  • O reinicie a MainActivity / FirstActivity.

Pasé unas horas en esto también … y acepto que FLAG_ACTIVITY_CLEAR_TOP suena como lo que querrías: borrar toda la stack, excepto la actividad que se está iniciando, por lo que el botón Atrás sale de la aplicación. Sin embargo, como mencionó Mike Repass, FLAG_ACTIVITY_CLEAR_TOP solo funciona cuando la actividad que estás lanzando ya está en la stack; cuando la actividad no está allí, la bandera no hace nada.

¿Qué hacer? Ponga en marcha la actividad en la stack con FLAG_ACTIVITY_NEW_TASK, que convierte esa actividad en el inicio de una nueva tarea en la stack del historial. A continuación, agregue el indicador FLAG_ACTIVITY_CLEAR_TOP.

Ahora, cuando FLAG_ACTIVITY_CLEAR_TOP va a buscar la nueva actividad en la stack, estará allí y se levantará antes de que todo lo demás se borre.

Aquí está mi función de cierre de sesión; el parámetro Ver es el botón al que está asociada la función.

 public void onLogoutClick(final View view) { Intent i = new Intent(this, Splash.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(i); finish(); } 

No deberías cambiar la stack. El botón Atrás de Android debería funcionar como en un navegador web.

Puedo pensar en una forma de hacerlo, pero es bastante complicado.

  • Realice sus Actividades singleTask agregándolo al Ejemplo AndroidManifest :

       
  • Extiende la Application que mantendrá la lógica de a dónde ir.

Ejemplo:

 public class DontHackAndroidLikeThis extends Application { private Stack classes = new Stack(); public Activity getBackActivity() { return classes.pop(); } public void addBackActivity(Activity activity) { classes.push(activity); } } 

De A a B:

 DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication(); app.addBackActivity(A.class); startActivity(this, B.class); 

De B ​​a C:

 DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication(); app.addBackActivity(B.class); startActivity(this, C.class); 

Cª:

 If ( shouldNotGoBackToB() ) { DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication(); app.pop(); } 

y maneja el botón Atrás para pop() desde la stack.

Una vez más, no deberías hacer esto 🙂

Inmediatamente después de comenzar una nueva actividad, utilizando startActivity , asegúrese de llamar a finish() para que la actividad actual no se apile detrás de la nueva.

Prueba esto:

 Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class); logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(logout_intent); finish(); 
 Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(i); 

Encontré un hack muy simple, solo agregue un nuevo elemento en AndroidManifest como:

  

android:noHistory borrará tu actividad no deseada de Stack.

A veces, su emulador de Android puede fallar al conectar la herramienta eclipse DDMS y solicitar que adb comience manualmente. En ese caso, puede iniciar o detener el adb usando el símbolo del sistema.