¿Cómo regresar a la última actividad lanzada al volver a iniciar la aplicación después de presionar HOME?

Escenario familiar: Tengo una actividad principal que inicia una actividad de juego cuando se presiona un botón. Si el usuario presiona HOME, y luego vuelve a iniciar mi aplicación, debe presentarla con la actividad del juego , que es lo que estaba haciendo al utilizar la aplicación.

Sin embargo, lo que sucede en su lugar es que obtiene la actividad Principal de nuevo. Tengo la sensación de que Android está creando otra instancia de MainActivity y añadiéndola a la pila para esa aplicación, en lugar de simplemente escoger lo que estuviera en la parte superior, porque si presiono BACK después de relanzar la aplicación, llegaré a la actividad del juego! Y el método Main.onCreate se llama cada vez, en lugar de llamar a GameActivity.onResume.

Mi AndroidManifest.xml es prácticamente 'huesos desnudos':

 <activity android:name="MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="GameActivity" android:label="@string/app_name"> </activity> 

Como puede ver, nada demasiado lujoso.

Y así es como se lanza la nueva actividad, muy simple también:

 Intent intent = new Intent(this, GameActivity.class); startActivity(intent); 

En teoría, esto debería funcionar en Android sólo "fuera de la caja", como la respuesta a una pregunta muy similar dice: Mantener la actividad de la aplicación estándar Estado de la pila de la espalda en Android (utilizando el modo de inicio singleTask) , pero no lo es.

He estado leyendo y releyendo la documentación sobre Actividad y tareas y pilas y navegando todas las respuestas relacionadas en SO, pero no entiendo por qué una configuración tan sencilla no está funcionando como esperaba.

  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { // Activity was brought to front and not created, // Thus finishing this will get us to the last viewed activity finish(); return; } // Regular activity creation code... } 

Oh, creo que he encontrado la respuesta.

Porque estaba lanzando la aplicación con IntelliJ, parece que lanza la aplicación de una manera diferente a un usuario, haciendo clic en un widget de pantalla de inicio, se pondría en marcha. Se explica en la respuesta a otra pregunta de SO:

Esto se debe a las intenciones que se utilizan para iniciar la aplicación es diferente. Eclipse inicia una aplicación con una intención sin acción y sin categoría. El Lanzador inicia una aplicación utilizando una intención con la acción android.intent.action.MAIN y la categoría android.intent.category.LAUNCHER. El instalador inicia una aplicación con la acción android.intent.action.MAIN y sin categoría.

Ref: La aplicación empieza siempre nueva de la actividad de la raíz en lugar de reanudar el estado de fondo (Bug conocido)

Así que he matado manualmente la aplicación en el teléfono, y lo relanzó de nuevo desde el widget de pantalla de inicio. A continuación, abrió la GameActivity y presionó HOME. Ahora, al relanzarlo, la GameActivity sigue siendo visible y mantiene su estado de UI tal y como era cuando lo dejé.

Y supongo que la razón por la que una nueva instancia de la actividad se creó al presionar el acceso directo antes se debía a una intención diferente que se utiliza para iniciar la actividad.

La solución más sencilla es escribir una preferencia durante la onPause o serializar su estado a un archivo persistente y luego leer este archivo durante onResume en su actividad de punto de entrada principal. Esta actividad reconstruirá el estado de la aplicación y volverá a iniciar la actividad correcta.

Estás viendo esto porque tu aplicación puede ser eliminada por el sistema operativo al salir. Nunca se sabe con seguridad, así que si quieres una verdadera persistencia del uso, es decir, regresa a la última actividad, pase lo que pase, necesitas escribir tu estado en una tienda persistente.

Recomiendo encarecidamente el uso de isTaskRoot para comprobar si la actividad debe ser terminado en lugar del indicador FLAG_ACTIVITY_BROUGHT_TO_FRONT.

Me gustaba la respuesta de Sachin , pero a veces me daba falsos positivos y terminaba la actividad cuando no debía. La forma fiable que encontré para reproducir un falso positivo es:

  1. Inicie la aplicación desde la pantalla de inicio
  2. Inicio de prensa
  3. Lanzó de nuevo la aplicación desde la pantalla de inicio
  4. Pulse "atrás" para volver a la pantalla de inicio
  5. Devuelto a la aplicación de "aplicaciones recientes"

Empecé a buscar maneras de inspeccionar la actividad de mi tarea backstack y encontré respuestas utilizando ActivityManager. Esto parecía que podría funcionar, pero esta respuesta señaló la existencia de isTaskRoot , que es una forma simple y elegante de detectar esto que no da falsos positivos, no requiere un permiso especial y no utiliza métodos que documentación Dice están destinados a la depuración y las aplicaciones de gestión de tareas y que no son compatibles con este tipo de uso.

Entiendo de dónde vienes, pero creo que el sistema operativo no quiere hacer ninguna suposición. Además, existe el problema de que su aplicación se ha recuperado porque la memoria es necesaria para otra cosa. En esa causa estaría comenzando encima de su MainActivity.

Dependiendo de lo complicado que esté tu juego, puedes guardar el estado en SharedPreferences o una base de datos SqlLite en el método onPause () de tu actividad. A continuación, onResume () puede restaurar el usuario al último estado, que puede incluir "reiniciar" su GameActivity.

¡Espero que esto ayude!

Edit: Y lo que estoy diciendo es que es nuestra responsabilidad como desarrolladores para mostrar / garantizar al usuario que la actividad correcta se muestra al volver a la aplicación. La memoria de la aplicación siempre tiene el potencial de ser recuperado y luego android va a volver a iniciar la actividad que ha etiquetado con intentos MAIN y LAUNCHER. Al guardar el estado (el identificador de actividad), puede redirigirlos a esa actividad desde la …

Resuelvo el problema usando la pila de actividad siguiente en mi aplicación:

LaunchActivity -> MainActivtiy -> SomeSubActivtiy

LaunchActivtiy sólo verifica algunos parámetros y lanza MainActivtiy . Resultó, que MainActivity debe ser lanzado con

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

Esta combinación de banderas en MainActivity da el comportamiento deseado.

  • Cómo borrar una tarea en Android y cambiar la actividad de la raíz?
  • App pierde su capacidad de recordar su pila cuando se inicia desde otra aplicación
  • Android: ¿Cómo hacer que el lanzador abra siempre la actividad principal en lugar de la actividad infantil? (o de otro modo)
  • Android: Cancelar tarea asíncrona
  • ¿Diferencia entre OnlyOnRanToCompletion y NotOnFaulted?
  • Borrar tarea e iniciar una nueva actividad
  • Android, ¿cómo llevar una tarea al primer plano?
  • ¿Cómo manipulo la pila de actividades de Android?
  • Android tarea matar
  • Diferencia entre un asesino de tareas matando una aplicación y el sistema operativo Android Matando una aplicación
  • Android: Error de OutOfMemory y el backstack
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.