Existe uma maneira nativa do Android de obter uma referência à atividade atualmente em execução de um serviço?
Eu tenho um serviço em execução em segundo plano e gostaria de atualizar minha Atividade atual quando ocorrer um evento (no serviço). Existe uma maneira fácil de fazer isso (como o que sugeri acima)?
android
service
android-activity
George
fonte
fonte
Respostas:
Você não pode ser o proprietário da "Atividade em execução no momento".
Intent
para a atividade - aqui está um projeto de amostra demonstrando esse padrãoPendingIntent
(por exemplo, viacreatePendingResult()
) que o serviço chamabindService()
e faça com que o serviço chame um método de evento nesse objeto de retorno de chamada / ouvinteIntent
para a atividade, com uma prioridade baixaBroadcastReceiver
como backup (para aumentarNotification
se a atividade não estiver na tela) - aqui está uma postagem de blog com mais informações sobre esse padrãofonte
instanceof
verificações ou refatoração das atividades para compartilhar uma superclasse ou interface comum. E se você for refatorar as atividades, é melhor fazê-lo de uma maneira que melhor se adapte à estrutura e cubra mais cenários, como nenhuma de suas atividades sendo ativa. # 4 é provavelmente o menos trabalhoso e mais flexível.Atualização : isso não funciona mais com as atividades de outros aplicativos a partir do Android 5.0
Aqui está uma boa maneira de fazer isso usando o gerenciador de atividades. Você basicamente recebe as tarefas em execução do gerenciador de atividades. Ele sempre retornará a tarefa atualmente ativa primeiro. De lá, você pode obter a topActivity.
Exemplo aqui
Existe uma maneira fácil de obter uma lista de tarefas em execução no serviço ActivityManager. Você pode solicitar um número máximo de tarefas em execução no telefone e, por padrão, a tarefa atualmente ativa é retornada primeiro.
Depois de conseguir, você pode obter um objeto ComponentName solicitando o topActivity da sua lista.
Aqui está um exemplo.
Você precisará da seguinte permissão no seu manifesto:
fonte
As of LOLLIPOP, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak person information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks, and possibly some other tasks such as home that are known to not be sensitive.
Aviso: violação do Google Play
O Google ameaçou remover aplicativos da Play Store se eles usassem serviços de acessibilidade para fins de não acessibilidade. No entanto, isso está sendo reconsiderado .
Use um
AccessibilityService
AccessibilityService
.onAccessibilityEvent
retorno de chamada, verifique o tipo de evento para determinar quando a janela atual é alterada.TYPE_WINDOW_STATE_CHANGED
PackageManager.getActivityInfo()
.Benefícios
GET_TASKS
permissão.Desvantagens
AccessibilityService
, ele não pode pressionar o botão OK se um aplicativo tiver colocado uma sobreposição na tela. Alguns aplicativos que fazem isso são Velis Auto Brightness e Lux. Isso pode ser confuso porque o usuário pode não saber por que não pode pressionar o botão ou como contornar esse problema.AccessibilityService
não conhecerão a atividade atual até a primeira alteração de atividade.Exemplo
Serviço
AndroidManifest.xml
Mesclar isso em seu manifesto:
Informações de serviço
Coloque isso em
res/xml/accessibilityservice.xml
:Habilitando o serviço
Cada usuário do aplicativo precisará ativar explicitamente o
AccessibilityService
para que ele seja usado. Veja esta resposta StackOverflow para saber como fazer isso.Observe que o usuário não poderá pressionar o botão OK ao tentar ativar o serviço de acessibilidade se um aplicativo tiver colocado uma sobreposição na tela, como Velis Auto Brightness ou Lux.
fonte
settingsActivity
deyour.app.ServiceSettingsActivity
, então você deve alterar isso para sua própria atividade de configurações para o seu serviço de acessibilidade. Eu acho que a atividade de configurações é opcional, então removi essa parte da minha resposta para simplificá-la.onAccessibilityEvent
não recebe nenhum evento, mas se eu desabilitar e habilitar novamente o Serviço de Acessibilidade, o serviço é reativado eonAccessibilityEvent
começa a funcionar.Isso pode ser feito por:
Implemente sua própria classe de aplicativo, registre-se no ActivityLifecycleCallbacks - dessa forma, você poderá ver o que está acontecendo com nosso aplicativo. Em cada retorno, o retorno de chamada atribui a atividade visível atual na tela e, na pausa, remove a atribuição. Ele usa o método
registerActivityLifecycleCallbacks()
que foi adicionado na API 14.Na sua chamada de serviço
getApplication()
e transmita-o para o nome da classe do seu aplicativo (neste caso, aplicativo). Do que você pode chamarapp.getActiveActivity()
- isso fornecerá uma Atividade visível atual (ou nula quando nenhuma atividade estiver visível). Você pode obter o nome da Atividade chamandoactiveActivity.getClass().getSimpleName()
fonte
onActivityResumed()
,onActivityPaused()
egetActiveActivity()
para ver como é que Callet, se sempre assim.activity
eactiveActivity
são os mesmos antes de atribuiractiveActivity
comnull
, a fim de erros a evitar, devido à ordem chamando entremeadas de métodos de ciclo de vida de várias atividades.Não consegui encontrar uma solução com a qual nossa equipe ficasse feliz, então criamos a nossa. Usamos
ActivityLifecycleCallbacks
para acompanhar a atividade atual e, em seguida, expô-la através de um serviço:Em seguida, configure seu contêiner de DI para retornar a instância de
MyApplication
paraContextProvider
, por exemplo(Observe que a implementação de
getCurrent()
é omitida no código acima. É apenas uma variável estática definida no construtor do aplicativo)fonte
activity
ecurrentActivity
são os mesmos antes de atribuircurrentActivity
anull
, a fim de evitar erros devido a ordem de chamada entrelaçada dos métodos do ciclo de vida de várias atividades.Usar
ActivityManager
Se você deseja conhecer apenas o aplicativo que contém a atividade atual, pode fazê-lo usando
ActivityManager
. A técnica que você pode usar depende da versão do Android:ActivityManager.getRunningTasks
( exemplo )ActivityManager.getRunningAppProcesses
( exemplo )Benefícios
Desvantagens
ActivityManager.RunningAppProcessInfo.processState
Exemplo (baseado no código do KNaito )
Manifesto
Adicione a
GET_TASKS
permissão paraAndroidManifest.xml
:fonte
Estou usando isso para meus testes. É API> 19, e apenas para atividades do seu aplicativo.
fonte
Use este código para a API 21 ou superior. Isso funciona e fornece melhores resultados em comparação com as outras respostas, ele detecta perfeitamente o processo em primeiro plano.
fonte
Aqui está a minha resposta que funciona muito bem ...
Você deve conseguir a Atividade atual dessa maneira ... Se você estruturar seu aplicativo com algumas Atividades com muitos fragmentos e quiser acompanhar qual é a sua Atividade atual, levaria muito trabalho. Meu senario foi que eu tenho uma atividade com vários fragmentos. Para que eu possa acompanhar a Atividade Atual através do Objeto Aplicativo, que pode armazenar todo o estado atual das variáveis Globais.
Aqui está um caminho. Quando você inicia sua Atividade, você a armazena por Application.setCurrentActivity (getIntent ()); Este aplicativo irá armazená-lo. Na sua classe de serviço, você pode simplesmente fazer como Intent currentIntent = Application.getCurrentActivity (); getApplication (). startActivity (currentIntent);
fonte
Não sei se é uma resposta estúpida, mas resolvi esse problema armazenando um sinalizador em preferências compartilhadas toda vez que inseri oCreate () de qualquer atividade, então usei o valor das preferências shered para descobrir qual é a atividade em primeiro plano.
fonte
Recentemente descobri sobre isso. Com apis como:
targetSdkVersion 26
ActivityManager.getCurrentActivity (contexto)
Espero que isso seja útil.
fonte
getCurrentActivity()
função naActivityManager
classe ( developer.android.com/reference/android/app/ActivityManager ). Engraçado que esta função não existe:ActivityManager.isUserAMonkey()
.