Eliminar una actividad de la pila de historial


382

Mi aplicación muestra una actividad de registro la primera vez que el usuario ejecuta la aplicación, se ve así:

  1. ActivitySplashScreen (bienvenido al juego, ¿registrarse para obtener una cuenta?)
  2. ActivitySplashScreenSignUp (genial, complete esta información)
  3. ActivityGameMain (pantalla principal del juego)

entonces las actividades se inician entre sí exactamente en ese orden, cuando el usuario hace clic en un botón en cada pantalla.

Cuando el usuario pasa de la actividad n. ° 2 a la n. ° 3, ¿es posible borrar por completo el n. ° 1 y n. ° 2 de la pila de historial? Me gustaría que si el usuario está en el n. ° 3 y presiona el botón Atrás, simplemente vaya a la pantalla de inicio, en lugar de volver a la pantalla de inicio.

Creo que puedo lograr esto con tareas (es decir, comenzar una nueva tarea en el n. ° 3) pero quería ver si había un método más simple,

Gracias


Después de estar en la pantalla de inicio, cuando el usuario reanuda su aplicación, ¿lo lleva a ActivitySplashScreen o ActivityGameMain?
Tamil

Respuestas:


632

Esto se puede conseguir ajustando el android:noHistory atributo que "true"en las correspondientes <activity>entradas en el AndroidManifest.xmlarchivo. Por ejemplo:

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />

12
Esta es la mejor manera de hacerlo.
shkschneider

22
Equivalentemente puedes usar FLAG_ACTIVITY_NO_HISTORY.
Timmmm

34
¿Cómo puedo lograr esto desde el código? Porque no quiero hacer esto todo el tiempo. Me gustaría eliminar una actividad determinada del historial solo en algunas condiciones.
Namratha

8
Solo tenga en cuenta que el uso del atributo noHistory hará que esa actividad finalice, lo que podría causar un comportamiento inesperado con el inicio de sesión de G +, por ejemplo. Consulte: stackoverflow.com/questions/20383878/… Me tomó un tiempo encontrar este error ya que mi aplicación se bloqueaba sin dejar rastro.
Acapulco

13
Es difícil copiar la bandera necesaria, ya que es un enlace, por lo que aquí se puede copiar fácilmente. android:noHistory="true"
MirroredFate

137

Puede utilizar el reenvío para eliminar la actividad anterior de la pila de actividades mientras inicia la siguiente. Hay un ejemplo de esto en APIDemos , pero básicamente todo lo que está haciendo es llamar finish()inmediatamente después de llamar startActivity().


1
Hola Daniel, leí el ejemplo, pero eso solo borrará la pila de historial en 1 actividad, ¿no? Si mi pila se parece a A, B y estoy iniciando C, quiero que C sea la nueva raíz y que borre completamente A y B. En el ejemplo de SDK, llamar a terminar () desde B me dejaría con una pila de A C, ¿no? Gracias.
Mark

1
Puede borrar A cuando inicia B y borrar B cuando inicia C; sin embargo, supongo que no podrás retroceder de B a A si eso es lo que deseas. Tendré que pensar más en esto si eso es un problema.
Dan Lew

3
Mark, para lograr lo que quieres, debes usar la bandera: FLAG_ACTIVITY_CLEAR_TOP. Espero que ayude.
Francisco Junior

3
FLAG_ACTIVITY_CLEAR_TOPno funcionará porque C aún no está en la pila trasera.
Timmmm

1
@DanielLew Hay tantos ejemplos en APIDemos. Tendría el nombre del ejemplo sugerido?
Stephane

52

Sí, eche un vistazo a Intent.FLAG_ACTIVITY_NO_HISTORY .


46
Tenga en cuenta que esto no establece un historial para la actividad que está iniciando. Para no tener historial de la actividad desde la que está iniciando, simplemente lo configuré android:noHistory="true"en el manifiesto.
georgiecasey

1
Esto funciona bien Use intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)para configurar esta bandera.
vovahost

1
@georgiecasey, esto es útil cuando a veces quieres mantenerlo en el historial y, a veces, no lo quieres en el historial.
Vihaan Verma el

24

Probablemente esta no sea la forma ideal de hacerlo. Si alguien tiene una mejor manera, espero poder implementarla. Así es como realicé esta tarea específica con la versión previa 11 sdk.

en cada clase que quiera irse cuando sea hora clara, debe hacer esto:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

entonces el que necesita desencadenar la cadena de estallidos de la pila solo debe llamar a esto cuando desee iniciarlo:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

¡Entonces las actividades no están en la pila!
Recuerde, amigos, que pueden comenzar una actividad y luego comenzar a limpiar detrás de ella, la ejecución no sigue un solo hilo (la interfaz de usuario).


En caso de que alguien se encuentre con esto más tarde, pensé que podría ser importante saberlo, si ha girado la pantalla, Android reiniciará su aplicación de manera útil cuando saque la última actividad de la pila. ¡Solo ten en cuenta esto!
Travis

Esta es una buena respuesta si solo desea eliminar una actividad de la pila condicionalmente dependiendo de lo que haga el usuario en la próxima actividad +1
theMothaShip

23

Una forma que funciona antes de API 11 es comenzar ActivityGameMainprimero, luego, en onCreateesa Actividad, inicie su ActivitySplashScreenactividad. El ActivityGameMainno aparecerá como se llama a startActivity demasiado pronto para el chapoteo.

Luego puede borrar la pila al comenzar ActivityGameMainestableciendo estos indicadores en la intención:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

También debe agregar esto a ActivitySplashScreen:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

De modo que presionar hacia atrás en esa actividad no vuelve a su ActivityGameMain.

Supongo que no desea que la pantalla de bienvenida vuelva a tampoco, para lograr esto, sugiero configurarlo noHistoryen su AndroidManifest.xml. Luego ponga el goBackPressedcódigo en su ActivitySplashScreenSignUpclase en su lugar.

Sin embargo, he encontrado algunas formas de romper esto. Inicie otra aplicación desde una notificación mientras ActivitySplashScreenSignUpse muestra y el historial no se restablece.

La única forma real de evitar esto es en API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

20

Yo uso de esta manera.

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

Gracias. Encontré esto útil en el caso de que hubiera un botón de Inicio en mi menú, y no quería que las actividades apiladas aparecieran una vez que el usuario hizo clic en Inicio desde allí.
ghitesh

8

Sé que llegué tarde a esto (han pasado dos años desde que se hizo la pregunta) pero lo logré interceptando la presión del botón Atrás. En lugar de buscar actividades específicas, solo miro el recuento y si es inferior a 3, simplemente envía la aplicación a la parte posterior (pausa la aplicación y devuelve al usuario lo que se estaba ejecutando antes del lanzamiento). Compruebo menos de tres porque solo tengo una pantalla de introducción. Además, verifico el recuento porque mi aplicación permite al usuario navegar de regreso a la pantalla de inicio a través del menú, por lo que esto les permite retroceder a través de otras pantallas como de costumbre si hay actividades distintas a la pantalla de introducción en la pila.

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}

7

En el manifiesto puedes agregar:

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

Tambien puedes llamar

finish()

inmediatamente después de llamar a startActivity (..)


2
Es mejor usar banderas de actividad que poner cosas en el manifiesto.
Trevor Hart

6

Solo configúrelo noHistory="true"en el archivo de manifiesto . Hace que la actividad se elimine del backstack.


4

Es una locura que nadie haya mencionado esta elegante solución. Esta debería ser la respuesta aceptada.

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

La clave aquí es usar intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); para el intermediario Activity. Una vez que se rompe el enlace del medio, la DashActivityvoluntad será la primera y la última en la pila.

android:noHistory="true"es una mala solución, ya que causa problemas al confiar en el Activitycomo una devolución de llamada, por ejemplo onActivityResult. Esta es la solución recomendada y debe ser aceptada.


1
Esa bandera sonaba demasiado buena para ser verdad. FLAG_ACTIVITY_NO_HISTORY funciona bien y como cabría esperar hasta que se pone la aplicación en segundo plano y luego en primer plano nuevamente mientras se realiza la actividad con la bandera en la parte superior de la pila. Al ir al fondo, la actividad se destruye. Al volver a la aplicación, se verá la actividad anterior de la pila. Definitivamente no quería tal comportamiento.
NeverwinterMoon

4

Es demasiado tarde, pero espero que ayude. La mayoría de las respuestas no apuntan en la dirección correcta. Hay dos banderas simples para tal cosa.

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

Desde documentos de Android:

public static final int FLAG_ACTIVITY_CLEAR_TASK Agregado en API nivel 11

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

actividad que se borrará antes de que comience la actividad. Es decir, la actividad se convierte en la nueva raíz de una tarea que de otro modo estaría vacía, y cualquier actividad anterior ha finalizado. Esto solo se puede usar junto con FLAG_ACTIVITY_NEW_TASK.


1

Simplemente llame a this.finish () antes de startActivity (intent) como este:

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

los usuarios que tengan un error en "esto", deben cambiarlo a "ActivityOne.this"
ninbit

1

La eliminación de una actividad de un historial se realiza al establecer el indicador antes de la actividad que no desea

A-> B-> C-> D

Suponga que A, B, C y D son 4 actividades si desea borrar B y C, luego establezca el indicador

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

En la actividad A y B

Aquí está el bit de código

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);

0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.finishAndRemoveTask();
        }
        else {
            super.finish();
        }

-7

Prueba esto:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

es API Nivel 1, verifique el enlace .


2
¿Qué se supone que debe hacer esto? Definitivamente no resuelve el problema en cuestión.
rodrigo-silveira

¿Estás seguro de que no quisiste decir Intent.FLAG_ACTIVITY_NO_HISTORY?
Riot Goof Woof
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.