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

Archie.bpgc
fonte
@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.

kgiannakakis
fonte
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

Anup Cowkur
fonte
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.

Matt Accola
fonte
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.

Anurag Srivastava
fonte
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);
Mongi Zaidi
fonte
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();
Android
fonte
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.

madx
fonte
4

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

Coelho
fonte
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.

Sujal Mandal
fonte
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.

Aristo Michael
fonte
1

Apenas guarde

Intent intent = new Intent(ProfileActivity.this,
    LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);
Gaurav Vashisth
fonte
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.

Ian Wambai
fonte
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();
Maomé
fonte
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);
S.Sathya Priya
fonte
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();
Prashant Kumar
fonte
você conhecia setFlags e addFlags?
GvSharma de
0

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

Hally Trần
fonte
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
}
Gibolt
fonte