Como verificar se uma atividade é a última na pilha de atividades de um aplicativo?

Respostas:

116

ATUALIZAÇÃO (jul de 2015):

Desde getRunningTasks () se obsoleta, de API 21, é melhor seguir raukodraug resposta ou Ed Burnette um (eu preferiria segundo).


Há possibilidade de verificar as tarefas atuais e sua pilha usando o ActivityManager .

Portanto, para determinar se uma atividade é a última:

  • solicite permissões android.permission.GET_TASKS no manifesto.
  • Use o seguinte 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");
    }

Observe que o código acima será válido apenas se você tiver uma única tarefa. Se houver a possibilidade de existir um número de tarefas para o seu aplicativo - você precisará verificar outros elementos taskList . Leia mais sobre tarefas Tarefas e Back Stack


sandrstar
fonte
25
O H9kDroid fez uma sugestão correta. A resposta selecionada é um hack. Deve-se fazê-lo da maneira correta, usando o isTaskRoot()método
Sufian
@Sufian, onde é hackear particularmente? O código é lógico e usa APIs abertas do Android da maneira que elas pretendem ser usadas (por exemplo, getRunningTasks deve ser usado para executar tarefas em execução e é possível chamá-lo apenas com o objetivo de analisar essas tarefas). O uso de get (0) está bem documentado e lógico 'Retorne uma lista das tarefas que estão em execução no momento, sendo as mais recentes as primeiras e as mais antigas depois da ordem'.
sandrstar
2
getRunningTasks () é preterido no nível API 21.
gilchris
Posso fazer a mesma coisa com fragmentos. Se sim, então como? Por favor ajude
Sagar Devanga 4/15
1
@ Mr.Drew ver a maior resposta votou de @ raukodraug
David Wasser
167

Vou postar o comentário do @ H9kDroid como a melhor resposta aqui para pessoas que têm uma pergunta semelhante.

Você pode usar isTaskRoot () para saber se a atividade é a raiz de uma tarefa.

Eu espero que isso ajude

raukodraug
fonte
1
você pode fornecer a única linha de código para que fique claro como usar o isTaskRoot. Obrigado.
Kaveesh Kanwal
18
@TheHunterif (isTaskRoot()) { // do something }
howettl
3
O único problema é que, em <= 4.4, estou vendo um comportamento diferente do que em> = 5.x. Parece sempre retornar falso.
Chubbsondubs # 1/16
Eu acho que você deve considerar a incorporação do código de exemplo fornecido nos comentários na resposta, para facilitar para futuros leitores.
234 Isac
excelente resposta. no meu caso, depois que o usuário clicar em uma notificação, a atividade poderá ser a raiz se ele tiver fechado o aplicativo antes
dave o grady
19

Espero que isso ajude os novos iniciantes. Com base nas respostas acima, que funcionam bem para mim, também estou compartilhando um trecho de código para que seja fácil de implementar.

solução: usei o isTaskRoot()que retornará true se a atividade atual for apenas atividade na sua pilha e outro que não seja também o caso em que, se tiver alguma atividade na pilha, vá para a última atividade na pilha em vez de abrir uma nova personalizada.

Na sua atividade

   @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
fonte
16

existe uma solução mais fácil para isso, você pode usar isTaskRoot () em sua atividade

Laxmikant Revdikar
fonte
5

Embora possa haver uma maneira de conseguir isso (consulte outras respostas), sugiro que você não faça isso. Os aplicativos normais do Android não precisam saber se a tela inicial está prestes a ser exibida ou não.

Se você estiver tentando salvar dados, coloque o código para salvar dados no método onPause (). Se você está tentando dar ao usuário uma maneira de mudar de idéia sobre a existência do aplicativo, você pode interceptar a tecla para cima / baixo da tecla Voltar e do método onBackPressed () e apresentá-lo com um "Você tem certeza?" pronto.

Ed Burnette
fonte
1
E se eu precisar de um serviço em execução enquanto o usuário não tiver saído da atividade? Não consigo capturar nenhuma das funções como onStop, porque elas podem ser chamadas depois que a tela é desligada.
Michael
2
Se um serviço em segundo plano lança uma atividade, talvez você queira saber se essa é a única atividade na pilha.
Matt W
4

Uma maneira de acompanhar isso é incluir um marcador quando você inicia uma nova atividade e verificar se o marcador existe.

Sempre que você iniciar uma nova atividade, insira o marcador:

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

E você pode então verificar assim:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")
H9kDroid
fonte
1
Não funciona se a atividade for interrompida e a pilha de atividades for reconstruída - cada atividade por demanda.
AlikElzin-Kilaka
3

O problema com a solução da sandrstar ActivityManageré: você precisa de uma permissão para executar as tarefas dessa maneira. Eu encontrei uma maneira melhor:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

A Activityparte inferior da pilha deve sempre obter essa categoria por padrão, enquanto outras atividades não devem obtê-la.
Mas mesmo que isso falhe em alguns dispositivos, você pode configurá-lo ao iniciar o seu Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);
A. Binzxxxxxx
fonte
E se a atividade for aberta a partir da notificação por push? Eles não têm o CATEGORY LAUNCHER
nbtk 5/09
Tenho certeza de que a segunda parte da minha resposta ainda se aplica. Você pode definir a categoria como uma dica na intenção. Nesse caso, talvez na intenção do seu contexto de notificação. Fora isso, você também pode usar sinalizadores para isso. consulte este link para uma criação de notificação com a intenção: stackoverflow.com/questions/13716723/…
A. Binzxxxxxx
Ainda assim, se sua atividade mais antiga é MainActivity e agora é retomada, você recebe uma notificação por push e define o pendenteIntent para abrir com CATEGORY_LAUNCHER, então você terá 2 atividades com essa categoria. Provavelmente em tarefas diferentes
nbtk
Não sei exatamente como isso funciona com as notificações. Eu nunca os usei como você faz aqui. Tenho certeza de que existe uma maneira fácil de fazer isso com essa abordagem, mas não toquei no código do Android desde o primeiro trimestre de 2014. Talvez você queira usar uma segunda categoria para este caso? Ou alguma bandeira? Mas acho que seu trabalho funcionará assim. Que tal iniciar a atividade principal e adicionar algum tipo de meta informação para abrir a atividade correta?
A.Banzxxxxxx # 7/17
2

Criei uma classe base para todas as minhas atividades, estendendo o AppCompatActivity e que possui um 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); }
}

Até agora, isso funcionou bem o suficiente; e independentemente da versão da API. É claro que exige que todas as atividades estendam essa classe base - o que elas fazem, no meu caso.

Editar: notei uma instância em que o contador cai para zero antes de o aplicativo sair completamente, ou seja, quando a orientação é alterada e apenas uma atividade é aberta. Quando a orientação muda, a atividade é fechada e outra é criada, então onDestroyedé chamada para a última atividade e, em seguida, onCreateé chamada quando a mesma atividade é criada com a orientação alterada. Esse comportamento deve ser considerado; OrientationEventListener poderia ser usado.

Per Löwgren
fonte
0

O Android implementa uma pilha de atividades. Sugiro que você leia aqui . Parece que tudo que você quer fazer, porém, é recuperar a atividade de vocalização: getCallingActivity(). Se a atividade atual é a primeira atividade em seu aplicativo e o aplicativo foi iniciado a partir da tela inicial, devo (presumo) retornar null.

Gyan tcp Gary Buyn
fonte
9
Isso não funcionará, pois getCallingActivity () retornará nulo se a atividade não tiver sido iniciada via startActivityForResult ().
precisa saber é o seguinte
0

A única coisa que faltou aqui é o clique na "tecla Home", quando ativado, você não pode detectar isso em sua atividade; portanto, é melhor controlar a pilha de atividades programaticamente com o manuseio da tecla "Back key" e a mudança para a atividade necessária ou apenas executando as etapas necessárias.

Além disso, você não pode ter certeza de que o início de sua atividade da lista "Atividade recente" pode ser detectado com a predefinição de alguns dados extras na intenção de abrir a atividade, pois ela é reutilizada nesse caso.

ACM64
fonte