singletop single pila example activity actividades android activity-stack

single - flags in android



Android: error en launchMode="singleTask"?-> pila de actividad no preservada (9)

Mi actividad principal A tiene como conjunto android:launchMode="singleTask" en el manifiesto. Ahora, cada vez que empiezo otra actividad desde allí, por ejemplo, B y presiono el HOME BUTTON en el teléfono para regresar a la pantalla de inicio y luego volver a mi aplicación, ya sea presionando el botón de la aplicación o presionando el HOME BUTTON para mostrar mi las aplicaciones más recientes no conserva mi pila de actividades y regresa directamente a A lugar de a la actividad esperada B

Aquí los dos comportamientos:

Expected: A > B > HOME > B Actual: A > B > HOME > A (bad!)

¿Hay algún ajuste que me falta o es un error? Si es este último, ¿hay alguna solución para esto hasta que se solucione el error?

FYI: Esta pregunta ya ha sido discutida here . Sin embargo, no parece que haya una solución real para esto, todavía.


Al usar el modo de inicio como singleTop, asegúrese de llamar a finish () (en la actividad actual, decir A) al iniciar la siguiente actividad (utilizando el método startActivity (Intención), digamos B). De esta forma, la actividad actual se destruye. A -> B -> Pausa la aplicación y haz clic en el icono del iniciador. Inicia A en el método de creación en A de A, debes tener una marca,

if(!TaskRoot()) { finish(); return; }

De esta forma, al iniciar la aplicación, estamos comprobando la tarea raíz y, anteriormente, la tarea raíz es B pero no A. Entonces, esta comprobación destruye la actividad A y nos lleva a la actividad B, que actualmente es la parte superior de la pila. ¡Espero que funcione para ti!.


Así es como finalmente resolví este extraño comportamiento. En AndroidManifest, esto es lo que agregué:

Application & Root activity android:launchMode="singleTop" android:alwaysRetainTaskState="true" android:taskAffinity="<name of package>" Child Activity android:parentActivityName=".<name of parent activity>" android:taskAffinity="<name of package>"


Cada vez que presiona el botón de inicio para volver a la pantalla de inicio, la pila de actividades elimina algunas de las aplicaciones que se lanzaron anteriormente.

Para verificar este hecho, intente iniciar una aplicación desde el panel de notificaciones después de pasar de A a B en su aplicación y vuelva utilizando el botón Atrás ......... encontrará su aplicación en el mismo estado que usted dejalo.


Creo que este es el comportamiento que quieres:

singleTask restablece la pila en la prensa de casa por alguna razón retrasada que no entiendo. La solución es, en cambio, no usar singleTask y usar StandardTop para la actividad del iniciador (aunque solo he intentado con singleTop hasta la fecha).

Como las aplicaciones tienen afinidad entre ellas, inician una actividad como esta:

Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); if(launchIntent!=null) { launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); }

hará que su pila de actividades reaparezca como estaba, sin que comience una nueva actividad sobre la anterior (que era mi principal problema antes). Las banderas son las más importantes :

FLAG_ACTIVITY_NEW_TASK Agregado en el nivel 1 de la API

Si se establece, esta actividad se convertirá en el inicio de una nueva tarea en esta pila de historial. Una tarea (desde la actividad que lo inició hasta la siguiente actividad de tarea) define un grupo atómico de actividades al que el usuario puede moverse. Las tareas se pueden mover al primer plano y al fondo; todas las actividades dentro de una tarea particular siempre permanecen en el mismo orden. Consulte Tareas y Back Stack para obtener más información sobre las tareas.

Esta bandera generalmente es utilizada por actividades que desean presentar un comportamiento de estilo "iniciador": le dan al usuario una lista de cosas separadas que se pueden hacer, que de otro modo se ejecutan completamente independientemente de la actividad que las lanza.

Al utilizar este indicador, si ya se está ejecutando una tarea para la actividad que está iniciando, entonces no se iniciará una nueva actividad; en su lugar, la tarea actual simplemente se colocará en la parte delantera de la pantalla con el estado en el que estuvo por última vez. Consulte FLAG_ACTIVITY_MULTIPLE_TASK para ver si un indicador desactiva este comportamiento.

Este indicador no se puede usar cuando la persona que llama solicita un resultado de la actividad que se inicia.

Y:

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED Agregado en el nivel de API 1

Si se establece, y esta actividad se inicia en una nueva tarea o lleva a la cima una tarea existente, entonces se lanzará como la puerta de entrada de la tarea. Esto dará como resultado la aplicación de las afinidades necesarias para que la tarea se encuentre en el estado adecuado (ya sea moviendo actividades desde o hacia ella) o simplemente restableciendo esa tarea a su estado inicial si es necesario.

Sin ellos, la actividad lanzada simplemente será empujada a la cima de la pila vieja o algún otro comportamiento indeseable (en este caso, por supuesto)

Creo que el problema de no recibir la última intención se puede resolver de esta manera (fuera de mi cabeza):

@Override public void onActivityReenter (int resultCode, Intent data) { onNewIntent(data); }

¡Pruébalo!


Esto no es un error. Cuando se singleTask actividad singleTask existente, se singleTask todas las demás actividades encima de ella en la pila.

Cuando presiona HOME e inicia la actividad nuevamente, ActivityManger llama un intento

{act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]flag=FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_IF_NEEDED cmp=A}

Entonces el resultado es A> B> INICIO> A.

Es diferente cuando A launchMode de A es "Estándar". La tarea que contiene A pasará a primer plano y mantendrá el estado igual que antes.

Puede crear una actividad "Estándar" ej. C como iniciador y startActivity (A) en el método onCreate de C

O

Simplemente elimine launchMode="singleTask" y establezca el FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP siempre que FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP un intento para A


Frome http://developer.android.com/guide/topics/manifest/activity-element.html en singleTask

El sistema crea la actividad en la raíz de una nueva tarea y enruta el intento hacia ella. Sin embargo, si ya existe una instancia de la actividad, el sistema enruta el intento a la instancia existente a través de una llamada a su método onNewIntent (), en lugar de crear uno nuevo.

Esto significa que cuando los indicadores action.MAIN y category.LAUNCHER dirigen su aplicación desde el Iniciador, el sistema prefiere enrutar el intento a la ActivityA existente en lugar de crear una nueva tarea y establecer una nueva ActivityA como raíz. Preferiría derribar todas las actividades por encima de la tarea existente en la que ActivityA vive, e invocar es onNewIntent ().

Si desea capturar el comportamiento de singleTop y singleTask, cree una actividad de "delegado" separada llamada SingleTaskActivity con singleTask launchMode que simplemente invoca la actividad singleTop en su onCreate () y luego termina. La actividad SingleTop aún tendría los filtros de intención MAIN / LAUNCHER para continuar actuando como actividad principal del Lanzador de la aplicación, pero cuando otras actividades desean llamar a esta actividad singleTop, en su lugar debe invocar SingleTaskActivity para preservar el comportamiento singleTask. La intención que se transfiere a la actividad singleTop también debe trasladarse a la actividad SingleTop, por lo que me ha servido algo como lo siguiente, ya que quería tener los modos de inicio singleTask y singleTop.

<activity android:name=".activities.SingleTaskActivity" android:launchMode="singleTask"> public class SingleTaskActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); intent.setClass(this, SingleTop.class); startActivity(intent); } }

Y su actividad singleTop continuaría teniendo su modo de inicio singleTop.

<activity android:name=".activities.SingleTopActivity" android:launchMode="singleTop"/>

Buena suerte.


Si tanto A como B pertenecen a la misma Application , intente eliminar

android:launchMode="singleTask"

de tus Activities y prueba porque creo que el comportamiento predeterminado es lo que describiste como esperado.


Stefan, ¿alguna vez encuentras una respuesta a esto? Arreglé un caso de prueba para esto y estoy viendo el mismo comportamiento (desconcertante) ... Pegaré el siguiente código en caso de que alguien venga y vea algo obvio:

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example" > <uses-sdk android:minSdkVersion="3"/> <application android:icon="@drawable/icon" android:label="testSingleTask"> <activity android:name=".ActivityA" android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".ActivityB"/> </application> </manifest>

ActivityA.java:

public class ActivityA extends Activity implements View.OnClickListener { @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); setContentView( R.layout.main ); View button = findViewById( R.id.tacos ); button.setOnClickListener( this ); } public void onClick( View view ) { //Intent i = new Intent( this, ActivityB.class ); Intent i = new Intent(); i.setComponent( new ComponentName( this, ActivityB.class ) ); startActivity( i ); } }

ActivityB.java:

public class ActivityB extends Activity { @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); setContentView( R.layout.layout_b ); } }

Traté de cambiar minSdkVersion inútilmente. Esto simplemente parece ser un error, al menos según la documentation , que dice lo siguiente:

Como se señaló anteriormente, nunca hay más de una instancia de una actividad "singleTask" o "singleInstance", por lo que se espera que esa instancia maneje todos los nuevos intentos. Una actividad de "instancia única" siempre está en la parte superior de la pila (ya que es la única actividad en la tarea), por lo que siempre está en posición de manejar la intención. Sin embargo, una actividad "singleTask" puede o no tener otras actividades encima en la pila. Si lo hace, no está en posición de manejar la intención, y la intención se descarta. (Aunque se quitó la intención, su llegada habría provocado que la tarea pasara a primer plano, donde permanecería).


<activity android:name=".MainActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>

// Trate de usar launchMode = "singleTop" en su actividad principal para mantener una sola instancia de su aplicación. Ve a manifestar y cambiar.