Como verifico se um serviço em segundo plano está em execução?
Quero uma atividade do Android que alterne o estado do serviço - ele permite ativá-lo se estiver desativado e desativado.
android
android-service
Abelha
fonte
fonte
getRunningTasks()
, provavelmente será.Respostas:
Eu tive o mesmo problema há pouco tempo. Como meu serviço era local, acabei simplesmente usando um campo estático na classe de serviço para alternar o estado, conforme descrito por hackbod aqui
EDIT (para o registro):
Aqui está a solução proposta pelo hackbod:
fonte
onDestroy()
não é chamado. Portanto, a variável estática não pode ser atualizada nesse cenário, resultando em comportamento inconsistente.Eu uso o seguinte de dentro de uma atividade:
E eu chamo isso usando:
Isso funciona de maneira confiável, porque se baseia nas informações sobre os serviços em execução fornecidos pelo sistema operacional Android por meio do ActivityManager # getRunningServices .
Todas as abordagens que usam eventos onDestroy ou onSometing, Binders ou variáveis estáticas não funcionarão de maneira confiável porque, como um desenvolvedor que você nunca conhece, quando o Android decide interromper seu processo ou qual dos retornos de chamada mencionados é chamado ou não. Observe a coluna "matável" na tabela de eventos do ciclo de vida na documentação do Android.
fonte
getRunningServices
está obsoleto. Esta resposta precisa de uma atualização para a versão mais recente.Entendi!
Você DEVE solicitar
startService()
que seu serviço seja registrado corretamente e a aprovaçãoBIND_AUTO_CREATE
não será suficiente.E agora a classe ServiceTools:
fonte
Um pequeno complemento é:
Meu objetivo é saber se um serviço está sendo executado sem realmente executá-lo, se não estiver sendo executado.
Chamar bindService ou chamar uma intenção que pode ser capturada pelo serviço não é uma boa ideia, pois iniciará o serviço se não estiver em execução.
Portanto, como o miracle2k sugeriu, o melhor é ter um campo estático na classe de serviço para saber se o serviço foi iniciado ou não.
Para torná-lo ainda mais limpo, sugiro transformar o serviço em um singleton com uma busca muito preguiçosa: ou seja, não há instanciação em toda a instância do singleton por métodos estáticos. O método estático getInstance do seu serviço / singleton apenas retorna a instância do singleton se ele tiver sido criado. Mas, na verdade, ele não inicia nem instancia o próprio singleton. O serviço é iniciado apenas através dos métodos normais de início do serviço.
Seria então mais limpo modificar o padrão de design singleton para renomear o método getInstance confuso para algo como o
isInstanceCreated() : boolean
método.O código será parecido com:
Essa solução é elegante, mas só é relevante se você tiver acesso à classe de serviço e apenas para as classes do aplicativo / pacote do serviço. Se suas aulas estiverem fora do aplicativo / pacote de serviço, você poderá consultar o ActivityManager com as limitações sublinhadas por Pieter-Jan Van Robays.
fonte
Você pode usar isso (ainda não tentei isso, mas espero que funcione):
O método startService retorna um objeto ComponentName se já houver um serviço em execução. Caso contrário, nulo será retornado.
Consulte o resumo público ComponentName startService (serviço de intenção) .
Acho que não é como checar, porque está iniciando o serviço, para que você possa adicionar
stopService(someIntent);
o código.fonte
if(startService(someIntent) != null)
isso verifica isso,IsserviceRunning
mas também reproduz um novo serviço.fonte
Uma extração de documentos do Android :
Pense nesse hack como "pingando" o arquivo
Service
. Como podemos transmitir de forma síncrona, podemos transmitir e obter um resultado de forma síncrona , no thread da interface do usuário.Service
Activity
O vencedor em muitos aplicativos é, obviamente, um campo booleano estático no serviço definido como
true
inService.onCreate()
efalse
inService.onDestroy()
porque é muito mais simples.fonte
Modifiquei levemente uma das soluções apresentadas acima, mas passei a classe em vez de um nome genérico de string, para garantir a comparação de strings que saem do mesmo método
class.getName()
e depois
fonte
Class<? extends Service>
A maneira correta de verificar se um serviço está sendo executado é simplesmente perguntar. Implemente um BroadcastReceiver em seu serviço que responda aos pings de suas atividades. Registre o BroadcastReceiver quando o serviço iniciar e cancele o registro quando o serviço for destruído. Na sua atividade (ou em qualquer componente), envie uma intenção de transmissão local para o serviço e, se responder, você sabe que está em execução. Observe a diferença sutil entre ACTION_PING e ACTION_PONG no código abaixo.
fonte
Eu só quero adicionar uma nota à resposta de @Snicolas. As etapas a seguir podem ser usadas para verificar a interrupção do serviço com / sem chamar
onDestroy()
.onDestroy()
chamado: Vá para Configurações -> Aplicativo -> Serviços em execução -> Selecione e pare seu serviço.onDestroy()
não chamado: Vá para Configurações -> Aplicativo -> Gerenciar aplicativos -> Selecione e "Force Stop" seu aplicativo em que o serviço está sendo executado. No entanto, como seu aplicativo é parado aqui, definitivamente as instâncias de serviço também serão interrompidas.Por fim, gostaria de mencionar que a abordagem mencionada lá usando uma variável estática na classe singleton está funcionando para mim.
fonte
onDestroy
nem sempre é chamado no serviço, portanto isso é inútil!Por exemplo: Basta executar o aplicativo novamente com uma alteração do Eclipse. O aplicativo é encerrado à força usando SIG: 9.
fonte
Antes de tudo, você não deve tentar acessar o serviço usando o ActivityManager. (Discutido aqui )
Os serviços podem ser executados por conta própria, vinculados a uma Atividade ou a ambos. A maneira de fazer check-in de uma Atividade se o seu Serviço está em execução ou não é criando uma interface (que estende o Fichário) em que você declara métodos que tanto a Atividade quanto o Serviço entendem. Você pode fazer isso criando sua própria interface, onde declara, por exemplo, "isServiceRunning ()". Em seguida, você pode vincular sua Atividade ao seu Serviço, executar o método isServiceRunning (), o Serviço verificará por si próprio se está em execução ou não e retornará um booleano à sua Atividade.
Você também pode usar esse método para interromper seu serviço ou interagir com ele de outra maneira.
Usei este tutorial para aprender como implementar esse cenário no meu aplicativo.
fonte
Novamente, outra alternativa que as pessoas podem achar mais limpa se usarem intenções pendentes (por exemplo, com o
AlarmManager
:Onde
CODE
é uma constante que você define em particular na sua classe para identificar as intenções pendentes associadas ao seu serviço.fonte
Abaixo está um hack elegante que cobre todo o
Ifs
. Isto é apenas para serviços locais.E depois, mais tarde:
fonte
Versão Xamarin C #:
fonte
GetSystemService
.Para o caso de uso fornecido aqui, podemos simplesmente usar o
stopService()
valor de retorno do método. Retornatrue
se houver o serviço especificado e for morto. Caso contrário, ele retornafalse
. Portanto, você pode reiniciar o serviço se o resultado forfalse
outro, pois o serviço atual foi interrompido. :) Seria melhor se você desse uma olhada nisso .fonte
Outra abordagem usando o kotlin. Inspirado nas respostas de outros usuários
Como extensão kotlin
Uso
fonte
No kotlin, você pode adicionar variáveis booleanas no objeto complementar e verificar seu valor em qualquer classe que desejar:
Altere seu valor quando o serviço for criado e destruído
fonte
Na sua subclasse de serviço Use um booleano estático para obter o estado do serviço, conforme demonstrado abaixo.
MyService.kt
MainActivity.kt
fonte
Para o kotlin, você pode usar o código abaixo.
fonte
A chamada
fonte
ActivityManager.getRunningServices
está obsoleto desde o Android OPode haver vários serviços com o mesmo nome de classe.
Acabei de criar dois aplicativos. O nome do pacote do primeiro aplicativo é
com.example.mock
. Criei um subpacote chamadolorem
no aplicativo e um serviço chamadoMock2Service
. Portanto, seu nome completo écom.example.mock.lorem.Mock2Service
.Então eu criei o segundo aplicativo e um serviço chamado
Mock2Service
. O nome do pacote do segundo aplicativo écom.example.mock.lorem
. O nome completo do serviço écom.example.mock.lorem.Mock2Service
também é.Aqui está minha saída do logcat.
A melhor idéia é comparar
ComponentName
casos, porqueequals()
deComponentName
compara ambos os nomes de pacotes e nomes de classe. E não pode haver dois aplicativos com o mesmo nome de pacote instalados em um dispositivo.O método equals () de
ComponentName
.Nome do componente
fonte
Por favor, use este código.
fonte
Isso se aplica mais à depuração do Serviço de Intenção, pois eles geram um encadeamento, mas também podem funcionar para serviços regulares. Encontrei este tópico graças ao Binging
No meu caso, brinquei com o depurador e encontrei a visualização de threads. Parece o ícone do marcador no MS Word. De qualquer forma, você não precisa estar no modo de depurador para usá-lo. Clique no processo e clique nesse botão. Quaisquer Serviços de Intenção aparecerão enquanto estiverem em execução, pelo menos no emulador.
fonte
Se o serviço pertencer a outro processo ou APK, use a solução com base no ActivityManager.
Se você tiver acesso à sua origem, basta usar a solução com base em um campo estático. Mas, em vez disso, usando um booleano, sugiro usar um objeto Date. Enquanto o serviço estiver em execução, basta atualizar seu valor para 'agora' e, quando terminar, defina-o como nulo. A partir da atividade, você pode verificar se é nulo ou se a data é muito antiga, o que significa que não está em execução.
Você também pode enviar uma notificação de transmissão do seu serviço, indicando que está sendo exibida mais informações, como progresso.
fonte
Dentro de TheServiceClass, defina:
Em seguida, em onStartCommand (...)
Em seguida, ligue
if(TheServiceClass.serviceRunning == true)
de qualquer classe.fonte
stopService
. Pelo menos para serviços Intent.onDestroy()
será chamado imediatamente, masonHandleIntent()
ainda estará funcionandouso simples vincular com não criar auto- veja ps. e atualizar ...exemplo:
por que não usar? getRunningServices ()
Nota: este método destina-se apenas à depuração ou implementação de interfaces de usuário do tipo gerenciamento de serviços.
ps. A documentação do Android é enganosa. Abri um problema no Google Tracker para eliminar qualquer dúvida:
https://issuetracker.google.com/issues/68908332
como podemos ver, o serviço de ligação realmente chama uma transação através do fichário ActivityManager através de fichários de cache de serviço - identifico qual serviço é responsável pela ligação, mas como podemos ver o resultado da ligação é:
a transação é feita através do fichário:
Próximo:
isso é definido no ActivityThread via:
isso é chamado no ActivityManagerService no método:
então:
mas não há "atividade" apenas pacote de janela e alarme ..
então precisamos voltar a ligar para:
isso faz a chamada através de:
o que leva a :
e este é o método nativo ....
agora não tenho tempo para cavar c, até dissecar a chamada de descanso e suspender minha resposta.
mas a melhor maneira de verificar se o serviço está em execução é criar a ligação (se a ligação não foi criada, o serviço não existe) - e consultar o serviço sobre seu estado através da ligação (usando sinalizador interno armazenado no estado).
atualização 23.06.2018
eu achei aqueles interessantes:
em resumo :)
"Forneça um fichário para um serviço já vinculado. Este método é síncrono e não iniciará o serviço de destino se ele não estiver presente."
public IBinder peekService (serviço Intent, String resolvedType, String chamandoPackage) lança RemoteException;
fonte
Minha conversão kotlin das
ActivityManager::getRunningServices
respostas baseadas. Coloque essa função em uma atividade -fonte
É possível usar essas opções nas opções do Desenvolvedor Android para ver se seu serviço ainda está sendo executado em segundo plano.
fonte
Calma galera ... :)
Eu acho que a solução mais adequada é manter um par de valores-chave
SharedPreferences
sobre se o serviço está sendo executado ou não.A lógica é muito direta; em qualquer posição desejada em sua classe de serviço; coloque um valor booleano que atuará como um sinalizador para você sobre se o serviço está sendo executado ou não. Em seguida, leia esse valor onde quiser no seu aplicativo.
Um código de exemplo que estou usando no meu aplicativo está abaixo:
Na minha classe de serviço (um serviço para fluxo de áudio), executo o código a seguir quando o serviço está ativo;
Em qualquer atividade do meu aplicativo, estou verificando o status do serviço com a ajuda do código a seguir;
Sem permissões especiais, sem loops ... Maneira fácil, solução limpa :)
Se você precisar de informações adicionais, consulte o link
Espero que isto ajude.
fonte
onDestroy
nem sempre é chamado quando o serviço é interrompido . Por exemplo, vi meus serviços serem mortos em situações de pouca memória semonDestroy
serem chamados.