Devoluciones de llamadas del servicio remoto de Android
(Tengo un servicio remoto con una interfaz AIDL que se utiliza por varias aplicaciones de cliente.Me gustaría agregar un método asíncrono a la interfaz para las llamadas que llevan algún tiempo, pero necesito la solución para ser seguro , lo que significa que sólo mis aplicaciones Pueden comunicarse con el servicio.Las aplicaciones de cliente están firmadas con la misma firma que la aplicación de servicio.Actualmente las aplicaciones sólo se unen al servicio y llamar a un método de interfaz única para realizar varias operaciones.
Una opción es la difusión de una intención del servicio cuando la operación está completa y utilizando un BroadcastReceiver en la aplicación cliente, pero ( Pregunta # 1 ) se puede hacer de una manera que garantiza que sólo mis aplicaciones pueden recibir la intención? SetPackage () parece hacer esto, pero tengo que apoyar los dispositivos de pan de jengibre, que parece descartar ese enfoque de acuerdo a la respuesta aquí: setPackage para la intención en pan de jengibre
- Android geofencing cuando se mata la aplicación
- Guardar el estado del servicio enlazado antes de que sea eliminado por Android
- Servicio de Android que se reinicia cuando se cancela la aplicación
- ¿Cómo utilizo Android SpeechRecognizer como servicio?
- ¿Es posible tener Android Voice Recognition (como un servicio personalizado) en Google Glass?
Por lo tanto, parece que necesito añadir una segunda interfaz .aidl con la interfaz de devolución de llamada para el servicio a utilizar, implementado por el cliente. He visto ejemplos que usan los oyentes aquí, pero no estoy seguro de cuál es la diferencia entre el cliente que acaba de pasar el segundo objeto de interfaz como un argumento (como se utiliza en el ejemplo IScript / IScriptResult de esta respuesta: llamada de servicio de vuelta a la actividad en Androide
Pregunta # 2 , ¿cuál es el beneficio de usar un oyente aquí frente a un método de devolución de llamada?
- El servicio Android debe ejecutarse siempre (nunca detener o detener)
- Priorizar la programación del reinicio del servicio androide bloqueado
- Android.os.NetworkOnMainThreadException en el inicio del servicio en android
- ¿Cómo se declara un servicio de intención en el manifiesto de Android?
- ¿Cómo puedo eliminar una notificación de primer plano en Android Lollipop?
- REST / JSON / XML-RPC / SOAP
- Android Service Exchange siempre se bloquea
- Android MediaProjectionManager en servicio
Un método / oyente de devolución de llamada es lo correcto. (Como dice CommonsWare, es casi lo mismo). Yo diría que es mucho más sencillo que jugar con BroadcastReceivers, ya que ya estás usando aidl.
Algo como esto:
IAsyncThing.aidl:
package com.my.thingy; import com.my.thingy.IAsyncThingListener; interface IAsyncThing { void doSomething(IAsyncThingListener listener); }
IAsyncThingListener.aidl:
package com.my.thingy; import com.my.thingy.IAsyncThingListener; interface IAsyncThingListener { void onAsyncThingDone(int resultCodeIfYouLike); }
Puede aplicar que solo sus aplicaciones pueden enlazar con el servicio mediante un permiso de nivel de firma en su servicio (consulte la nota sobre 'permisos de servicio' aquí: http://developer.android.com/guide/topics/security/permissions .html ). Específicamente:
- Declare un permiso en
AndroidManifest.xml
su servicio. Asegúrese de que es el nivel designature
. - Agregue ese permiso en su etiqueta de
service
- En todas las demás aplicaciones, use
uses-permission
para usarlo.
Un par de otras cosas a tener en cuenta:
- En el llamador, necesitará subclasificar
IAsyncThingListener.Stub
. Su código de aplicación de llamada ya puede estar subclasificando algo más, por lo que significa que tendría que usar una clase extra (probablemente interna) para recibir la notificación de finalización. Menciono esto sólo porque esta podría ser la respuesta a la pregunta # 2 – que no entiendo completamente. - Si el servicio está potencialmente en diferentes procesos de la persona que llama, cada uno debe registrarse para la notificación de la muerte de la otra utilizando
IBinder.linkToDeath
.