Android: remova todas as atividades anteriores da pilha posterior


119

Quando estou clicando no botão Logout em minha atividade de perfil, quero levar o usuário à página de Login , onde ele precisa usar novas credenciais.

Portanto, usei este código:

Intent intent = new Intent(ProfileActivity.this,
        LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

no onButtonClickbotão Logout.

Mas o problema é que quando clico no botão Voltar do dispositivo na Atividade de login, ele me leva para a ProfileActivity. Eu esperava que o aplicativo fechasse quando pressiono o botão Voltar do dispositivo no LoginActivity.

O que estou fazendo de errado?

Eu também adicionei android:launchMode="singleTop"no manifesto da minha LoginActivity

Obrigado


@GauravVashisth Eu estava apenas seguindo esta solução stackoverflow.com/questions/5794506/…
— Archie.bpgc

@abbas.aniefa Essa solução é um pouco complicada. Essa é a única maneira de limpar toda a pilha de volta. Como tenho mais de 30 atividades, devo escrever este código de transmissão para todas elas
— Archie.bpgc

tente isso então, stackoverflow.com/questions/10961481/… . Usar o Broadcast é a melhor solução.
— abbas.aniefa

outra abordagem que você pode usar para o logout, uma vez que você logout armazena um sinalizador em sharedpreferences e em cada método onRestart () de uma atividade, você pode verificar o valor desta variável se estiver definido como true, você pode terminar a atividade atual. portanto, não importa quantas atividades estejam abertas em background. isso encerraria todas as suas atividades.
— Hiren Dabhi

Seu código original realmente funciona para a API de nível 11 ou superior com um ajuste. Você só precisa colocar as bandeiras juntas em uma única chamada: intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);eu obtive a resposta desta pergunta: stackoverflow.com/questions/3473168/…
— jokeefe

Respostas:


302

A solução proposta aqui funcionou para mim:

Java

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Kotlin

val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)

No entanto, requer nível de API> = 11.


Pessoal, leiam a documentação do FLAG_ACTIVITY_CLEAR_TASK.Esta é a forma oficial de obter. Não há necessidade de alterar todas as atividades no aplicativo.
— AlikElzin-kilaka

Isso não funciona para notificações stackoverflow.com/questions/24873131/…
— Sam,

Eu tenho meu minAPI = 16, então está funcionando perfeitamente bem para mim. No entanto, percebi que a execução da visualização é um pouco lenta com API> 21 e suave com APIs <21. Alguém está tendo o mesmo problema?
— Red M

1
Isso criará uma nova tarefa para atividades
— Rohit

@kgiannakakis Sem dúvida, a solução está funcionando se tivermos apenas uma tarefa (pilha de atividades anteriores), mas quando temos várias tarefas (pilha de atividades), ela não está funcionando. ex- digamos que eu tenha quatro atividades para minha aplicação A, B, C e D. Suponha que eu tenha duas pilhas de atividades A-> B-> C (plano de fundo) & D-> A-> B (primeiro plano) e se eu chame a atividade A da minha pilha atual (D-> A-> B) com filtro de intenção o que você sugeriu o que vai acontecer, limpe minha pilha atual (D-> A-> B) e abra a atividade A e quando eu pressioná-lo feche aplicativo, mas se eu pressionar o botão do aplicativo recente, posso ver duas pilhas de meu aplicativo lá.
— Rahul Pareta

31

Aqui está uma solução para limpar todas as atividades do seu aplicativo ao usar o botão de logout.

Cada vez que você iniciar uma atividade, inicie-a assim:

Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);

Quando você quiser fechar o aplicativo inteiro, faça o seguinte:

setResult(RESULT_CLOSE_ALL);
finish();

RESULT_CLOSE_ALL é uma variável global final com um número inteiro único para sinalizar que você deseja fechar todas as atividades.

Em seguida, defina o onActivityResult(...)retorno de chamada de cada atividade para que, quando uma atividade retornar com o valor RESULT_CLOSE_ALL, ela também chame finish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode)
    {
    case RESULT_CLOSE_ALL:
        setResult(RESULT_CLOSE_ALL);
        finish();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Isso causará um efeito em cascata que fecha todas as suas atividades.

No entanto, este é um hack e usa startActivityForResultde uma forma que não foi projetada para ser usada.

Talvez a melhor maneira de fazer isso seja usando broadcast receivers, conforme mostrado aqui:

Ao sair, limpe a pilha do histórico de atividades, evitando que o botão "voltar" abra atividades somente conectadas

Veja estes tópicos para outros métodos também:

Android: limpe a pilha posterior

Concluir todas as atividades anteriores


4
É viável quando você tem cerca de 30 atividades na história ??
— Rakesh Gondaliya

4
deveria estar. Mas se você tem 30 atividades na história, então você pode querer considerar mudar seu projeto. 30 parece um pouco demais e o Android pode matá-los sozinho.
— Anup Cowkur

1
Esta parece uma maneira ruim de fazer isso. A resposta da pergunta de @RakeshGondaliya parece legítima. 30 talvez apenas um número representando um número "alto" de atividades. Esta resposta parece melhor: stackoverflow.com/a/3008684/243709
— Aman Alam

Essa resposta é ótima. Você também pode usar a biblioteca EventBus para enviar eventos para suas atividades no backstack. github.com/greenrobot/EventBus
— Stan

Melhor usar a sinalização 'Intent.FLAG_ACTIVITY_CLEAR_TOP' simples com intenção
— Naveen Rao,

18

Para limpar a pilha de atividades completamente, você deseja criar uma nova pilha de tarefas usando TaskStackBuilder, por exemplo:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

Isso não apenas criará uma nova pilha de tarefas limpa, mas também permitirá o funcionamento adequado do botão "para cima" se sua LoginActivity tiver uma atividade pai.


1
Esta é a melhor forma de o fazer.
— Paul Burke

FLAG_ACTIVITY_NEW_TASKou finishAffinity()não funcionou para mim. Somente esta resposta resolveu o propósito.
— TM

Se eu sair do aplicativo por meio do botão Voltar e retornar pelo ícone do aplicativo, ele abre na atividade que chamei desse método. Então, não está funcionando para mim.
— Tgo1014

17

finishAffinity()adicionado na API 16. Use ActivityCompat.finishAffinity()em versões anteriores. Quando você iniciará qualquer atividade usando a intenção e terminará a atividade atual. Agora use em seu ActivityCompat.finishAffinity()lugar finish(). ele encerrará todas as atividades empilhadas abaixo da atividade atual. Isso funciona bem para mim.


3
Na verdade, éActivityCompat.finishAffinity()
— The Berga

finishAffinity()também termina a atividade atual com todas as atividades presentes na pilha posterior da mesma afinidade.
— Neeraj Sewani,

10

O que funcionou para mim

Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);

5

Uma solução possível que posso sugerir é adicionar android:launchMode="singleTop"no manifesto para minha ProfileActivity . e quando o logout for clicado, você poderá efetuar o logoff reiniciando a sua LoginActivity. ao sair, você pode ligar para isso.

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();

Eu fiz isso, o que aconteceu é: quando eu clico no botão Voltar, ele me leva para a Activty de onde vim para ProfileActivity
— Archie.bpgc

Isso pode acontecer porque você chegou a ProfileActivity chamando um novo intent, não chamando finish (); Como você está vindo para ProfileActivity de outra atividade além da LoginActivty?
— Android de

Estou cruzando a mesma questão. Acho que não funcionaria quando a intenção de login fosse destruída pelo sistema, digamos devido à falta de memroy.
— user1914692

5

Para API 11+, você pode usar Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASKassim:

Intent intent = new Intent(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);

Ele apagará totalmente todas as atividades anteriores e iniciará uma nova atividade.


4

Você pode tentar finishAffinity(), ele fecha todas as atividades atuais e funciona no Android 4.1 e superior


1
finishAffinity () adicionado na API 16. Use ActivityCompat.finishAffinity () na versão anterior. Eu funciona bem para mim.
— Anurag Srivastava

2

Eu também estou enfrentando o mesmo problema..

na atividade de login o que eu faço é.

    Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
    finish();
    MainActivity.this.startActivity(myIntent);  

no logout

   Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
   finish();
   ActivityLoggedIn.this.startActivity(myIntent);

Isso funciona bem, mas quando estou no ActivityLoggedIn e minimizo o aplicativo e clico no ícone do botão de inicialização na gaveta do aplicativo, a MainActivity começa novamente: - / estou usando o sinalizador

android:LaunchMode:singleTask 

para a MainActivity.


2

Use o seguinte para activity

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);

remover o sinalizador CLEAR_TASK para uso do fragmento.

Espero que isso possa ser usado para algumas pessoas.


1

Apenas guarde

Intent intent = new Intent(ProfileActivity.this,
    LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);

4
Não está funcionando. Ainda posso ir para ProfileActivity usando o botão Voltar
— Archie.bpgc

1

Nenhuma das sinalizações de intent funcionou para mim, mas foi assim que corrigi:

Quando um usuário sai de uma atividade, eu tive que transmitir uma mensagem dessa atividade e, em seguida, recebê-la nas atividades que eu queria encerrar e depois chamo terminar (); e funciona muito bem.


1

Experimente isso vai funcionar:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();

1

Na API de nível 11 ou superior, use FLAG_ACTIVITY_CLEAR_TASKe FLAG_ACTIVITY_NEW_TASKsinalize no Intent para limpar toda a pilha de atividades.

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |  Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

0

Usa isto

Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();

você conhecia setFlags e addFlags?
— GvSharma de

0

adicione ao manifesto para sua atividade android:launchMode="singleTask"


0

Kotlin avançado e reutilizável:

Você pode definir o sinalizador diretamente usando o método setter. No Kotlin oré a substituição do bit a bit Java ou |.

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

Se você planeja usar isso regularmente, crie uma função de extensão Intent

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Você pode então chamar esta função diretamente antes de iniciar o intent

intent.clearStack()

Se você precisar da opção de adicionar sinalizadores adicionais em outras situações, adicione um parâmetro opcional à função de extensão.

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.