Todas as atividades no meu aplicativo exigem que um usuário esteja logado para visualizar. Os usuários podem sair de praticamente qualquer atividade. Este é um requisito do aplicativo. A qualquer momento, se o usuário sair, quero enviar o usuário para o Login Activity
. Nesse ponto, quero que essa atividade esteja na parte inferior da pilha do histórico, de modo que pressionar o botão "voltar" retorne o usuário à tela inicial do Android.
Já vi essa pergunta em alguns lugares diferentes, todas respondidas com respostas semelhantes (que descrevi aqui), mas quero colocá-la aqui para obter feedback.
Tentei abrir a atividade de logon definindo seus Intent
sinalizadores para o FLAG_ACTIVITY_CLEAR_TOP
que parece fazer o descrito na documentação, mas não alcança meu objetivo de colocar a atividade de logon na parte inferior da pilha do histórico e impedindo que o usuário volte. às atividades de logon vistas anteriormente. Também tentei usar android:launchMode="singleTop"
a atividade Login no manifesto, mas isso também não cumpre minha meta (e parece não ter efeito mesmo).
Acredito que preciso limpar a pilha de histórico ou concluir todas as atividades abertas anteriormente.
Uma opção é ter o onCreate
status de logon de verificação de cada atividade e, finish()
se não estiver logado. Não gosto dessa opção, pois o botão Voltar ainda estará disponível para uso, navegando de volta à medida que as atividades se fecham.
A próxima opção é manter uma LinkedList
referência a todas as atividades abertas que são estaticamente acessíveis de qualquer lugar (talvez usando referências fracas). No logout, acessarei esta lista e repetirei todas as atividades abertas anteriormente, invocando finish()
cada uma. Provavelmente vou começar a implementar esse método em breve.
Eu prefiro usar alguns Intent
truques de bandeira para fazer isso, no entanto. Ficaria feliz em descobrir que posso atender aos requisitos do meu aplicativo sem precisar usar nenhum dos dois métodos descritos acima.
Existe uma maneira de fazer isso usando Intent
ou manifestar configurações ou a minha segunda opção é manter uma LinkedList
das atividades abertas a melhor opção? Ou existe outra opção que estou completamente ignorando?
Parece um rito de passagem que um novo programador do Android gaste um dia pesquisando esse problema e lendo todos esses threads do StackOverflow. Agora sou recém iniciado e deixo aqui vestígios de minha humilde experiência para ajudar um futuro peregrino.
Primeiro, não há uma maneira óbvia ou imediata de fazer isso de acordo com minha pesquisa.
(as of September 2012).
Você pensaria que poderia ser simples,startActivity(new Intent(this, LoginActivity.class), CLEAR_STACK)
mas não .Você pode fazer
startActivity(new Intent(this, LoginActivity.class))
comFLAG_ACTIVITY_CLEAR_TOP
- e isto fará com que o quadro para procurar para baixo da pilha, encontrar o seu instância anterior original LoginActivity, recriá-lo e limpar o resto da (para cima) pilha. E como o Login está presumivelmente na parte inferior da pilha, agora você tem uma pilha vazia e o botão Voltar simplesmente sai do aplicativo.MAS - isso só funciona se você deixou a instância original do LoginActivity ativa na base da sua pilha. Se, como muitos programadores, você optar por fazer
finish()
issoLoginActivity
depois que o usuário fizer login com sucesso, ele nãoFLAG_ACTIVITY_CLEAR_TOP
estará mais na base da pilha e a semântica não se aplicará ... você acaba criando um novoLoginActivity
no topo da pilha existente. O que quase certamente NÃO é o que você deseja (comportamento estranho em que o usuário pode "voltar" do caminho para uma tela anterior).Portanto, se você já teve
finish()
esse problemaLoginActivity
, precisa seguir algum mecanismo para limpar sua pilha e iniciar um novoLoginActivity
. Parece que a resposta@doreamon
neste tópico é a melhor solução (pelo menos para meus humildes olhos):https://stackoverflow.com/a/9580057/614880
Eu suspeito fortemente que as implicações complicadas de você deixar o LoginActivity ativo estão causando muita dessa confusão.
Boa sorte.
fonte
ATUALIZAR
o super
finishAffinity()
método ajudará a reduzir o código, mas conseguirá o mesmo. Terminará a atividade atual, bem como todas as atividades na pilha, usegetActivity().finishAffinity()
se você estiver em um fragmento.RESPOSTA ORIGINAL
Suponha que LoginActivity -> HomeActivity -> ... -> SettingsActivity indicativo de chamadaOut ():
Página inicial
Isso funciona para mim, espero que seja útil para você também. :)
fonte
Se você usa a API 11 ou superior, pode tentar o seguinte:
FLAG_ACTIVITY_CLEAR_TASK
- parece estar resolvendo exatamente o problema que está tendo. Obviamente, o público pré-API 11 teria que usar alguma combinação de todas as atividades para verificar um extra, como sugere @doreamon, ou algum outro truque.(Observe também: para usar isso, você deve passar
FLAG_ACTIVITY_NEW_TASK
)fonte
finish();
fará o trabalho para evitar voltar após o logout. Qual é a necessidade de definir sinalizadores?Também passei algumas horas nisso ... e concordo que FLAG_ACTIVITY_CLEAR_TOP soa como o que você deseja: limpe toda a pilha, exceto a atividade que está sendo iniciada, para que o botão Voltar saia do aplicativo. No entanto, como Mike Repass mencionou, FLAG_ACTIVITY_CLEAR_TOP só funciona quando a atividade que você está iniciando já está na pilha; quando a atividade não está lá, a bandeira não faz nada.
O que fazer? Coloque a atividade sendo iniciada na pilha com FLAG_ACTIVITY_NEW_TASK , que torna essa atividade o início de uma nova tarefa na pilha de histórico. Em seguida, adicione o sinalizador FLAG_ACTIVITY_CLEAR_TOP.
Agora, quando FLAG_ACTIVITY_CLEAR_TOP for encontrar a nova atividade na pilha, ela estará lá e será exibida antes que todo o resto seja limpo.
Aqui está a minha função de logout; o parâmetro View é o botão ao qual a função está conectada.
fonte
FLAG_ACTIVITY_CLEAR_TASK
ainda não foi adicionadoMuitas respostas. Pode ser que este também ajude
Versão Kotlin-
fonte
Use isso, deve ser útil para você. Resposta xbakesx ligeiramente modificada.
fonte
A solução aceita não está correta, há problemas, pois o uso de um receptor de transmissão não é uma boa ideia para esse problema. Se sua atividade já chamou o método onDestroy (), você não receberá o receptor. A melhor solução é ter um valor booleano em suas preferências compartilhadas e verificá-lo no método onCreate () da sua atividade. Se não deve ser chamado quando o usuário não estiver conectado, conclua a atividade. Aqui está o código de exemplo para isso. Tão simples e funciona para todas as condições.
fonte
onResume()
methode. Porque quando você pressiona o botão Voltar, é mais provável que a atividade seja retomada em vez de criada.Às vezes
finish()
não está funcionandoEu resolvi esse problema com
finishAffinity()
fonte
Eu sugeriria uma abordagem diferente para esta pergunta. Talvez não seja o mais eficiente, mas acho que é o mais fácil de aplicar e requer muito pouco código. Escrever o próximo código em sua primeira atividade (atividade de logon, no meu caso) não permitirá que o usuário volte para as atividades iniciadas anteriormente após o logout.
Suponho que o LoginActivity tenha terminado logo após o login do usuário, para que ele não possa voltar mais tarde pressionando o botão Voltar. Em vez disso, o usuário deve pressionar um botão de logout dentro do aplicativo para fazer logoff corretamente. O que esse botão de logoff implementaria é uma intenção simples, como a seguir:
Todas as sugestões são bem vindas.
fonte
A resposta selecionada é inteligente e complicada. Aqui está como eu fiz isso:
LoginActivity é a atividade raiz da tarefa, defina android: noHistory = "true" no Manifest.xml; Digamos que você queira sair do SettingsActivity, faça o seguinte:
fonte
Aqui está a solução que eu encontrei no meu aplicativo.
No meu LoginActivity, depois de processar com êxito um login, inicio o próximo de maneira diferente, dependendo do nível da API.
Em seguida, no método onActivityForResult do meu LoginActivity:
Por fim, depois de processar um logout em qualquer outra atividade:
Quando no Gingerbread, fica assim se eu pressionar o botão voltar de MainActivity, o LoginActivity será imediatamente oculto. No Honeycomb e posterior, apenas concluo o LoginActivity após o processamento de um login e ele é recriado corretamente após o processamento de um logout.
fonte
Isso funcionou para mim:
fonte
Inicie sua atividade com StartActivityForResult e, enquanto você efetua logout, defina seu resultado e, de acordo com o resultado, termine sua atividade
fonte
A solução @doreamon fornecida funciona bem em todos os casos, exceto um:
Se Após o login, o usuário da tela Killing Login navegou diretamente para uma tela do meio. Por exemplo, em um fluxo de A-> B-> C, navegue como: Login -> B -> C -> Pressione o atalho para voltar para casa. O uso de FLAG_ACTIVITY_CLEAR_TOP limpa apenas a atividade C, pois a Página inicial (A) não está no histórico da pilha. Pressionar Voltar em uma tela nos levará de volta a B.
Para resolver esse problema, podemos manter uma pilha de atividades (Arraylist) e, quando pressionamos o botão home, precisamos matar todas as atividades nessa pilha.
fonte
É possível gerenciando um sinalizador em SharedPreferences ou em Application Activity.
No início do aplicativo (na tela inicial), defina o sinalizador = false; No evento Logout Click, apenas defina o sinalizador true e, em OnResume () de todas as atividades, verifique se o sinalizador é true e chame finish ().
Ele funciona como um encanto :)
fonte
ao clicar em Logout, você pode chamar isso
onActivityResult () da atividade anterior, chame esse código acima novamente até concluir todas as atividades.
fonte
O que você quer fazer é chamar logout () e finish () nos métodos onStop () ou onPause (). Isso forçará o Android a ligar para onCreate () quando a atividade for reativada, pois ela não ficará mais na pilha de atividades. Em seguida, faça o que você diz: em onCreate () verifique o status de logon e encaminhe para a tela de logon, se não estiver logado.
Outra coisa que você pode fazer é verificar o status de logon em onResume () e, se não estiver logado, terminar () e iniciar a atividade de logon.
fonte