Termina todas las actividades anteriores.

368

Mi aplicación tiene las siguientes pantallas de flujo:

Home->screen 1->screen 2->screen 3->screen 4->screen 5

Ahora tengo un log out botón común en cada pantalla

( Home/ screen 1 / screen 2 /screen 3/ screen 4 / screen 5)

Quiero que cuando el usuario haga clic en el botón de cerrar sesión (desde cualquier pantalla), todas las pantallas estarán terminadas y Log inse abrirá una nueva pantalla .

He intentado casi todo FLAG_ACTIVITYpara lograr esto. También reviso algunas respuestas en stackoverflow, pero no puedo resolver el problema. Mi aplicación está en Android 1.6, así que no puedo usarFLAG_ACTIVITY_CLEAR_TASK

¿Hay alguna forma de resolver el problema?

Tanmay Mandal
fuente
¿Ejecutas tus actividades anidadas usando startActivityForResult?
woodshy
No, todas las actividades se inician con startActivity.
Tanmay Mandal
Estoy usando actividades anidadas mientras el bacalao ejecuta finishaffinitytask () en la actividad anidada. ¿cambia el comportamiento? como a veces obtengo un error al entregar ResultInfo cuando se ejecuta finishaffinitytask.
Ripal Tamboli
Verifique esta respuesta, seguramente lo ayudará a stackoverflow.com/a/25159180/2732632
Kimmi Dhingra el
3
Android 21 introdujo Activity.finishAndRemoveTask ().
Joseph Johnson

Respuestas:

543

Utilizar:

Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Esto borrará todas las actividades en la parte superior de la casa.

Suponiendo que está terminando la pantalla de inicio de sesión cuando el usuario inicia sesión y se crea la página de inicio y luego todas las pantallas de 1 a 5 encima de esa. El código que publiqué lo devolverá a la pantalla de inicio y finalizará todas las demás actividades. Puede agregar un extra en la intención y leerlo en la actividad de la pantalla de inicio y finalizarlo también (tal vez inicie nuevamente la pantalla de inicio de sesión o algo así).

No estoy seguro, pero también puede intentar iniciar sesión con esta bandera. No sé cómo se ordenarán las actividades en ese caso. Así que no sé si eliminará los que están debajo de la pantalla en la que está, incluido el que está actualmente, pero definitivamente es el camino a seguir.

Espero que esto ayude.

DArkO
fuente
El usuario muestra su primera pantalla como pantalla de inicio, ese es el problema principal.
Tanmay Mandal
bueno, ya que tengo mi respuesta, debes volver a la pantalla de inicio y terminar esa. entonces el proceso llama a la intención anterior desde cualquier pantalla. reciba la intención en la pantalla de inicio y lance al instante una intención de iniciar sesión y termine en casa después del método startActivity. También puede anular la animación pendiente para que sea nula para entrar y salir para que no muestre la transición (lo hago porque se siente un poco más rápido) .Así que debería funcionar bien para lo que necesita.
DArkO
10
En lugar de declarar la actividad como singleInstance, considere usar FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOPcomo indicadores para la intención. Esto terminará las actividades de intervención y comenzará (o traerá de nuevo a primer plano) la actividad deseada.
CommonsWare
13
@ CommonsWare Agregar intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);a mi actividad no me ayudó. No terminó las actividades que intervienen. Cuando presiono hacia atrás desde la pantalla de Inicio de sesión puedo ver las actividades anteriores. Aquí está mi código Intent intent=new Intent(BaseActivity.this, Login.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);startActivity(intent);.
Tanmay Mandal
26
este código solo borra la pila de actividades superior, para borrar todas las actividades intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
Ajay Venugopal
318

Puedes intentarlo Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK. Borrará totalmente todas las actividades anteriores y comenzará una nueva actividad.

Kong Ken
fuente
11
La solución adecuada, pero solo API 11+
riwnodennyk
Terminé usando este indicador adicional ya que no causa un retraso al mostrar la actividad principal (no lo reiniciará, por lo que es mucho más rápido).
Maurizio
2
@riwnodennyk ¿por qué API 11+?
Muhammad Babar
17
Use IntentCompat.FLAG_ACTIVITY_CLEAR_TASK para las versiones anteriores a 11
Steven Pena
2
@ono Sí. Eso deberia ser todo lo que necesitas. Asegúrese de que el modo de inicio de su actividad objetivo esté configurado como "singleTask" en el manifiesto.
Steven Pena
137

Antes de lanzar su nueva Actividad, simplemente agregue el siguiente código:

finishAffinity();

O si quieres que funcione en versiones anteriores de Android:

ActivityCompat.finishAffinity(this);
Henrique
fuente
12
ActivityCompat.finishAffinity (esto); llama a activity.finish () para api <16. Por lo tanto, no funcionará.
Aamir Abro
1
@Beto Caldas, yo mismo he confirmado el código fuente, no funcionará para API <16 como mencionó AamirAbro. Simplemente terminará la actividad que pasas en API <16.
HendraWD
39

Cuando el usuario desea salir de todas las actividades abiertas , debe presionar un botón que carga la primera Actividad que se ejecuta cuando se inicia su aplicación, borrar todas las demás actividades y luego finalizar la última actividad restante. Ejecute el siguiente código cuando el usuario presione el botón de salida. En mi caso, LoginActivityes la primera actividad en ejecutar mi programa.

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

El código anterior borra todas las actividades excepto LoginActivity. Luego ponga el siguiente código dentro de LoginActivity's onCreate(...), para escuchar cuándo LoginActivityse recrea y se pasa la señal' EXIT ':

if (getIntent().getBooleanExtra("EXIT", false)) {
    finish();  
}

¿Por qué es tan difícil hacer un botón de salida en Android?

Android se esfuerza por disuadirlo de tener un botón de "salida" en su aplicación, porque quieren que al usuario nunca le importe si los programas que utilizan se ejecutan en segundo plano o no.

Los desarrolladores del sistema operativo Android quieren que su programa pueda sobrevivir a un apagado inesperado y apagar el teléfono, y cuando el usuario reinicia el programa, retoman el punto donde lo dejaron. Por lo tanto, el usuario puede recibir una llamada telefónica mientras usa su aplicación y abrir mapas que requieren que su aplicación se libere para obtener más recursos.

Cuando el usuario reanuda su aplicación, retoma justo donde lo dejó sin interrupción. Este botón de salida está usurpando el poder del administrador de actividades, lo que puede causar problemas con el ciclo de vida del programa Android administrado automáticamente.

Eric Leschinski
fuente
31
Intent intent = new Intent(this, classObject);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

Esto funcionará para todas las versiones de Android. Donde se IntentCompatagregó la clase en la biblioteca de soporte de Android.

Joya
fuente
IntentCompat.FLAG_ACTIVITY_CLEAR_TASKno se reconoce, use en Intentlugar de IntentCompat.
CoolMind
30

Use lo siguiente para la actividad

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

eliminar el indicador CLEAR_TASK para el uso de fragmentos.

Espero que esto pueda usarse para algunas personas.

Aristo Michael
fuente
24

Supongo que llego tarde pero hay una respuesta simple y corta. Hay un método finishAffinity () en Activity que finalizará la actividad actual y todas las actividades principales, pero solo funciona en Android 4.1 o superior.

Para API 16+, use

finishAffinity();

Para menores de 16 años, use

ActivityCompat.finishAffinity(YourActivity.this);

¡Espero eso ayude!

Akshay Taru
fuente
21

Desde developer.android.com :

public void finishAffinity ()

Agregado en API nivel 16

Finalice esta actividad, así como todas las actividades inmediatamente debajo de ella en la tarea actual que tengan la misma afinidad. Esto normalmente se usa cuando una aplicación se puede iniciar en otra tarea (como desde una ACTION_VIEW de un tipo de contenido que comprende) y el usuario ha utilizado la navegación hacia arriba para cambiar de la tarea actual a su propia tarea. En este caso, si el usuario se ha desplazado hacia abajo a cualquier otra actividad de la segunda aplicación, todas ellas deben eliminarse de la tarea original como parte del cambio de tarea.

Tenga en cuenta que este final no le permite entregar resultados a la actividad anterior, y se lanzará una excepción si está intentando hacerlo.

gmrl
fuente
19

En una nota al margen, es bueno saber que
esta respuesta funciona ( https://stackoverflow.com/a/13468685/7034327 )

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
this.finish();

mientras que esto no funciona

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

.setFlags() reemplaza cualquier indicador anterior y no agrega ningún indicador nuevo mientras lo .addFlags()hace.

Entonces esto también funcionará

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Juan
fuente
Gran explicación sobre la diferencia entre setFlag vs addFlag, gracias
Pelanes
13

Si su aplicación tiene un mínimo de SDK versión 16, entonces puede usar finishAffinity ()

Finalice esta actividad, así como todas las actividades inmediatamente debajo de ella en la tarea actual que tengan la misma afinidad.

Esto es trabajo para mí En la pantalla de Pago superior, elimine todas las actividades de back-stack,

@Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29

Jaydeep purohit
fuente
10

Una solución que implementé para esto (creo que la encontré en Stack Overflow en alguna parte, pero no lo recuerdo, así que gracias a quien hizo eso en primer lugar):

Desde cualquiera de sus actividades, haga esto:

// Clear your session, remove preferences, etc.
Intent intent  = new Intent(getBaseContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Luego, en su LoginActivity, sobrescriba onKeyDown:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
Andy
fuente
3
Esa suele ser una muy mala idea, aunque puede funcionar, presenta un punto de contacto que puede romperse en el futuro y será difícil de depurar. Te lo digo por experiencia :)
Martin Marconcini
10

Para el botón de cierre de sesión en la última pantalla de la aplicación, use este código en el botón de escucha de cierre de sesión para finalizar todas las actividades anteriores abiertas, y su problema está resuelto.

{
Intent intent = new Intent(this, loginScreen.class);
ntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
Amrit
fuente
8
    Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();
Prashant Kumar
fuente
66
¿ Por qué FLAG_ACTIVITY_CLEAR_TASK dos veces?
Choletski
1
Por lo que entiendo, .setFlags reemplaza las banderas anteriores y no agrega ninguna bandera. .addFlags es lo que querías usar, supongo. Causa todo el código anterior i1.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); se
borra
addFlags funciona para mí
Jamil
1
setFlagsreemplazará todos los anteriores, por lo que el último setFlagssolo es válido, los anteriores se reemplazan. Entonces no necesita llamari1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mtrakal
8

Tengo el mismo problema que puedes usar IntentCompat, así:

import android.support.v4.content.IntentCompat;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);

Este código funciona para mí.

API de Android 17

Adnan Abdollah Zaki
fuente
8

En mi caso, utilizo la finishAffinity()función en la última actividad como:

finishAffinity()
startHomeActivity()

Espero que te sea útil.

Djek-Grif
fuente
7

en lugar de usar finish()solo usarfinishAffinity();

Hitesh Kushwah
fuente
1
Buena respuesta pero requiere API 16
Akshay Taru
6

Iniciar sesión> Inicio-> pantalla 1-> pantalla 2-> pantalla 3-> pantalla 4-> pantalla 5

en la pantalla 4 (o cualquier otra) ->

StartActivity (Iniciar sesión)
con
FLAG_ACTIVITY_CLEAR_TOP

Plamen Nikolov
fuente
2
Cuando presiono el botón Atrás, todas las actividades anteriores se muestran en el orden en que estaban. Esas actividades deben cerrarse, cuando se hace clic en el botón Cerrar sesión, solo habrá una actividad en la pila y esa será la actividad de inicio de sesión. pantalla de inicio de sesión. El usuario comienza desde la pantalla de inicio.
Tanmay Mandal
6

para API> = 15 a API 23 solución simple.

 Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
 nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
 startActivity(nextScreen);
 ActivityCompat.finishAffinity(currentActivity.this);
Kamal Bunkar
fuente
Elabore su respuesta para que todos puedan beneficiarse de ella.
Shubhamoy el
5

Si está utilizando startActivityForResult()en sus actividades anteriores, simplemente anule OnActivityResult()y llame al finish();método dentro de él en todas las actividades. Esto hará el trabajo ...

ngesh
fuente
No, startActivitysolo estoy usando .
Tanmay Mandal
Será difícil de mantener onActivityResulten cada actividad. He implementado la sugerencia de DArkO y he logrado mi objetivo y gracias por la ayuda.
Tanmay Mandal
3

Cuando el usuario haga clic en el botón Cerrar sesión, escriba el siguiente código:

Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Y también cuando, después de iniciar sesión, si llama a una nueva actividad, no use finish ();

nikki
fuente
2

Simplemente, cuando salga de la pantalla de inicio de sesión, no cuando termine la pantalla de inicio de sesión.

Y luego, en todas las actividades hacia adelante, use esto para cerrar sesión:

final Intent intent = new Intent(getBaseContext(), LoginScreen.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

Funciona perfectamente

Asad Rao
fuente
1

Si inicia sesión en el usuario screen 1y desde allí va a las otras pantallas, use

Intent intent = new Intent(this, Screen1.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Gabriel Negut
fuente
Cuando presiono el botón Atrás, todas las actividades anteriores se muestran en el orden en que estaban. Esas actividades deben cerrarse, cuando se hace clic en el botón Cerrar sesión, solo habrá una actividad en la pila y será la actividad de inicio de sesión.
Tanmay Mandal
Si desea este comportamiento, debe anular onKeyDowny onBackPressed(o onKeyDown, si desea admitir versiones de Android <2.0) en cada una de sus actividades (excepto la de inicio de sesión), y startActivity(login)allí como se muestra arriba.
Gabriel Negut
Tengo un botón que me llevará a la pantalla de inicio de sesión para finalizar todas las actividades en la pila. ¿Es posible?
Tanmay Mandal
1

Encontré de esta manera, borrará todo el historial y saldrá

Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
Intent intent = new Intent(getApplicationContext(), SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

finish();
System.exit(0);
pirooz jenabi
fuente
1

Supongo que llego tarde pero hay una respuesta simple y corta. Hay un método finishAffinity () en Activity que finalizará la actividad actual y todas las actividades principales, pero solo funciona en Android 4.1 o superior.

Para API 16+, use

finishAffinity ();

Para menores de 16 años, use

ActivityCompat.finishAffinity (YourActivity.this);

¡Espero eso ayude!

shareedit respondió mayo 27 '18 a las 8:03

Akshay Taru

Samuel Quiroz
fuente
0

Encontré que esta solución funciona en todos los dispositivos a pesar del nivel de API (incluso para <11)

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);
priyankvex
fuente
0

La mejor manera de cerrar todas las actividades anteriores y borrar la memoria

finishAffinity()
System.exit(0);
Shivam Tripathi
fuente
0
startActivity(
                Intent(this, LoginActivity::class.java)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .addFlags(FLAG_ACTIVITY_CLEAR_TASK)
            )
Kishan Solanki
fuente