Estoy escribiendo mi primera aplicación de Android y estoy tratando de entender la comunicación entre servicios y actividades. Tengo un Servicio que se ejecutará en segundo plano y que hará algunos gps y registros basados en el tiempo. Tendré una Actividad que se utilizará para iniciar y detener el Servicio.
Primero, necesito poder determinar si el Servicio se está ejecutando cuando se inicia la Actividad. Hay algunas otras preguntas aquí sobre eso, así que creo que puedo resolverlo (pero siéntase libre de ofrecer consejos).
Mi verdadero problema: si la Actividad se está ejecutando y se inicia el Servicio, necesito una forma para que el Servicio envíe mensajes a la Actividad. Cadenas simples y enteros en este punto: mensajes de estado en su mayoría. Los mensajes no sucederán regularmente, por lo que no creo que sondear el servicio sea una buena opción si hay otra. Solo quiero esta comunicación cuando el usuario ha iniciado la Actividad; no quiero iniciar la Actividad desde el Servicio. En otras palabras, si inicia la Actividad y el Servicio se está ejecutando, verá algunos mensajes de estado en la IU de la Actividad cuando ocurra algo interesante. Si no inicia la Actividad, no verá estos mensajes (no son tan interesantes).
Parece que debería poder determinar si el Servicio se está ejecutando y, de ser así, agregar la Actividad como escucha. Luego, elimine la Actividad como oyente cuando la Actividad se detenga o se detenga. ¿Es eso realmente posible? La única forma en que puedo resolverlo es hacer que la Actividad implemente Parcelable y cree un archivo AIDL para poder pasarlo a través de la interfaz remota del Servicio. Sin embargo, parece una exageración, y no tengo idea de cómo la Actividad debe implementar writeToParcel () / readFromParcel ().
¿Hay una manera más fácil o mejor? Gracias por cualquier ayuda.
EDITAR:
Para cualquiera que esté interesado en esto más adelante, hay un código de muestra de Google para manejar esto a través de AIDL en el directorio de muestras: /apis/app/RemoteService.java
fuente
busy-wait
la actividad? ¿Puedes explicar por favor?Activity.onCreate()
?Intents
enviando datos a través deParcellable
mensajes entre ellos?El autor de la pregunta probablemente ya pasó hace mucho tiempo, pero en caso de que alguien más busque esto ...
Hay otra forma de manejar esto, que creo que podría ser la más simple.
Agrega un
BroadcastReceiver
a tu actividad. Regístrese para recibir alguna intención personalizadaonResume
y anule el registroonPause
. Luego envíe esa intención desde su servicio cuando desee enviar sus actualizaciones de estado o lo que tenga.Asegúrate de no ser infeliz si alguna otra aplicación te escuchara
Intent
(¿alguien podría hacer algo malicioso?), Pero más allá de eso, deberías estar bien.Se solicitó una muestra de código:
En mi servicio, tengo esto:
(
RefreshTask.REFRESH_DATA_INTENT
es solo una cadena constante).En mi actividad auditiva, defino mi
BroadcastReceiver
:Declaro mi receptor en la parte superior de la clase:
Anulo
onResume
para agregar esto:Y anulo
onPause
para agregar:Ahora mi actividad está escuchando mi servicio para decir "Hey, ve y actualízate". Podría pasar datos en
Intent
lugar de actualizar las tablas de la base de datos y luego regresar para encontrar los cambios dentro de mi actividad, pero dado que quiero que los cambios persistan de todos modos, tiene sentido pasar los datos a través de DB.fuente
Broadcasts
son fantásticos y, además, si no desea que su transmisión vaya más allá de su propio proceso, considere usar unLocalBroadcast
: developer.android.com/reference/android/support/v4/content/…Use
LocalBroadcastManager
para registrar un receptor para escuchar una transmisión enviada desde el servicio local dentro de su aplicación, la referencia va aquí:http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
fuente
LocalBroadcastManager
ahora está en desuso a favorLiveData
u otras herramientas de patrones de observación: developer.android.com/reference/androidx/localbroadcastmanager/…Me sorprende que nadie haya hecho referencia a la biblioteca de autobuses de eventos de Otto.
http://square.github.io/otto/
He estado usando esto en mis aplicaciones de Android y funciona a la perfección.
fuente
android:process=":my_service"
que no pueden comunicarse.)Usar un Messenger es otra forma simple de comunicarse entre un Servicio y una Actividad.
En la actividad, cree un controlador con un Messenger correspondiente. Esto manejará los mensajes de su Servicio.
El Messenger se puede pasar al servicio adjuntándolo a un Mensaje:
Puede encontrar un ejemplo completo en las demostraciones de API: MessengerService y MessengerServiceActivity . Consulte el ejemplo completo de cómo funciona MyService.
fuente
myService.send(message);
debería sermessenger.send(message);
en su lugar.El otro método que no se menciona en los otros comentarios es enlazar al servicio desde la actividad usando bindService () y obtener una instancia del servicio en la devolución de llamada de ServiceConnection. Como se describe aquí http://developer.android.com/guide/components/bound-services.html
fuente
También puede usar
LiveData
que funciona como unEventBus
.Luego agregue un observador de su
Activity
.Puedes leer más de este blog.
fuente
Otra forma podría ser utilizar observadores con una clase de modelo falso a través de la actividad y el servicio en sí, implementando una variación de patrón MVC. No sé si es la mejor manera de lograr esto, pero es la forma en que funcionó para mí. Si necesita algún ejemplo, solicítelo y publicaré algo.
fuente
Mi metodo:
Clase para gestionar enviar y recibir mensajes de / al servicio / actividad:
En el ejemplo de actividad:
En servicio Ejemplo:
Enviar un mensaje de Actividad / Servicio:
Cómo funciona esto:
en la actividad que inicia o vincula el servicio. Los métodos de servicio "OnBind" devuelven el Binder a su MessageManager, y en la Actividad a través de la implementación de métodos de interfaz de "Conexión de servicio" "OnServiceConnected" obtiene este IBinder e inicia su MessageManager usándolo. Después de que la Actividad haya iniciado su MessageManager, MessageHandler envía y Handshake al servicio para que pueda configurar su remitente "MessageHandler" (el "Messenger mMsgSender privado" en MessageManager). Al hacer esto, el servicio sabe a quién envía sus mensajes.
También puede implementar esto usando un "remitente" de Lista / Cola de Messenger en el Administrador de mensajes para que pueda enviar múltiples mensajes a diferentes Actividades / Servicios o puede usar un "receptor" de Lista / Cola de Mensajero en el Administrador de mensajes para que pueda recibir múltiples mensaje de diferentes actividades / servicios.
En la instancia "MessageManager" tiene una lista de todos los mensajes recibidos.
Como puede ver, la conexión entre "Activity Messenger" y "Service Messenger" utilizando esta instancia de "MessageManager" es automática, se realiza mediante el método "OnServiceConnected" y mediante el uso del "Handshake".
Espero que esto sea útil para ti :) ¡Muchas gracias! Adiós: D
fuente
Para dar seguimiento a @MrSnowflake, responda con un ejemplo de código. Esta es la XABBER ahora de código abierto
Application
de clase . LaApplication
clase se está centralizando y coordinandoListeners
y ManagerInterfaces y más. Los gerentes de todo tipo se cargan dinámicamente.Activity´s
iniciado en el Xabber informará en qué tipo deListener
son. Y cuandoService
comienza, informa a laApplication
clase como iniciada. Ahora, para enviar un mensaje aActivity
todo lo que tiene que hacer es convertirseActivity
en unolistener
de los tipos que necesita. En elOnStart()
OnPause()
registro / unreg. LaService
puede pedir a laApplication
clase para sólo quelistener
se necesita hablar con y si está allí entonces la actividad está listo para recibir.Al pasar por la
Application
clase verás que hay mucho más en juego que esto.fuente
El enlace es otra forma de comunicarse
Implemente la interfaz en la actividad
Proporcionar la implementación del método.
Vincula la actividad al servicio
Registre y anule el registro de devolución de llamada cuando el Servicio se vincula y se desvincula con Activity.
Inicializar devolución de llamada
Invoque el método de devolución de llamada cuando sea necesario
fuente
serviceConnection
está fuera deonCreate
. Por favor edítelo.Como lo mencionó Madhur, puede usar un autobús para comunicarse.
En caso de utilizar un autobús, tiene algunas opciones:
Otto event Bus library (en desuso a favor de RxJava)
http://square.github.io/otto/
EventBus de Green Robot
http://greenrobot.org/eventbus/
NYBus (RxBus, implementado usando RxJava. Muy similar al EventBus)
https://github.com/MindorksOpenSource/NYBus
fuente
Además de LocalBroadcastManager, Event Bus y Messenger ya respondieron en esta pregunta, podemos usar la intención pendiente para comunicarnos desde el servicio.
Como se menciona aquí en mi blog
fuente