En primer lugar, sé que uno no debería realmente matar / reiniciar una aplicación en Android. En mi caso de uso, quiero restablecer de fábrica mi aplicación en un caso específico donde un servidor envía una información específica al cliente.
El usuario solo puede iniciar sesión en el servidor con UNA instancia de la aplicación (es decir, no se permiten varios dispositivos). Si otra instancia obtiene ese bloqueo de "inicio de sesión", todas las demás instancias de ese usuario deben eliminar sus datos (restablecimiento de fábrica) para mantener la coherencia.
Es posible obtener el bloqueo por la fuerza, porque el usuario puede eliminar la aplicación y volver a instalarla, lo que daría como resultado una identificación de instancia diferente y el usuario ya no podrá liberar el bloqueo. Por lo tanto, es posible obtener el bloqueo por la fuerza.
Debido a esa posibilidad de fuerza, debemos verificar siempre en una instancia concreta que tiene el bloqueo. Eso se hace en (casi) cada solicitud al servidor. El servidor puede enviar una "identificación de bloqueo incorrecta". Si se detecta eso, la aplicación cliente debe eliminar todo.
Ese fue el caso de uso.
Tengo una Activity
A que inicia el inicio de sesión Activity
L o la Activity
B principal de la aplicación dependiendo de un valor sharedPrefs. Después de iniciar L o B, se cierra solo para que solo L o B se esté ejecutando. Entonces, en el caso de que el usuario haya iniciado sesión, B ya se está ejecutando.
B comienza C. C llama startService
a la IntentService
D. Eso da como resultado esta pila:
(A)> B> C> D
Desde el método onHandleIntent de D se envía un evento a un ResultReceiver R.
R ahora maneja ese evento al proporcionar al usuario un cuadro de diálogo donde puede elegir restablecer la aplicación de fábrica (eliminar la base de datos, sharedPrefs, etc.)
Después del restablecimiento de fábrica, quiero reiniciar la aplicación (para cerrar todas las actividades) y solo iniciar A nuevamente, que luego inicia el inicio de sesión Activity
L y finaliza:
(A)> L
El método onClick del diálogo se ve así:
@Override
public void onClick(DialogInterface dialog, int which) {
// Will call onCancelListener
MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.)
Intent i = new Intent(MyApp.getContext(), A.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyApp.getContext().startActivity(i);
}
Y esa es la MyApp
clase:
public class MyApp extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
public static Context getContext() {
return context;
}
public static void factoryReset() {
// ...
}
}
El problema es si uso FLAG_ACTIVITY_NEW_TASK
las actividades B y C que aún se están ejecutando. Si presiono el botón Atrás en el inicio de sesión Activity
, veo C, pero quiero volver a la pantalla de inicio.
Si no configuro FLAG_ACTIVITY_NEW_TASK
, aparece el error:
07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
No puedo usar las Actividades ' Context
, porque la ServiceIntent
D también podría llamarse desde una tarea en segundo plano que es iniciada por AlarmManager
.
Entonces, ¿cómo podría resolver esto con la pila de actividades convirtiéndose en (A)> L?