Concluir todas as atividades anteriores

368

Meu aplicativo possui as seguintes telas de fluxo:

Home->screen 1->screen 2->screen 3->screen 4->screen 5

Agora eu tenho um log out botão comum em cada tela

( Home/ screen 1 / screen 2 /screen 3/ screen 4 / screen 5)

Quero que, quando o usuário clicar no botão de logout (de qualquer tela), todas as telas sejam finalizadas e uma nova tela Log inseja aberta.

Eu tentei quase tudo FLAG_ACTIVITYpara conseguir isso. Também passo por algumas respostas no stackoverflow, mas não consegui resolver o problema. Meu aplicativo está no Android 1.6, portanto, não posso usarFLAG_ACTIVITY_CLEAR_TASK

Existe alguma maneira de resolver o problema?

Tanmay Mandal
fonte
Você executa suas atividades aninhadas usando startActivityForResult?
woodshy
Todas as atividades são iniciadas com startActivity.
precisa
Estou usando atividades aninhadas enquanto o bacalhau executa finishaffinitytask () na atividade aninhada. isso muda o comportamento? às vezes, estou recebendo Falha na entrega do resultado ResultInfo quando o finishaffinitytask é executado.
Ripal Tamboli
Por favor, verifique esta resposta, Ele certamente irá ajudá-lo a stackoverflow.com/a/25159180/2732632
Kimmi Dhingra
3
O Android 21 apresentou o Activity.finishAndRemoveTask ().
Joseph Johnson

Respostas:

543

Usar:

Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Isso limpará todas as atividades em cima da casa.

Supondo que você esteja finalizando a tela de login quando o usuário efetuar login e a página inicial for criada e depois todas as telas de 1 a 5 em cima dessa. O código que eu publiquei retornará à tela inicial, finalizando todas as outras atividades. Você pode adicionar um extra na intenção e ler na atividade da tela inicial e finalizá-la também (talvez inicie a tela de login novamente a partir daí ou algo assim).

Não tenho certeza, mas você também pode tentar acessar com esta bandeira. Não sei como as atividades serão ordenadas nesse caso. Portanto, não sei se ele limpará os que estão abaixo da tela em que você está, incluindo o que você está atualmente, mas é definitivamente o caminho a percorrer.

Espero que isto ajude.

DArkO
fonte
O usuário está mostrando sua primeira tela como tela inicial, esse é o problema principal.
precisa
bem como eu tenho a minha resposta, você precisa voltar para a tela inicial e finalizá-la. portanto, o processo chama a intenção acima de qualquer tela. receba a intenção na tela inicial e instale instantaneamente uma intenção de efetuar login e terminar a página inicial após o método startActivity. você também pode substituir a animação pendente para nula para dentro e para fora, para que não mostre a transição (eu faço isso porque parece um pouco mais rápido). então isso deve estar funcionando bem para o que você precisa.
Darko
10
Em vez de declarar a atividade como singleInstance, considere usar FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOPcomo sinalizadores para a Intenção. Isso terminará as atividades intermediárias e iniciará (ou trará de volta ao primeiro plano) a atividade desejada.
CommonsWare
13
@ CommonsWare A adição intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);à minha atividade não me ajudou.Ele não concluiu as atividades intermediárias.Quando pressiono a tela de login, consigo ver as atividades anteriores.Aqui está o meu código Intent intent=new Intent(BaseActivity.this, Login.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);startActivity(intent);.
precisa
26
esse código limpa apenas a pilha de atividades superior, para limpar todas as atividades intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
precisa saber é o seguinte
318

Você pode tentar Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK. Ele limpa totalmente todas as atividades anteriores e inicia uma nova atividade.

Kong Ken
fonte
11
A solução adequada, mas apenas a API 11
#
Acabei usando esse sinalizador extra, pois não causa um atraso ao mostrar a atividade principal (não o reinicia, por isso é muito mais rápido).
Maurizio
2
@riwnodennyk why API 11+?
Muhammad Babar
17
Use IntentCompat.FLAG_ACTIVITY_CLEAR_TASK para versões anteriores a 11 #
Steven Pena
2
@ono Sim. Isso deve ser tudo o que você precisa. Verifique se o modo de inicialização da atividade de destino está definido como "tarefa única" no manifesto.
Steven Pena
137

Antes de iniciar sua nova atividade, basta adicionar o seguinte código:

finishAffinity();

Ou se você deseja que ele funcione nas versões anteriores do Android:

ActivityCompat.finishAffinity(this);
Henrique
fonte
12
ActivityCompat.finishAffinity (this); chama activity.finish () para api <16. Portanto, não funcionará.
Aamir Abro
11
@Beto Caldas, eu mesmo confirmei o código-fonte, ele não funcionará para a API <16 como o AamirAbro mencionou. Ela só vai terminar a atividade que você passar API <16.
HendraWD
39

Quando o usuário deseja sair de todas as atividades abertas , ele deve pressionar um botão que carrega a primeira Atividade executada quando o aplicativo é iniciado, limpar todas as outras atividades e concluir a última atividade restante. Execute o código a seguir quando o usuário pressionar o botão sair. No meu caso, LoginActivityé a primeira atividade do meu programa a ser executada.

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

O código acima limpa todas as atividades, exceto LoginActivity. Em seguida, coloque o seguinte código dentro do LoginActivity's onCreate(...), para ouvir quando LoginActivityé recriado e o sinal' EXIT 'foi passado:

if (getIntent().getBooleanExtra("EXIT", false)) {
    finish();  
}

Por que tornar tão difícil um botão de saída no Android?

O Android se esforça para desencorajá-lo a ter um botão "exit" em seu aplicativo, porque eles querem que o usuário nunca se importe com a execução ou não dos programas que eles usam em segundo plano.

Os desenvolvedores do sistema operacional Android desejam que seu programa seja capaz de sobreviver a um desligamento inesperado e desligue o telefone e, quando o usuário reinicia o programa, ele retoma exatamente de onde parou. Assim, o usuário pode receber uma ligação enquanto usa seu aplicativo e abrir mapas que exigem que seu aplicativo seja liberado para obter mais recursos.

Quando o usuário retoma seu aplicativo, ele retoma exatamente de onde parou sem interrupção. Esse botão de saída está consumindo energia do gerenciador de atividades, causando problemas no ciclo de vida do programa Android gerenciado automaticamente.

Eric Leschinski
fonte
31
Intent intent = new Intent(this, classObject);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

Isso funcionará para todas as versões do Android. Onde IntentCompata classe foi adicionada na biblioteca de suporte do Android.

Gema
fonte
IntentCompat.FLAG_ACTIVITY_CLEAR_TASKnão é reconhecido, use em Intentvez de IntentCompat.
CoolMind 29/10/19
30

Use o seguinte para atividade

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

remova o sinalizador CLEAR_TASK para uso de fragmentos.

Espero que isso possa ser usado para algumas pessoas.

Aristo Michael
fonte
24

Acho que estou atrasado, mas há uma resposta simples e curta. Existe um método finishAffinity () em Activity que finaliza a atividade atual e todas as atividades pai, mas funciona apenas no Android 4.1 ou superior.

Para API 16+, use

finishAffinity();

Para menores de 16 anos, use

ActivityCompat.finishAffinity(YourActivity.this);

Espero que ajude!

Akshay Taru
fonte
21

De developer.android.com :

public void finishAffinity ()

Adicionado no nível 16 da API

Conclua esta atividade e todas as atividades imediatamente abaixo dela na tarefa atual que possui a mesma afinidade. Isso geralmente é usado quando um aplicativo pode ser iniciado em outra tarefa (como de um ACTION_VIEW de um tipo de conteúdo que ele entende) e o usuário usa a navegação para sair da tarefa atual e fazer sua própria tarefa. Nesse caso, se o usuário tiver navegado para outras atividades do segundo aplicativo, todas elas deverão ser removidas da tarefa original como parte da alternância de tarefas.

Observe que esse acabamento não permite que você entregue resultados à atividade anterior e uma exceção será lançada se você estiver tentando fazê-lo.

gmrl
fonte
19

Por outro lado, é bom saber
Esta resposta funciona ( https://stackoverflow.com/a/13468685/7034327 )

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

enquanto isso não funciona

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

.setFlags() substitui os sinalizadores anteriores e não acrescenta novos sinalizadores enquanto o .addFlags()faz.

Então isso também vai funcionar

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
John
fonte
Grande explicação sobre a diferença entre setFlag vs addFlag, obrigado
Pelanes
13

Se o seu aplicativo tiver no mínimo a versão 16 do sdk, você poderá usar finishAffinity ()

Conclua esta atividade e todas as atividades imediatamente abaixo dela na tarefa atual que possui a mesma afinidade.

Isso é bom para mim. Na tela Pagamento principal, remova todas as atividades de pilha traseira,

@Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29

Jaydeep purohit
fonte
10

Uma solução que eu implementei para isso (acho que a encontrei no Stack Overflow em algum lugar, mas não me lembro, então, graças a quem fez isso em primeiro lugar):

De qualquer uma de suas atividades, faça o seguinte:

// Clear your session, remove preferences, etc.
Intent intent  = new Intent(getBaseContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Em seu LoginActivity, substitua onKeyDown:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
Andy
fonte
3
Geralmente, é uma péssima idéia, embora funcione, introduza um ponto de contato que poderá se romper no futuro e será difícil depurar. Eu estou lhe dizendo com a experiência :)
Martin Marconcini
10

Para o botão de logout na última tela do aplicativo, use este código no ouvinte do botão de logout para concluir todas as atividades anteriores abertas e seu problema foi resolvido.

{
Intent intent = new Intent(this, loginScreen.class);
ntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
Amrit
fonte
8
    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
6
por que FLAG_ACTIVITY_CLEAR_TASK duas vezes?
Choletski
11
Pelo que entendi, .setFlags substitui os sinalizadores anteriores e não anexa nenhum sinalizador. .addFlags é o que você queria usar, presumo? Cause todo o código acima i1.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); é eliminado
iOSAndroidWindowsMobileAppsDev
addFlags Funciona para mim
Jamil
11
setFlagssubstituirá todos os anteriores; portanto, o último setFlagssó será válido; os anteriores serão substituídos. Então você não precisa ligari1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mtrakal
8

Eu tenho o mesmo problema que você pode usar IntentCompat, assim:

import android.support.v4.content.IntentCompat;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);

esse código funciona para mim.

Api Android 17

Adnan Abdollah Zaki
fonte
8

No meu caso, eu uso a finishAffinity()função na última atividade como:

finishAffinity()
startHomeActivity()

Espero que seja útil.

Djek-Grif
fonte
7

em vez de usar finish()apenas usefinishAffinity();

Hitesh Kushwah
fonte
11
Boa resposta, mas requer API 16
Akshay Taru
6

Entre -> tela inicial-> tela 1-> tela 2-> tela 3-> tela 4-> tela 5

na tela 4 (ou qualquer outra) ->

StartActivity (Entrar)
com
FLAG_ACTIVITY_CLEAR_TOP

Plamen Nikolov
fonte
2
Quando eu pressiono o botão Voltar, todas as atividades anteriores são exibidas na ordem em que estavam. Essas atividades precisam ser fechadas. Quando o botão Logout clicou, haverá apenas uma atividade na pilha e essa será a atividade de logon. O usuário inicia a partir da tela inicial.
precisa
6

para API> = 15 a API 23 solução simples.

 Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
 nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
 startActivity(nextScreen);
 ActivityCompat.finishAffinity(currentActivity.this);
Kamal Bunkar
fonte
Elabore sua resposta para que todos possam se beneficiar dela.
Shubhamoy
5

Se você estiver usando startActivityForResult()em suas atividades anteriores, basta substituir OnActivityResult()e chamar o finish();método dentro dele em todas as atividades. Isso fará o trabalho ...

ngesh
fonte
Não, estou usando startActivityapenas.
precisa
Será difícil manter-se onActivityResultem cada atividade. Implementei a sugestão de DArkO e alcancei meu objetivo e obrigado pela ajuda.
Tanmay Mandal
3

Quando o usuário clicar no botão logout, escreva o seguinte código:

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

E também quando após o login, se você chamar uma nova atividade, não use finish ();

Nikki
fonte
2

Simplesmente, quando você sai da tela de login, não ao terminar a tela de login.

E, em todas as atividades avançadas, use isto para logout:

final Intent intent = new Intent(getBaseContext(), LoginScreen.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

Funciona perfeitamente.

Asad Rao
fonte
1

Se você fizer o login do usuário screen 1e, a partir daí, for para as outras telas, use

Intent intent = new Intent(this, Screen1.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Gabriel Negut
fonte
Quando eu pressiono o botão Voltar, todas as atividades anteriores são exibidas na ordem em que estavam. Essas atividades precisam ser fechadas. Quando o botão Logout clicou, haverá apenas uma atividade na pilha e essa será a atividade de login.
precisa
Se você deseja esse comportamento, substitua onKeyDowne onBackPressed(ou onKeyDown, se desejar oferecer suporte a versões do Android <2.0) em cada uma de suas atividades (exceto a de logon) e startActivity(login), como mostrado acima.
Gabriel Negut
Eu tenho um botão que me levará para a tela de login finalizando todas as atividades na pilha. É possível?
precisa
1

Eu encontrei assim, vai limpar todo o histórico e sair

Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
Intent intent = new Intent(getApplicationContext(), SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

finish();
System.exit(0);
pirooz jenabi
fonte
1

Acho que estou atrasado, mas há uma resposta simples e curta. Existe um método finishAffinity () em Activity que finaliza a atividade atual e todas as atividades pai, mas funciona apenas no Android 4.1 ou superior.

Para API 16+, use

finishAffinity ();

Para menores de 16 anos, use

ActivityCompat.finishAffinity (YourActivity.this);

Espero que ajude!

O shareedit respondeu em 27 de maio de 18 às 8:03

Akshay Taru

Samuel Quiroz
fonte
0

Encontrei esta solução para trabalhar em todos os dispositivos, apesar do nível da API (mesmo para <11)

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);
priyankvex
fonte
0

Melhor maneira de fechar todas as atividades anteriores e limpar a memória

finishAffinity()
System.exit(0);
Shivam Tripathi
fonte
0
startActivity(
                Intent(this, LoginActivity::class.java)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .addFlags(FLAG_ACTIVITY_CLEAR_TASK)
            )
Kishan Solanki
fonte