Estou escrevendo meu primeiro aplicativo Android e tentando entender a comunicação entre serviços e atividades. Eu tenho um serviço que será executado em segundo plano e fará alguns logs baseados em tempo e gps. Terei uma Atividade que será usada para iniciar e parar o Serviço.
Então, primeiro, preciso descobrir se o Serviço está sendo executado quando a Atividade é iniciada. Existem algumas outras perguntas aqui sobre isso, então acho que posso descobrir isso (mas fique à vontade para oferecer conselhos).
Meu verdadeiro problema: se a Atividade estiver em execução e o Serviço for iniciado, preciso de uma maneira para o Serviço enviar mensagens para a Atividade. Sequências simples e números inteiros neste momento - mensagens de status principalmente. As mensagens não acontecerão regularmente, então não acho que pesquisar o serviço seja um bom caminho a percorrer, se houver outro caminho. Eu só quero essa comunicação quando a Atividade tiver sido iniciada pelo usuário - não quero iniciar a Atividade pelo Serviço. Em outras palavras, se você iniciar a Atividade e o Serviço estiver em execução, verá algumas mensagens de status na IU da Atividade quando algo interessante acontecer. Se você não iniciar a atividade, não verá essas mensagens (elas não são tão interessantes).
Parece que eu devo determinar se o Serviço está em execução e, se estiver, adicione a Atividade como ouvinte. Em seguida, remova a Atividade como ouvinte quando a Atividade pausar ou parar. Isso é realmente possível? A única maneira de descobrir isso é fazer com que a Activity implemente o Parcelable e crie um arquivo AIDL para que eu possa transmiti-lo pela interface remota do Serviço. Isso parece um exagero, e eu não tenho idéia de como a Atividade deve implementar writeToParcel () / readFromParcel ().
Existe uma maneira mais fácil ou melhor? Obrigado por qualquer ajuda.
EDITAR:
Para quem estiver interessado nisso posteriormente, há um código de exemplo do Google para lidar com isso via AIDL no diretório de exemplos: /apis/app/RemoteService.java
fonte
busy-wait
a atividade? Você pode explicar por favor?Activity.onCreate()
?Intents
enviando dados através deParcellable
mensagens entre eles?O solicitante provavelmente já passou disso, mas no caso de alguém procurar por isso ...
Há outra maneira de lidar com isso, que eu acho que pode ser a mais simples.
Adicione um
BroadcastReceiver
a sua atividade. Registre-o para receber alguma intenção personalizadaonResume
e cancelar o registroonPause
. Em seguida, envie essa intenção do seu serviço quando desejar enviar suas atualizações de status ou o que você tem.Certifique-se de que você não ficaria infeliz se algum outro aplicativo o escutasse
Intent
(alguém poderia fazer algo malicioso?), Mas, além disso, você deve ficar bem.Exemplo de código foi solicitado:
No meu serviço, eu tenho o seguinte:
(
RefreshTask.REFRESH_DATA_INTENT
é apenas uma string constante.)Na minha atividade de escuta, defino meu
BroadcastReceiver
:Declaro meu destinatário no topo da classe:
Eu substituo
onResume
para adicionar isso:E substituo
onPause
para adicionar:Agora, minha atividade está ouvindo meu serviço dizer "Ei, atualize-se". Eu poderia passar dados nas
Intent
tabelas do banco de dados em vez de atualizar e depois voltar para encontrar as alterações na minha atividade, mas como eu quero que as alterações persistam de qualquer maneira, faz sentido passar os dados via DB.fonte
Broadcasts
são fantásticos e, além disso, se você não quer que sua transmissão para ir além do seu próprio processo, em seguida, considere o uso de umLocalBroadcast
: developer.android.com/reference/android/support/v4/content/...Use
LocalBroadcastManager
para registrar um receptor e ouvir uma transmissão enviada pelo serviço local dentro do seu aplicativo. A referência é aqui:http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
fonte
LocalBroadcastManager
agora está obsoleto em favor deLiveData
ou outras ferramentas de padrão de observador: developer.android.com/reference/androidx/localbroadcastmanager/…Estou surpreso que ninguém tenha dado referência à biblioteca de ônibus do evento Otto
http://square.github.io/otto/
Eu tenho usado isso em meus aplicativos Android e funciona perfeitamente.
fonte
android:process=":my_service"
eles não são capazes de se comunicar.Usar um Messenger é outra maneira simples de se comunicar entre um Serviço e uma Atividade.
Na atividade, crie um manipulador com um Messenger correspondente. Isso manipulará as mensagens do seu serviço.
O Messenger pode ser passado para o serviço anexando-o a uma Mensagem:
Um exemplo completo pode ser encontrado nas demos da API: MessengerService e MessengerServiceActivity . Consulte o exemplo completo de como o MyService funciona.
fonte
myService.send(message);
deve ser omessenger.send(message);
contrário.O outro método que não é mencionado nos outros comentários é vincular ao serviço da atividade usando bindService () e obter uma instância do serviço no retorno de chamada ServiceConnection. Conforme descrito aqui http://developer.android.com/guide/components/bound-services.html
fonte
Você também pode usar
LiveData
isso funciona como umEventBus
.Em seguida, adicione um observador do seu
Activity
.Você pode ler mais neste blog.
fonte
Outra maneira poderia ser usar observadores com uma classe de modelo falsa por meio da atividade e do próprio serviço, implementando uma variação de padrão MVC. Não sei se é a melhor maneira de conseguir isso, mas é a maneira que funcionou para mim. Se você precisar de algum exemplo, peça e eu publicarei algo.
fonte
Meu método:
Classe para gerenciar o envio e recebimento de mensagens de / para serviço / atividade:
No exemplo de atividade:
Exemplo no serviço:
Envie uma mensagem da Atividade / Serviço:
Como isso funciona:
na atividade que você inicia ou liga o serviço. Os métodos de serviço "OnBind" retornam o fichário ao MessageManager, na atividade por meio da implementação de métodos de interface "Conexão de serviço" "OnServiceConnected" você obtém esse IBinder e inicia o MessageManager usando-o. Após a Atividade iniciar o MessageManager, o MessageHandler envia e Handshake para o serviço, para que ele possa definir o remetente "MessageHandler" (o "Messenger particular mMsgSender;" no MessageManager). Fazendo isso, o serviço sabe para quem envia suas mensagens.
Você também pode implementá-lo usando um "remetente" Lista / Fila de Messenger no MessageManager para poder enviar várias mensagens para diferentes Atividades / Serviços ou usar um "receptor" Lista / Fila de Messenger no MessageManager para receber vários mensagem de diferentes Atividades / Serviços.
Na instância "MessageManager", você tem uma lista de todas as mensagens recebidas.
Como você pode ver a conexão entre o "Activity's Messenger" e o "Service Messenger" usando esta instância "MessageManager" é automática, isso é feito pelo método "OnServiceConnected" e pelo uso do "Handshake".
Espero que isso seja útil para você :) Muito obrigado! Tchau: D
fonte
Para acompanhar a resposta do @MrSnowflake com um exemplo de código. Esta é a XABBER agora open source
Application
classe . AApplication
turma está centralizando e coordenandoListeners
e ManagerInterfaces e muito mais. Gerentes de todos os tipos são carregados dinamicamente.Activity´s
iniciado no Xabber relatará em que tipoListener
eles são. E quando umService
início é reportado àApplication
turma como iniciado. Agora, para enviar uma mensagem aActivity
tudo o que você precisa fazer é tornar-Activity
se umlistener
de que tipo você precisa. NoOnStart()
OnPause()
registro / unreg. OService
aluno pode pedir àApplication
classe apenas o quelistener
precisa falar e, se estiver lá, a Atividade está pronta para receber.Passando pela
Application
aula, você verá que há muito mais acontecendo então isso.fonte
A ligação é outra maneira de se comunicar
Implemente a interface na atividade
Forneça a implementação para o método
Vincular a atividade ao serviço
Registre e cancele o registro do retorno de chamada quando o Serviço for vinculado e desvinculado da Atividade.
Inicializar retorno de chamada
Invoque o método de retorno de chamada sempre que necessário
fonte
serviceConnection
está fora deonCreate
. Por favor edite-o.Como mencionado por Madhur, você pode usar um ônibus para comunicação.
No caso de usar um barramento, você tem algumas opções:
Otto event Bus library (descontinuado em favor do RxJava)
http://square.github.io/otto/
EventBus do robô verde
http://greenrobot.org/eventbus/
NYBus (RxBus, implementado usando RxJava. Muito semelhante ao EventBus)
https://github.com/MindorksOpenSource/NYBus
fonte
Além do LocalBroadcastManager, o Event Bus e o Messenger já responderam nesta pergunta, podemos usar a intenção pendente para se comunicar pelo serviço.
Como mencionado aqui no meu blog
fonte