¿Cómo comprobar si una actividad es la última en la pila de actividades de una aplicación?

Respuestas:

116

ACTUALIZACIÓN (julio de 2015):

Desde getRunningTasks () quedar obsoleta, API de 21 que es mejor seguir raukodraug respuesta o Ed Burnette uno (yo preferiría segundo).


Existe la posibilidad de verificar las tareas actuales y su pila usando ActivityManager .

Entonces, para determinar si una actividad es la última:

  • solicitar permisos android.permission.GET_TASKS en el manifiesto.
  • Utilice el siguiente código:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }

Tenga en cuenta que el código anterior será válido solo si tiene una sola tarea. Si existe la posibilidad de que exista una cantidad de tareas para su aplicación, deberá verificar otros elementos de taskList . Leer más sobre tareas Tasks y Back Stack


sandrstar
fuente
25
H9kDroid ha hecho una sugerencia correcta. La respuesta seleccionada es un truco. Uno debe hacerlo de la manera correcta usando el isTaskRoot()método.
Sufian
@Sufian, ¿dónde está hackear particularmente? El código es lógico y usa API de Android abiertas de la forma en que se pretendía usar (por ejemplo, getRunningTasks debe usarse para ejecutar tareas y es posible que desee llamarlo solo con el propósito de analizar estas tareas). El uso de get (0) está bien documentado y es lógico 'Devuelve una lista de las tareas que se están ejecutando actualmente, siendo la más reciente la primera y la anterior en orden'.
sandrstar
2
getRunningTasks () está en desuso en el nivel de API 21.
gilchris
¿Puedo hacer lo mismo con los fragmentos? Si es así, entonces cómo ? Por favor ayuda
Sagar Devanga
1
@ Mr.Drew vea la respuesta más votada de @ raukodraug
David Wasser
167

Voy a publicar el comentario de @ H9kDroid como la mejor respuesta aquí para las personas que tienen una pregunta similar.

Puede utilizar isTaskRoot () para saber si la actividad es la raíz de una tarea.

espero que esto ayude

raukodraug
fuente
1
¿Puede proporcionar una sola línea de código para que quede claro cómo usar isTaskRoot? Gracias.
Kaveesh Kanwal
18
@TheHunterif (isTaskRoot()) { // do something }
howettl
3
El único problema es que en <= 4.4 veo que tiene un comportamiento diferente al de> = 5.x. Parece que siempre vuelve falso.
chubbsondubs
Creo que debería considerar incorporar el código de muestra proporcionado en los comentarios en la respuesta, para que sea más fácil para los futuros lectores.
Isac
excelente respuesta. en mi caso, después de que el usuario hace clic en una notificación, la actividad podría ser la raíz si cerraron la aplicación antes
dave o grady
19

Espero que esto ayude a los nuevos principiantes. Basado en las respuestas anteriores que me funcionan bien, también estoy compartiendo un fragmento de código para que sea fácil de implementar.

solución: utilicé isTaskRoot()que devuelve verdadero si la actividad actual es solo actividad en su pila y, aparte de que también manejo el caso en el que si tengo alguna actividad en la pila, vaya a la última actividad en la pila en lugar de abrir una nueva personalizada.

En tu actividad

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }
Abhishek Garg
fuente
16

hay una solución más fácil para esto, puede usar isTaskRoot () en su actividad

Laxmikant Revdikar
fuente
5

Si bien puede haber una manera de lograr esto (vea otras respuestas), le sugiero que no lo haga. Las aplicaciones normales de Android no deberían necesitar saber si la pantalla de inicio está a punto de mostrarse o no.

Si está intentando guardar datos, coloque el código de guardado de datos en su método onPause (). Si está tratando de darle al usuario una forma de cambiar de opinión acerca de la existencia de la aplicación, puede interceptar la tecla arriba / abajo para la tecla Atrás y el método onBackPressed () y presentarle un "¿Está seguro?" rápido.

Ed Burnette
fuente
1
¿Qué tal si necesito un servicio en ejecución siempre que el usuario no haya abandonado la actividad? No puedo capturar ninguna de las funciones como onStop porque se pueden llamar después de que se apaga la pantalla.
Michael
2
Si un servicio en segundo plano lanza una Actividad, quizás le gustaría saber si esa es la única Actividad en la pila.
Matt W
4

Una forma de realizar un seguimiento de esto es incluir un marcador cuando inicie una nueva actividad y comprobar si el marcador existe.

Siempre que inicie una nueva actividad, inserte el marcador:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

Y luego puede verificarlo así:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")
H9kDroid
fuente
1
No funciona si se mata la actividad y se reconstruye la pila de actividades, cada actividad por demanda.
AlikElzin-kilaka
3

El problema con el uso de la solución de sandrstar ActivityManageres: necesita un permiso para obtener las tareas de esta manera. Encontré una mejor manera:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

El Activityen la parte inferior de la pila siempre debería obtener esta categoría de forma predeterminada, mientras que otras actividades no deberían obtenerla.
Pero incluso si esto falla en algunos dispositivos, puede configurarlo mientras inicia su Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);
A. Binzxxxxxx
fuente
¿Qué pasa si la actividad se abre desde una notificación automática? No tienen el LANZADOR
nbtk
Estoy bastante seguro de que la segunda parte de mi respuesta todavía se aplica. Puede establecer la categoría como una sugerencia en la intención. En este caso, tal vez en la intención de su contexto de notificación. Aparte de eso, también puede usar banderas para esto. vea este enlace para la creación de una notificación con intención: stackoverflow.com/questions/13716723/…
A. Binzxxxxxx
Aún así, si su actividad más antigua es MainActivity y ahora se reanuda, y luego recibe una notificación de inserción y establece el pendienteIntent para que se abra con CATEGORY_LAUNCHER, entonces tendrá 2 actividades con esta categoría. Sin embargo
nbtk
No estoy seguro de cómo funciona con las notificaciones. Nunca los usé como tú lo haces aquí. Estoy bastante seguro de que hay una manera fácil de hacerlo con este enfoque, pero no toqué el código de Android desde el primer trimestre de 2014. ¿Quizás desee usar una segunda categoría para este caso? ¿O alguna bandera? Pero supongo que es mejor que funcione así. ¿Qué tal comenzar la actividad principal y agregar algún tipo de metainformación para abrir la actividad correcta?
A. Binzxxxxxx
2

Creé una clase base para todas mis actividades, extendiendo AppCompatActivity y que tiene un contador estático:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

Esto ha funcionado bastante bien, hasta ahora; e independientemente de la versión de API. Por supuesto, requiere que todas las actividades amplíen esta clase base, lo que hacen, en mi caso.

Editar: He notado una instancia en la que el contador baja a cero antes de que la aplicación salga por completo, que es cuando se cambia la orientación y solo una actividad está abierta. Cuando cambia la orientación, la actividad se cierra y se crea otra, por lo que onDestroyedse llama para la última actividad, y luego onCreatese llama cuando se crea la misma actividad con la orientación cambiada. Este comportamiento debe tenerse en cuenta; Posiblemente, se podría utilizar OrientationEventListener .

Per Löwgren
fuente
0

Android implementa una pila de actividades, le sugiero que lea sobre esto aquí . Parece que todo lo que quiere hacer sin embargo es recuperar la actividad de llamada: getCallingActivity(). Si la actividad actual es la primera actividad en su aplicación y la aplicación se inició desde la pantalla de inicio, debería (supongo) regresar null.

Gyan alias Gary Buyn
fuente
9
Eso no funcionará ya que getCallingActivity () devolverá nulo si la actividad no se inició a través de startActivityForResult ().
H9kDroid
0

Lo único que se perdió aquí, es el clic de la "tecla Inicio", cuando se activa, no puede detectar esto en su actividad, por lo que sería mejor controlar la pila de actividades mediante programación manejando la tecla "Atrás" presionando y moviéndose a la actividad requerida o simplemente haciendo los pasos necesarios.

Además, no puede estar seguro de que el inicio de su actividad desde la lista "Actividad reciente" se puede detectar con la preconfiguración de algunos datos adicionales en la intención de la actividad de apertura, ya que se reutiliza en ese caso.

ACM64
fuente