¿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.
- Cómo evitar que el servicio se reinicie después de que la actividad se haya barrido desde el conmutador de tareas?
- Android empuja una nueva actividad mientras limpia a otros
- Iniciar nuevo subproceso en Async Task
- Necesita un ejemplo que muestre cómo realizar solicitudes HTTP asíncronas
- ¿El nombre del proceso es el mismo que el nombre del paquete en android?
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.
- Android: ¿FLAG_ACTIVITY_NEW_TASK tiene efecto dentro del mismo proceso?
- La aplicación comienza siempre nueva de la actividad de la raíz en lugar de reanudar el estado de fondo (Bug conocido)
- Cómo terminar una actividad de otra actividad
- ¿Cómo funcionan los asesinos de tareas?
- ¿Cómo llevar una Actividad al primer plano (o crear si no existe)?
- Continuar tarea después de terminar todas las tareas
- ActivityManager.killBackgroundProcesos diferentes de "Parada de fuerza"
- Manejar la instancia existente de actividad raíz al iniciar de nuevo la actividad raíz desde el filtro de intenciones
@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:
- Inicie la aplicación desde la pantalla de inicio
- Inicio de prensa
- Lanzó de nuevo la aplicación desde la pantalla de inicio
- Pulse "atrás" para volver a la pantalla de inicio
- 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.
- Depuración en dispositivo Android sobre wifi sin enraizamiento
- Uso de la forma dibujable como mi fondo xml