Al cerrar sesión, borre la pila del historial de actividades, evitando que el botón "atrás" abra actividades en las que solo se ha iniciado sesión.
Todas las actividades en mi aplicación requieren que un usuario inicie sesión para poder verlas. Los usuarios pueden cerrar sesión en casi cualquier actividad. Este es un requisito de la aplicación. En cualquier momento, si el usuario cierra sesión, quiero enviarlo al inicio de sesión Activity
. En este punto, quiero que esta actividad esté en la parte inferior de la pila del historial para que al presionar el botón "atrás" el usuario regrese a la pantalla de inicio de Android.
He visto esta pregunta formulada en diferentes lugares, todas respondidas con respuestas similares (que describo aquí), pero quiero plantearla aquí para recopilar comentarios.
Intenté abrir la actividad de inicio de sesión configurando sus Intent
indicadores, FLAG_ACTIVITY_CLEAR_TOP
lo que parece funcionar como se describe en la documentación, pero no logro mi objetivo de colocar la actividad de inicio de sesión en la parte inferior de la pila del historial y evitar que el usuario regrese. a actividades registradas previamente vistas. También intenté usarlo android:launchMode="singleTop"
para la actividad de inicio de sesión en el manifiesto, pero esto tampoco logra mi objetivo (y parece no tener ningún efecto de todos modos).
Creo que necesito borrar el historial o finalizar todas las actividades abiertas anteriormente.
Una opción es que cada actividad onCreate
verifique el estado de inicio de sesión y, finish()
si no, de inicio de sesión. No me gusta esta opción, ya que el botón Atrás seguirá estando disponible para su uso, navegando hacia atrás a medida que las actividades se cierran solas.
La siguiente opción es mantener una LinkedList
serie de referencias a todas las actividades abiertas a las que se pueda acceder estáticamente desde cualquier lugar (quizás usando referencias débiles). Al cerrar sesión, accederé a esta lista y recorreré todas las actividades abiertas anteriormente, invocando finish()
cada una de ellas. Probablemente comenzaré a implementar este método pronto.
Sin embargo , prefiero usar algunos Intent
trucos de banderas para lograr esto. Estaría más que feliz de saber que puedo cumplir con los requisitos de mi aplicación sin tener que usar ninguno de los dos métodos que describí anteriormente.
¿Hay alguna manera de lograr esto mediante el uso Intent
de la configuración de manifiesto, o mi segunda opción, mantener una LinkedList
de actividades abiertas, es la mejor opción? ¿O hay otra opción que estoy pasando por alto por completo?
Puedo sugerirle otro enfoque, en mi humilde opinión, más sólido. Básicamente, necesita transmitir un mensaje de cierre de sesión a todas sus actividades que deben permanecer en estado de inicio de sesión. Para que pueda utilizar sendBroadcast
e instalar BroadcastReceiver
en todas sus actividades. Algo como esto:
/** on your logout method:**/
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_LOGOUT");
sendBroadcast(broadcastIntent);
El receptor (actividad asegurada):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**snip **/
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.package.ACTION_LOGOUT");
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive","Logout in progress");
//At this point you should start the login activity and finish this one
finish();
}
}, intentFilter);
//** snip **//
}
Parece un rito de iniciación que un nuevo programador de Android pase un día investigando este tema y leyendo todos estos hilos de StackOverflow. Ahora soy recién iniciado y dejo aquí huella de mi humilde experiencia para ayudar a un futuro peregrino.
En primer lugar, según mi investigación, no existe una forma obvia o inmediata de hacer esto. (as of September 2012).
Uno pensaría que podría ser simple, startActivity(new Intent(this, LoginActivity.class), CLEAR_STACK)
pero no .
PUEDE hacerlo startActivity(new Intent(this, LoginActivity.class))
, FLAG_ACTIVITY_CLEAR_TOP
y esto hará que el marco busque en la pila, encuentre su instancia original anterior de LoginActivity, la vuelva a crear y borre el resto de la pila (hacia arriba). Y dado que el inicio de sesión probablemente esté en la parte inferior de la pila, ahora tiene una pila vacía y el botón Atrás simplemente sale de la aplicación.
PERO: esto solo funciona si previamente dejó viva esa instancia original de LoginActivity en la base de su pila. Si, como muchos programadores, elige finish()
eso LoginActivity
una vez que el usuario haya iniciado sesión exitosamente, entonces ya no estará en la base de la pila y la FLAG_ACTIVITY_CLEAR_TOP
semántica no se aplica... terminará creando una nueva LoginActivity
encima de la pila existente. Lo cual es casi seguro que NO es lo que desea (comportamiento extraño en el que el usuario puede "retroceder" para salir del inicio de sesión en una pantalla anterior).
Entonces, si ya finish()
lo ha hecho anteriormente LoginActivity
, debe buscar algún mecanismo para limpiar su pila y luego comenzar una nueva LoginActivity
. Parece que la respuesta @doreamon
en este hilo es la mejor solución (al menos para mi humilde opinión):
https://stackoverflow.com/a/9580057/614880
Sospecho firmemente que las complicadas implicaciones de dejar con vida LoginActivity están causando gran parte de esta confusión.
Buena suerte.
ACTUALIZAR
el súper finishAffinity()
método ayudará a reducir el código pero logrará lo mismo. Finalizará la actividad actual así como todas las actividades en la pila, úsela getActivity().finishAffinity()
si está en un fragmento.
finishAffinity();
startActivity(new Intent(mActivity, LoginActivity.class));
RESPUESTA ORIGINAL
Supongamos que LoginActivity --> HomeActivity --> ... --> SettingsActivity call signOut():
void signOut() {
Intent intent = new Intent(this, HomeActivity.class);
intent.putExtra("finish", true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // To clean up all activities
startActivity(intent);
finish();
}
InicioActividad:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean finish = getIntent().getBooleanExtra("finish", false);
if (finish) {
startActivity(new Intent(mContext, LoginActivity.class));
finish();
return;
}
initializeView();
}
Esto funciona para mí, espero que sea útil para ti también. :)