Eu tenho uma tela inicial em um cronômetro. Meu problema é que antes de iniciar finish()
minha atividade, preciso verificar se a próxima atividade foi iniciada porque uma caixa de diálogo do sistema aparece e eu só quero finish()
; depois que o usuário selecionou uma opção da caixa de diálogo?
Sei que há muitas perguntas sobre como ver se sua atividade está em primeiro plano, mas não sei se isso permite caixas de diálogo no topo da atividade também.
Aqui está o problema, o vermelho é a minha atividade que está em segundo plano enquanto o diálogo está em primeiro plano:
EDIT: Eu tentei apenas não usar, finish()
mas minha atividade pode voltar para a pilha de aplicativos que estou tentando evitar.
Respostas:
Isso é o que é recomendado como a solução certa :
No seu
finish()
método, você desejaisActivityVisible()
verificar se a atividade está visível ou não. Lá você também pode verificar se o usuário selecionou uma opção ou não. Continue quando ambas as condições forem atendidas.A fonte também menciona duas soluções erradas ... portanto, evite fazer isso.
Fonte: stackoverflow
fonte
onPause
,onStop
nem oonResume
evento é chamado. Então o que você faz se nenhum desses eventos for disparado ?!Se tiver como objetivo a API de nível 14 ou superior, pode-se usar android.app.Application.ActivityLifecycleCallbacks
fonte
UPD : atualizado para o estado
Lifecycle.State.RESUMED
. Obrigado a @htafoya por isso.Em 2019, com a ajuda da nova biblioteca de suporte
28+
ou AndroidX, você pode simplesmente usar:Você pode ler mais na documentação para entender o que aconteceu nos bastidores.
fonte
activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
ou COMEÇAR.INITIALIZED
não garante que esteja em primeiro plano.Activity :: hasWindowFocus () retorna o booleano que você precisa.
Aqui está um exemplo de aula para verificar a visibilidade de suas atividades de onde você estiver.
Lembre-se de que se você mostrar um caixa de diálogo , o resultado será falso, pois a caixa de diálogo terá o foco principal. Fora isso, é realmente útil e mais confiável do que as soluções sugeridas.
fonte
Essa é exatamente a diferença entre os eventos
onPause
eonStop
da atividade, conforme descrito na documentação da classe Activity .Se bem entendi, o que você quer fazer é ligar
finish()
de sua atividadeonStop
para encerrá-la. Veja a imagem em anexo do aplicativo Activity Lifecycle Demo . É assim que parece quando a Atividade B é iniciada a partir da Atividade A. A ordem dos eventos é de baixo para cima para que você possa ver que a Atividade AonStop
é chamada depois que a Atividade BonResume
já foi chamada.Caso seja exibida uma caixa de diálogo, sua atividade fica esmaecida no fundo e apenas
onPause
é chamada.fonte
Duas soluções possíveis:
1) Callbacks de ciclo de vida de atividades
Use um aplicativo que implemente ActivityLifecycleCallbacks e use-o para rastrear eventos de ciclo de vida de atividades em seu aplicativo. Observe que ActivityLifecycleCallbacks são para Android api> = 14. Para Android API anterior, você precisa implementá-lo sozinho em todas as suas atividades ;-)
Use o aplicativo quando precisar compartilhar / armazenar estados em atividades.
2) Verifique as informações do processo em execução
Você pode verificar o status de um processo em execução com esta classe RunningAppProcessInfo
Obtenha a lista de processos em execução com ActivityManager.getRunningAppProcesses () e filtre a lista de resultados para verificar o RunningAppProcessInfo desejado e verifique sua "importância"
fonte
Eu criei um projeto no github app-foreground-background-listen
que usa uma lógica muito simples e funciona bem com todos os níveis de API do Android.
fonte
Use o intervalo de tempo entre pausar e retomar do segundo plano para determinar se ele foi ativado do segundo plano
Em aplicativo personalizado
Na classe BaseActivity
fonte
Acho que tenho uma solução melhor. Porque você pode criar simplesmente MyApplication.activityResumed (); a cada atividade por uma extensão.
Em primeiro lugar, você deve criar (como CyberneticTwerkGuruOrc)
Em seguida, você deve adicionar a classe Application ao AndroidManifest.xml
Em seguida, crie a classe ActivityBase
Finalmente, ao criar uma nova Activity, você pode simplesmente estendê-la por ActivityBase em vez de Activity.
Para mim, é um método melhor porque você só precisa se lembrar de extend by ActivityBase. Além disso, você pode expandir sua função básica no futuro. No meu caso, adicionei receptores para meu serviço e alertas sobre a rede em uma classe.
Se você quiser verificar a visibilidade do seu aplicativo, basta ligar
fonte
Isso pode ser alcançado de maneira eficiente, usando Application.ActivityLifecycleCallbacks
Por exemplo, vamos pegar o nome da classe Activity como ProfileActivity permite descobrir se ela está em primeiro plano ou em segundo plano
primeiro precisamos criar nossa classe de aplicativo estendendo a classe de aplicativo
que implementa
Vamos ser minha classe de aplicativo da seguinte maneira
Aula de aplicação
na classe acima, há um método de substituição onActivityResumed de ActivityLifecycleCallbacks
onde todas as instâncias de atividade que estão sendo exibidas na tela podem ser encontradas, basta verificar se Sua Atividade está na Tela ou não pelo método acima.
Registre sua classe de aplicativo em manifest.xml
Para verificar se a atividade do clima está em primeiro ou segundo plano, de acordo com a solução acima, chame o seguinte método nos lugares que você precisa verificar
fonte
Se você quiser saber se alguma atividade do seu aplicativo está visível na tela, pode fazer algo assim:
Basta criar um singleton desta classe e configurá-lo em sua instância do aplicativo como abaixo:
Então você pode usar o método isAnyActivityVisible () de sua instância MyAppActivityCallbacks em qualquer lugar!
fonte
você tentou não chamar finish e colocar "android: noHistory =" true "no manifesto? Isso impedirá que a atividade vá para a pilha.
fonte
Devo dizer que seu fluxo de trabalho não está no padrão Android. No Android, você não precisa da
finish()
sua atividade se quiser abrir outra atividade do Intent. Quanto à conveniência do usuário, o Android permite que o usuário use a tecla 'voltar' para voltar da atividade que você abriu em seu aplicativo.Portanto, deixe o sistema interromper sua atividade e salvar tudo o que for necessário para quando sua atividade for chamada de volta.
fonte
Salve um sinalizador se você for pausado ou retomado. Se você voltou, significa que você está em primeiro plano
fonte
Uma solução possível pode ser definir um sinalizador enquanto mostra a caixa de diálogo do sistema e, em seguida, no método onStop do ciclo de vida da atividade, verificar o sinalizador, se verdadeiro, conclua a atividade.
Por exemplo, se a caixa de diálogo do sistema for acionada por algum clique de botão, o ouvinte onclick pode ser como
e na parada da atividade:
fonte
Por que não usar transmissões para isso? a segunda atividade (a que precisa ser ativada) pode enviar uma transmissão local como esta:
em seguida, escreva um receptor simples na atividade inicial:
e registre seu novo receptor no LocalBroadcastManager para ouvir a transmissão de sua segunda atividade:
NOTE que você pode usar uma constante ou um recurso de string para a string de "identificador de transmissão".
fonte
LocalBroadcastManager
aquiSe você usa
finish()
apenas para evitar que um novo aplicativo inicie na pilha (tarefa) de seu aplicativo, você pode usarIntent.FLAG_ACTIVITY_NEW_TASK
sinalizar, ao iniciar um novo aplicativo e não chamar definish()
jeito nenhum. De acordo com a documentação , este é o sinalizador a ser usado para implementar um comportamento do estilo "lançador".fonte
Use esses métodos dentro de um
Activity
.isDestroyed()
isFinishing()
Um erro comum com
AsyncTask
é capturar uma referência forte ao hostActivity
(ouFragment
):Isso é um problema porque
AsyncTask
pode sobreviver facilmente ao paiActivity
, por exemplo, se uma mudança de configuração acontecer enquanto a tarefa está em execução.A maneira certa de fazer isso é transformar sua tarefa em uma
static
classe, que não capture o pai e mantenha uma referência fraca ao hostActivity
:fonte
Aqui está uma solução usando
Application
classe.Você pode simplesmente usá-lo como segue,
Se você tiver uma referência à atividade necessária ou usando o nome canônico da atividade, poderá descobrir se ela está em primeiro plano ou não. Esta solução pode não ser infalível. Portanto, seus comentários são muito bem-vindos.
fonte
Não sei por que ninguém falou sobre sharedPreferences, para Activity A, definir uma SharedPreference como essa (por exemplo em onPause ()):
Acho que essa é a maneira confiável de rastrear a visibilidade das atividades.
fonte
Seria
Activity.onWindowFocusChanged(boolean hasFocus)
útil aqui? Isso, mais um sinalizador de nível de classe, algo comoisFocused
esseonWindowFocusChanged
conjunto, seria uma maneira fácil de dizer em qualquer ponto de sua atividade se ela está focada ou não. Ao ler os documentos, parece que seria definido corretamente como "falso" em qualquer situação em que a atividade não estivesse diretamente no "primeiro plano" físico, como se uma caixa de diálogo estivesse sendo exibida ou a bandeja de notificação fosse puxada para baixo.Exemplo:
fonte
Se você estiver usando EventBus , ele é um método chamado
hasSubscriberForEvent
que pode ser usado para verificar se umActivity
está focado.fonte
Eu costumava fazer como,
se a atividade não estiver em primeiro plano
retornará nulo. : = P
fonte