Removendo uma Atividade da Pilha do Histórico

382

Meu aplicativo mostra uma atividade de inscrição na primeira vez que o usuário o executa, se parece com:

  1. ActivitySplashScreen (bem-vindo ao jogo, inscreva-se em uma conta?)
  2. ActivitySplashScreenSignUp (ótimo, preencha estas informações)
  3. ActivityGameMain (tela principal do jogo)

portanto, as atividades se iniciam exatamente nessa ordem, quando o usuário clica em um botão em cada tela.

Quando o usuário passa da atividade nº 2 para a nº 3, é possível apagar os nºs 1 e 2 da pilha de histórico completamente? Eu gostaria que, se o usuário estivesse na posição # 3 e apertasse o botão Voltar, eles apenas fossem para a tela inicial, em vez de voltar para a tela inicial.

Eu acho que posso fazer isso com tarefas (por exemplo, iniciar uma nova tarefa no 3), mas queria ver se havia um método mais simples,

obrigado

Marca
fonte
Depois de estar na tela inicial, quando o usuário retoma seu aplicativo, ele é levado para ActivitySplashScreen ou ActivityGameMain?
Tamil

Respostas:

632

Você pode conseguir isto, definindo o android:noHistory atributo para "true"nos relevantes <activity>entradas no seu AndroidManifest.xmlarquivo. Por exemplo:

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />
Aitor Gómez
fonte
12
Essa é a melhor maneira de fazer isso.
shkschneider
22
Equivalentemente você pode usar FLAG_ACTIVITY_NO_HISTORY.
Timmmm 30/10/12
34
Como posso conseguir isso a partir do código? Porque eu não quero fazer isso o tempo todo. Gostaria de remover uma determinada atividade da história apenas sob algumas condições.
Namratha
8
Lembre-se de que o uso do atributo noHistory fará com que a atividade termine, o que pode causar um comportamento inesperado com o login no G +, por exemplo. Consulte: stackoverflow.com/questions/20383878/… Levei um tempo para encontrar esse bug, pois meu aplicativo continuava travando sem deixar vestígios.
Acapulco
13
É difícil copiar o sinalizador necessário, pois é um link; portanto, aqui pode ser facilmente copiado. android:noHistory="true"
MirroredFate
137

Você pode usar o encaminhamento para remover a atividade anterior da pilha de atividades enquanto inicia a próxima. Há um exemplo disso no APIDemos , mas basicamente tudo o que você está fazendo é ligar finish()imediatamente após a chamada startActivity().

Dan Lew
fonte
11
Oi Daniel, eu li o exemplo, mas isso só limpará a pilha de histórico em 1 atividade, não é? Se minha pilha se parece com A, B e eu estou iniciando C, quero que C seja a nova raiz e completamente clara A e B. No exemplo sdk, chamar finish () de B me deixaria com uma pilha de A C, não é? Obrigado.
Mark
11
Você pode limpar A ao iniciar B e limpar B ao iniciar C; no entanto, suponho que você não seria capaz de voltar de B para A se é isso que deseja. Vou ter que pensar mais nisso se isso for um problema.
21411 Dan Lew
3
Marque, para conseguir o que deseja, use a bandeira: FLAG_ACTIVITY_CLEAR_TOP. Espero que ajude.
Francisco Junior
3
FLAG_ACTIVITY_CLEAR_TOPnão funcionará porque C ainda não está na pilha de trás.
Timmmm 30/10/12
11
@DanielLew Existem muitos exemplos nos APIDemos. Você sugeriria o nome do exemplo?
Stephane
52

Sim, consulte Intent.FLAG_ACTIVITY_NO_HISTORY .

Matthias
fonte
46
Observe que isso não define um histórico para a atividade para a qual você está iniciando. Para não ter histórico para a atividade da qual você está iniciando, basta defini-lo android:noHistory="true"no manifesto.
georgiecasey
11
Isso funciona bem. Use intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)para definir este sinalizador.
precisa saber é
11
@georgiecasey isso é útil quando às vezes você deseja mantê-lo na história e, às vezes, não na história.
Vihaan Verma
24

Provavelmente, essa não é a maneira ideal de fazê-lo. Se alguém tiver uma maneira melhor, esperarei implementá-la. Aqui está como eu realizei essa tarefa específica com o pré-version-11 sdk.

em cada aula que você deseja ir quando estiver na hora certa, faça o seguinte:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

então o que precisa desencadear a cadeia de pops da pilha precisa chamar assim quando você deseja iniciá-lo:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

Então as atividades não estão na pilha!
Lembre-se, pessoal, de que você pode iniciar uma atividade e, em seguida, começar a limpar por trás dela, a execução não segue um único thread (a interface do usuário).

Travis
fonte
Caso alguém se depare com isso mais tarde, achei que seria importante saber que, se você girou a tela, o Android será útil para reiniciar seu aplicativo quando você tirar a última atividade da pilha. Esteja ciente disso!
Travis
Esta é uma resposta boa, se você só quer remover uma atividade da pilha condicionalmente dependendo do que o usuário faz na próxima atividade +1
theMothaShip
23

Uma maneira que funciona antes da API 11 é iniciar ActivityGameMainprimeiro e, em seguida, na onCreateatividade iniciar sua ActivitySplashScreenatividade. A ActivityGameMainnão aparecerá como você chama startActivity cedo demais para o respingo.

Em seguida, você pode limpar a pilha ao iniciar ActivityGameMain, definindo esses sinalizadores no Intent:

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

Você também deve adicionar isso ao ActivitySplashScreen:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

Para que pressionar essa atividade não volte para o seu ActivityGameMain.

Suponho que você também não queira que a tela inicial volte, para conseguir isso, sugiro configurá-la noHistoryno seu AndroidManifest.xml. Em seguida, coloque o goBackPressedcódigo na sua ActivitySplashScreenSignUpclasse.

No entanto, eu encontrei algumas maneiras de quebrar isso. Inicie outro aplicativo a partir de uma notificação enquanto ActivitySplashScreenSignUpé mostrado e o histórico anterior não é redefinido.

A única maneira real de contornar isso é na API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mxcl
fonte
20

Eu uso assim.

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
Smiderle
fonte
Obrigado. Achei isso útil no caso de haver um botão Início no meu menu e não queria que as atividades empilhadas fossem exibidas depois que o usuário clicasse em casa a partir daí.
ghitesh
8

Sei que estou atrasado (faz dois anos que a pergunta foi feita), mas consegui isso interceptando o botão Voltar. Em vez de verificar atividades específicas, basta olhar para a contagem e, se for menor que 3, simplesmente envia o aplicativo para trás (pausando o aplicativo e retornando o usuário para o que estava sendo executado antes do lançamento). Verifico menos de três, porque só tenho uma tela de introdução. Além disso, verifico a contagem, pois meu aplicativo permite que o usuário navegue de volta à tela inicial pelo menu; portanto, isso permite que ele faça backup em outras telas normalmente, se houver outras atividades além da tela de introdução na pilha.

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}
alphonzo79
fonte
7

No manifesto, você pode adicionar:

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

Você também pode ligar

finish()

imediatamente após chamar startActivity (..)

Anubhav
fonte
2
Melhor usar sinalizadores de atividade do que colocar as coisas no manifesto.
Trevor Hart
6

Basta definir noHistory="true"no arquivo de manifesto . Faz com que a atividade seja removida do backstack.

Stanislaw Brzezinski
fonte
4

É uma loucura que ninguém tenha mencionado essa solução elegante. Essa deve ser a resposta aceita.

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

A chave aqui é usar intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); para o intermediário Activity. Depois que o link do meio é quebrado, oDashActivity testamento será o primeiro e o último da pilha.

android:noHistory="true"é uma solução ruim, pois causa problemas ao confiar no Activityretorno de chamada, por exemplo onActivityResult. Esta é a solução recomendada e deve ser aceita.

Rowland Mtetezi
fonte
11
Essa bandeira parecia boa demais para ser verdade. FLAG_ACTIVITY_NO_HISTORY funciona bem e como seria de esperar até colocar o aplicativo em segundo plano e voltar ao primeiro plano novamente, mantendo a atividade com o sinalizador no topo da pilha. Ao entrar em segundo plano, a atividade é destruída. Ao retornar ao aplicativo, você verá a atividade anterior da pilha. Eu definitivamente não queria esse comportamento.
precisa
4

É tarde demais, mas espero que ajude. A maioria das respostas não está apontando na direção certa. Existem duas bandeiras simples para isso.

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Dos documentos do Android:

public static final int FLAG_ACTIVITY_CLEAR_TASK Adicionado no nível 11 da API

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

atividade a ser limpa antes do início da atividade. Ou seja, a atividade se torna a nova raiz de uma tarefa vazia e quaisquer atividades antigas são concluídas. Isso pode ser usado apenas em conjunto com FLAG_ACTIVITY_NEW_TASK.

Nouman Ghaffar
fonte
1

Basta chamar this.finish () antes de startActivity (intent) como este-

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

fonte
usuários que possuem erro "this", devem alterá-lo para "ActivityOne.this"
ninbit 17/18
1

A remoção de uma atividade de um histórico é concluída Ao definir o sinalizador antes da atividade que você não deseja

A-> B-> C-> D

Suponha que A, B, C e D sejam 4 Atividades, se você deseja limpar B e C e defina o sinalizador

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

Na atividade A e B

Aqui está o bit de código

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
ricky
fonte
0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.finishAndRemoveTask();
        }
        else {
            super.finish();
        }
ansioso
fonte
-7

Tente o seguinte:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

é o nível 1 da API, verifique o link .

Alécio Carvalho
fonte
2
O que isso deve fazer? Definitivamente não resolve o problema em questão.
Rodrigo-silveira
Tem certeza de que não quis dizer isso Intent.FLAG_ACTIVITY_NO_HISTORY?
Motim vai Woof