Capitulo 9 Del Gran Libro de Android
-
Upload
adesmiro-zelada-escobedo -
Category
Documents
-
view
212 -
download
0
Transcript of Capitulo 9 Del Gran Libro de Android
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
1/19
263
CAPITULO 9. Servicios y
notificaciones
Cuando necesites que parte de una aplicacin se ejecute en segundo pimo, debajo de otras
actividades, y que adems no precise de ningn lipo de interaccin con el usuario, la opcin ms
adecuada es crear un servicio Un servicio puede estar en ejecucin indefinidamente, o podemos
controlarlo desde una actividad. A lo largo de este capitulo aprenderemos las facilidades
proporcionadas por Android para la creacin de servicios.
Por otra parte, las notificaciones de la barra de estado constituyen un mecanismo de comunicacin
vital en Android. Permite a las aplicaciones que corren en un segundo plano adviertan al usuario sobre
alertas, avisos o cualquier tipo de informacin. Las notificaciones se representan como pequeos
conos en la barra superior de la pantalla y se utilizan habitualmente para indicar la llegada de un
mensaje, una cita de calendario, una llamada perdida o cualquier otra incidencia de inters al usuario.
Se trata de una comunicacin que no requiere una interaccin inmediata del usuario; este puede estar
utilizando otra aplicacin sin ser interrumpido o puede no estar utilizando el telfono en ese momento
Este hecho hace de las notificaciones un mecanismo de comunicacin ideal para un servicio. Por lo
tanto, este capitulo parece el sitio ideal para describir cmo podemos crear nuestras propias
notificaciones y utilizarlas desde nuestras aplicaciones.
9.1. Introduccin a los servicios en Android
Los diferentes ejemplos mostrados hasta el momento construan uni aplicacin concatenando una
serie de actividades, cada una de las cuales permilia construir un elemento de interaccin con el
usuario. En otros casos, ser necesario aadir un nuevo elemento a tu aplicacin, pero que no requiera
una interaccin directa con el usuario. Este es el momento de crear un servicio.
En Android los servicios tiene una doble funcin:
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
2/19
264
La primera funcin permite indicar al sistema que el elemento que estamos creando ha de ejecutarse en
segundo plano, normalmente durante un largo perodo de tiempo. Este tipo de servicios son iniciados
mediante el mtodo startservice (), que ndica al sistema que lo ejecute de forma indefinida hasta que
alguien le indique lo contrario.
La segunda funcin permite que nuestra aplicacin se comunique con otras aplicaciones, para lo
cual ofreceremos ciertas funciones que podrn ser llamada desde otras aplicaciones. Este tipo de
servicios son iniciados mediante el mtodo bindServce O, que permite establecer una conexin con
el servicio e invocar alguno de los mtodos que son ofrecidos.
Cada vez que un servicio es creado por alguna de las razones anteriores, el sistema instancia el servicio
y llama al mtodo onCreate (). Corresponde al servicio implementar el comportamiento adecuado,
habitualmente crear un hilo de ejecucin (thread) secundario donde se realizar el trabajo.
Un servicio en s es algo muy simple, en este captulo se vern ejemplos de servicios locales
escritos en muy pocas lineas. No obstante, tambin pueden complicarse, como veremos al final del
capitulo cuando tratemos de invocar ser/icios remotos por medio de una interfaz AIDL.
Un servicio, como el resto de componentes de una aplicacin, se ejecuta en el
hilo principal del proceso de la aplicacin. Por lo tanto, si el servicio necesita un
uso intensivo de CPU o puede quedar bloqueado en ciertas operaciones, como
uso de redes, debes crear su propio hilo. Tambin puedes utilizar la clase
' para lanzar un servicio en su propio hilo.
9.1.1. Ciclo de vida de un servicio.
1
6 importante que recuerdes que un servicio tiene un ciclo de vida diferente a una actividad. Acontinuacin, podemos ver un grfico que ilustra el ciclo de vida de los servicios:
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
3/19
265
Figura 6.Ciclo de vida de los servicios
Como acabamos de explicar existen dos tipos de servicio:; segn como hayan
Sido creados. Las funciones de estos servicios son diferentes y poi lo i., tambin su ciclo de vida.
Si el servicio es iniciado mediante start sev ice() el sistema comenzara crendolo y llamando a
su mtodo onCreat e() A continuacin llamara asu mtodo onStart Command (In ten t incent., intflags, in t s ta rt Id) con argumentos proporcionados por el cliente. El servicio continuar en
ejecucin hasta que sea invocado el mtodo stopService() o stopSelf().
Nota:Si se producen varias llamadas a sta r t Serv i ce ( )no Supondrla creacin de varios
servicios, aunque si que se realizarn mltiples ll amadas a
onStartComand(). No importa cuntas veces els e r v i c i o haya sido creado, parara con la
primera invocacin de stopServ ic e()o stopSe lf () Sin embargo, podemos utilizar el mtodo
stopSelf (i nt start Id para asegurarnos que elservicio no parar hasta que todas las llamadas
hayan sido procesadas
Cuando se inicia un servicio para realizar alguna tarea en segundo plano, el proceso donde seejecuta podra ser eliminado ante una situacin de baja
En versiones del API inferiores a 2.0 el mtodo llamado ser versiones recientes se mantiene
por razones de compatibilidad.
Servico creado por startService()
onCreate
onstart()/onStartComand()
Servico creado por bindService()
onCreate
onBind()
Corrriendo Conectado
Desconecta
DestruirDestruido
onDestroy()
onDestroy()
onUnBind() onRebind()
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
4/19
266
memoria. Podemos configurar la forma en que el sistema reaccionar ante estacircunstancia segn el valor que devolvamos en onStartCommandO, Existen dos modosprincipales: devolveremos start_STICKY si queremos que el sistema'trate de crear denuevo el servicio cuando disponga de memoria suficiente. Devolveremosstart_not_STICKTV si queremos que el servicio sea creado de nuevo solo cuando llegueuna nueva solicitud de creacin.
Teniendo en cuenta que los servicios pueden estar largo tiempo en ejecucin, el ciclo devida del proceso que contiene nuestro servicio es un asunto de gran importancia. Convieneaclarar que en situaciones donde el sistema necesite memoria conservar un servicio siempreser menos prioritario que la actividad visible en pantalla, aunque ms prioritario que otrasactividades en segundo plano. Dado que el nUmero de actividades visibles es siemprereducido, un servicio solo ser eliminado en situaciones de extrema necesidad de memoria.
Por otra parte, si un cliente visible est conectado a un servicio, el servicio tambin serconsiderado como visible, siendo tan prioritario como el cliente. En el caso de un procesoque contenga varios componentes, por ejemplo una actividad y un servicio, su prioridad seobtiene como el mximo de sus componentes.
Podemos tambin utilizar bindServicedntent servicio, ServiceConnectioiicbriexion, int flags) para obtener una conexin persistente con un servicio. Si dichoservicio no est en ejecucin, ser creado {siempre que el flag sirvo auto crate estactivo), llamndose al mtodo onCreatet). pero no se llamar a onStartCommandO . Ensu lugar se llamar al mtodo onBindUntent intento) que ha de devolver al cliente unobjeto IBindes: a travs del cual se podr establecer una comunicacin entre cliente y
servicio. Esta comunicacin se establece por medio de una nterfaz escrita en AIDL, quepermite el inlercambio de objetos entre aplicaciones que corren en procesos separados. Elservicio permanecer en ejecucin tanto tiempo como la conexin est establecida,independientemente de que se mantenga o no la referencia al objeto iBinder.
Tambin es posible disear un servicio que pueda ser arrancado de ambas formas(startservice t! y bindService ()). Este servicio permanecer activo se fia sido creado desde laaplicacin que lo contiene o si recibe conexiones desde otras aplicaciones.
Todo servicio terminar llamando al mtodo onDeatroyO cuando vaya a terminar deforma efectiva.
9.1.2. Permisos
Podemos conseguir que el acceso global a un servicio declararlo en la etiquetaservice* de AndroidManifeat.xml. Tambin podemos definir un permiso para restringirsu acceso. En este caso, las aplicaciones han de declarar este permiso, con elcorrespondiente uses-permission.-. en su propio manifiesto.Podemos definir un permiso para arrancar, parrar o conectarse a un servicio De formaadicional, podemos restringir el acceso a funciones especificas de las
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
5/19
267
ofertadas por un servicio. Para este propsito,
podemos llamar al principio de nuestra funcin a checkCaliingPermission string! paraverificar si el cliente dispone de un permiso en concreto.
Para ms informacin sobre permisos se recomienda la lectura del CAPTULO6.
9.2. Un servicio para ejecucin en segundo plano.
Dentro de los dos usos de un servicio, el ms frecuente es permitirnos ejecutar parte denuestra aplicacin en segundo plano. En una situacin tipica todos los componentes de unaaplicacin se ejecutan en un mismo proceso, a menos que se indique de forma explcita locontrario.
Cuando nos encontramos en esta situacin, asumiendo que todos los componentes deuna aplicacin corren en el mismo proceso, se comunica de forma significativa lacomunicacin entre los diferentes componentes. Los cliente;, pueden simplemente coger eliBinder recibido del servicio y realizar un cambio do tipo (type cast) a una clase concretapublicada por el servicio.
Otro asunto ser comunicarnos con servicios que corren en procesos diferentes al nuestro.La comunicacin entre procesos ser estudiada al final del capitulo.
Veamos un ejemplo de servicio que corre en el mismo proceso de la aplicacin que loutiliza. El servicio ser creado con la finalidad de reproducir una msica de fondo y podr serarrancado y detenido desde la actividad principal. Crea un nuevo proyecto con los siguientesdatos:
Projct rame: ServicioMusica
Bu i Id Target: Android 2.0Application ame: Servicio de Msica
Package name: org.example.aerviciomueica Crate
Activity: ActividadPrincipal
Min SDK Versin: 5
Reemplaza el cdigo del layoutmain.xml por:
eliinearLayout
xmlns : android"http: / / schemas. andr ici. caro/ apk/ res /andri o'"android:orientation="vertical "android:layout_width="fill_parent"android : 1 a y out_height = " f ill parent ">
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
6/19
268
android: layout_height= "C ON T E N T "
android: text- "Servicio D E R E P R O D U C I O N ' D E M S IC A" /
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
7/19
269
Button detener = (Button) findViewByld(R.id.boton_detener) ,;
detener.setOnClickListener(new OnClickListener() ( public void onClick(View
view)' (
stopService(new Intent(ActividadPrincipal.this, ServicioMusica.class));
}};
}}
Crea la nueva clase, ServicioMusica, con el siguiente cdigo:
@ override
public void onCreate0 j
Toast. .make(this, "Servicio creado" ,Toast . LENGTH_SHORT) . show ( )
reproductor . MediaPlayer . create ( this . H. raw . A U D IO ) ;@Override
public int onStartCoomand(Intent intento, int Hag::, int idArranque){
Toast.makeText(this,"Servicio arrancado " < idArranque,Toast . LENGTH_SHORT) . show ();
reproductor.start () ; return
START_STICKY;
}
@Override
public void onDest roy ) |
T o a s t . EAKE TE X T (this. "Servicio detenido".Toast. Length_SHORT).show();
reproductor.stop ();
}
@Override
public IBinder onBindtIntent intent return null;
}}
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
8/19
270
Edita e l f i chero androidMani fes t .xml y aade la s iguiente l inea dentro de
la et iqueta
Crea una nueva carpeta con nombro raw dentro de la carpeta res.Arrastra
a su inter ior e l f i chero audi o. mp3
Ejecuta la apl i cac in y comprueba su func ionamiento. Ver i f i ca q ue
aunque pulses var ias veces e l botn "Arrancar servic io" , es te no vuelve a
crearse , pero s i que vuelve a l lamarse a l mtodo onStartCommandt).
Adem s , con s olo una vez q ue puls es en " D et ene r s ervi c io" es t e pa ra r .
Hay que tener en cuenta un problema de compat ib i l idad. El mtodo
onStartComand0 aparece a part i r de l n ive l de API 5 , en sust i tuc in de
onStart()! . S i t rabajas con una vers in in fer ior a la 2 .0 , reemplaza es te
mtodo por e l cdigo s iguiente:
@override
Public void onStart(Intent intent, int startId){
Toast.makeText(this,Servicio arrancado + startId,
Toast .LENGTH_SHORT). Show();
Reproductor.start();
}
Si lo comparas con onStartConimand(), este l t imo t iene un parmetro
ms y permite devolver un resul tado. Vemoslos con ms deta l le , dado
que sus parmetros pueden ser ut i l i zados para obtener in formacinva l iosa:
public int onStartComand (Intent intent, int lags, int idArrantjue)
l lamandocada vez que un c l iente in ic ia l i za un servic io mediante e l
mtodo Los parmetros se deta l lan a cont inuac in:
intento Un objeto intent que se indic en la l lamada
atartService(Intent;)
f lags Informacin sobre como comienza la so l i c i tud Puede ser 0 ,
STARTflagREDELIVERY O START FIAG RETRY. Un VA L OR dis t intode 0 se ut i l i za para re in ic iar un servic io tras detec tar
a lgn problema
idArranque Un entero nico representando la so l i c i tud de arranqueespec f i ca Usar es te mismo es tero en e l mtodo s topSel fResul t ( int
idArranque) ;
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
9/19
271
r e t o r na D e s c r i be c mo ha de c ompor t a r s e e l s i s t e ma c ua ndo e l p r oc e s o de l
s e r v i c i o s e a ma t a do una ve z que e l s e r v i c i o ya s e ha i n i c i a l i z a do . E s t o pue de
ocur r i r en s i tuac iones de ba ja memor ia . Los s igu ien te s va lore s e s tnpe rmi t i dos :
start sticky: C ua ndo s e a pos i b l e e l s i s t e ma t r a t a r de r e c r e a r e l s e r v i c i o , s e
realizar una llamada a onStartCommand () pero con el parmetro intento igual a null.
E s t o t i e ne s e n t i do c ua ndo e l s e r v i c i o pue de a r r a nc a r s i n i n f o r ma c i n a d i c i ona l ,
c omo po r e j e mpl o , e l s e r v i c i o mos t r a do pa r a l a r e p r oduc c i n de ms i c a de
fondo. start_ n o t _sticky: E l s i s t e ma no t r a t a r de vo l ve r a c r e a r e l s e r v i c i o , po r l o
ta nt o el pa rm etr o intento nun ca p odr ser i gua l a null.. Es to t i ene sen t ido
c ua ndo e l s e r v i c i o no pu e de r e a nuda r s e una ve z i n t e r r umpi do .
start redeuIver intent: E l s i s t ema t r a ta r de vo lve r a c rea r e l s e rv ic io . E l
pa r me t ro intento s e r e l qu e s e u t i l i z en l a l t i mal l a ma da startservice (Intent).
STAPT_STICKY_COMPATIBILITy" : V e r s i n c ompa t i b l e de s t a r t sticky, que no
ga r a n t i z a que onstartcomnandl) s e a l l a ma do de s pu s de que e l p r oc e s o s e a ma t a do .
9.3. Las notificaciones de la barra de estado
La ba r ra de e s tado de Andro id se encuent ra s i tuada en l a pa r te supe r ior de
l a pa n t a l l a . L a pa r t e i z qu i e r da de e s t a ba r r a e s t r e s e r va da pa r a v i s u a l i z a r
no t i f i c a c i one s. C ua ndo s e c r e a una nue va no t i f i c a c i n , a pa r e c e un t e x t ode s p l a z ndos e e n l a ba r r a , y a c on t i nua c i n , un pe que o i c ono pe r ma ne c e r e n
l a ba r r a pa r a r e c o r da r a l u s ua r i o l a no t i f i c a c i n .
E l u s ua r i o pue de a r r a s t r a r l a ba r r a de no t i f i c a c i one s ha c i a a ba j o , pa r a
mos t r a r e l l i s t a do de l a s no t i f i c a c i one s po r l e e r . U n pos i b l e e j e mpl o s e
mue s t r a a c on t i nua c i n :
http://stapt_sticky_compatibh.it/http://stapt_sticky_compatibh.it/http://stapt_sticky_compatibh.it/http://stapt_sticky_compatibh.it/http://stapt_sticky_compatibh.it/http://stapt_sticky_compatibh.it/http://stapt_sticky_compatibh.it/ -
7/27/2019 Capitulo 9 Del Gran Libro de Android
10/19
272
Una notificacin puede ser creada por un servicio o por una actividad. Aunque dado que la actividad
dispone de su propio interfaz de usuario, parece que las notificaciones son el mecanismo de interaccin
ms interesante del que disponen los servicios. Las notificaciones pueden crearse desde un segundo
plano, sin interferir con la actividad que en ese momento est utilizando el usuario.
Para crear una notificacin en la barra de estados has de seguir los siguientes pasos. Aade el
cdigo de ejemplo a la clase S erv i c i oM u s i ca .
1) Obtenuna referencia al Not i f i cat ionManager . Para ello, declara las siguientes variables y
aade al mtodo onCreate
prvate N o t i f i c a t i o n M a n a g er tn
p r va t e s t a t i c . f i n a l i n tID_NOTIFICACION_CREAR
= 1 ;
@override
public voidon C reat e ( ) {
n m = ( N ot i f i ca t ion M an ager ) ge tS ys t em S erv i ce {NOTIF ICAT10N_SERVICE) ;
2) Instancia una nueva notificacin:
Notif icat ion not i f icacin = new Noti f icat ion (
R .drawable . i c on ,
" crean d o S erv i c i o d e M s i ca" ,
Sys tem , currentTimeMillis( ) ) ;
Como puedes ver, en el constructor de una notificacin hay que indicar 3 parmetros: el icono a
visualizar (en el ejemplo usamos el mismo que el de la aplicacin), el texto a mostrar y cuando
queremos que se visualice (en el ejemplo indicamos que ahora mismo).
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
11/19
273
3) Define informacin adicional que ser utilizada en la ventana de notificaciones. Esta informacin
incluye el mensaje expandido y la actividad a ejecutar cuando se pulse sobre la notificacin:
Pe nd i ng l n t en t i n t e n t oPe nd i e n t e = Pe nd i ng I n t e n t .getActi vit y (
th i s , 0 , new In ten t ( th i s , Ac t iv idadPr in c ipa l . c la s s ) , 0 ) ;
no t i f i c a c i n . s et L a t e s t E ve n t I n f o( t h i s , "R e pr oduc i e ndo ms i c a " ,
" i n f o r ma c i n a d i c i ona l " , i n t e n t oPe nd i e n t e ) ;
Cuando el usuario abra la ventana de notificaciones, podr ver informacin adicional formada por
un ttulo y un texto explicativo. Adems se podr asociar una actividad para que se ejecute cuando
el usuario pulse sobre la notificacin. En el ejemplo se crea un Pendinglntent asociado a la
actividad A ct i v i d ad P r i n f c i p a l . Por supuesto, tambin puedes crear una nueva actividad
para usarla exclusivamente con este fin. En un ejemplo ms complejo, puedes pasar los parmetros
adecuados a travs del i n t en c , para que la actividad conozca los detalles especficos que
provocaron la notificacin (por ejemplo, el nmero de telfono que provoc la llamada perdida).
Una notificacin puede tener otros parmetros, por ejemplo, puede reproducir un sonido, puede
hacer vibrar el telfono o puede hacer parpadear un LED del telfono. Puedes consultar el
siguiente punto si ests interesado en alguno de estos aspectos.
4) Pasa la notificacin creada al Not i f i cat ionManager:
nm.not i fy ( ID_NOTIFICACION_CREAR. no t i f i c a c i n ) ;
! . . . / / r e s t o de c d i go de onc r e a t e ( )
5) Si el servicio deja de estar activo, eliminamos la notificacin:
@Override
pu b l i c vo id onD e s t r oy( ) (
nm. c a nc e l {1D_N0TIFICACI0N_CREAR) ;
Este paso es opcional. Muchas notificaciones han de permanecer .visibles aunque el servicio quelas creo sea destruido. En nuestro caso, dado que estamos anunciando que un servicio de
reproduccin de msica est activado, la notificacin deja de tener sentido al desaparecer el
servicio.
9.3.1. Configurando tipos de avisos en las notificacionesComo hemos comentado una notificacin puede utilizar diferentes mtodos para alertar al
usuario de que se ha producido. Veamos algunas opciones.
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
12/19
274
9.3.1.1. Asociar un sonido
Si consideras que una notificacin es muy urgente y deseas que el usuario pueda conocerla de forma
inmediata, puedes asociarle un sonido que ser reproducido cuando se produzca.
El usuario puede definir un sonido por defecto para las notificaciones. Si quieres asociar el sonido
de notificaciones por defecto, utiliza la siguiente sentencia'
notificacion.defaults = Notificacin.DEFAULT SOUND;
Si prefieres reproducir un sonido personalizado para la notificacin, puedes almacenarlo en una carpeta
y usar:
notificacin.sound - Uri.parpe("file://'sdcard/carpeta/tono.mp3";
Si el fichero de audio se encuentra almacenado en el ContentProvider MediaStore. puedes utilizar
la siguiente sentencia:
notificacion.sound =
Uri.withAppendedPath(Audio.Media.INTERNAL CONTENT ORI, "6");
Tendrs que sustituir el parmetro 6" por el ID del elemento que quieras reproducir. Si desconoces
este ID, puedes realizar una consulta al ContentProvider Para ms informacin consulta el apartado
7.6.
9.3.1.2. Aadiendo vibracin
Tambin es posible alertar al usuario haciendo vibrar el telfono. Puedes utilizarla vibracin por defecto:
notificacin .defaults |= Notification . DEFAULT_VIBRATE ;
O por el contrario tu propio patrn de vibracin:
Long()vibrate = {0,100,200,300}; notication.vibrate
=vibrate;
El array define un patrn de longitudes expresadas en milisegundos; donde el primer valor es el
tiempo sin vibrar, el segundo es el tiempo vibrado, el tercero sin vibrar y asi sucesivamente. Este array
puede ser tan largo como queramos, pero solo ser activado una vez. no se repetir de forma cclica.
9.3.1.3. Aadiendo parpadeo de LED
Algunos mviles disponen de diodos LED que pueden ser utilizados para avisar al usuario que se ha producido una
notificacin. Este mtodo es muy interesante si el grado de urgencia del aviso no es lo suficientemente alto para usar uno
de los mtodos anteriores.
Podemos utilizar el aviso de LED configurado por defecto:
http://%27sdcard/carpeta/tono.mp3http://%27sdcard/carpeta/tono.mp3http://%27sdcard/carpeta/tono.mp3http://%27sdcard/carpeta/tono.mp3 -
7/27/2019 Capitulo 9 Del Gran Libro de Android
13/19
275
Notification.defaults |=notification.DEFAULT_LIGHTS;
O podemos definir una cadencia de tiempo y color especfica para nuestra notificacin:
Notification.ledARGB=0xff00ff00;
Notification.ledOnMS=300;
Notification.ledOffMS=1000;
Notification.flags | =Notification.FLAG_SHOW_LIGHTS;
En el ejemplo anterior se empieza indicando que queremos que el LED se ilumine en color verde, durante 300 ms y
luego est apagado durante 1 segundo. Esta secuencia se repetir de forma cclica hasta que el usuario atienda la
notificacin.
Conviene destacar que no todos los mviles disponen de un LED para este propsito. Adems, no todos los colorespueden ser utilizados, siendo e! color verde el ms habitual para indicar una notificacin.
9.4. Un servicio comomecanismo de comunicacin entre aplicaciones
Como hemos comentado, un servicio tiene una doble funcionalidad, adems de permitir la ejecucin de cdigo en
segundo plano, vamos a poder utilizarlo como un mecanismo de comunicacin entre aplicaciones .
Cuando una aplicacin quiere compartir algn tipo de informacin a otra aplicacin se presenta un problema. Las
aplicaciones en Android se ejecutan en procesos separados y por tanto tienen espacios de memorias distintos. Esio nos
impide, por ejemplo, que ambas aplicaciones compartan un mimo objeto.
Como respuesta a este problema Android nos propone un mecanismo de comunicacin entre procesos que se basa
en un lenguaje de especificacin de nterfaces, AIDL, que son publicados por medio de servicios.
AIDL [Android Interface Definition Language) es un lenguaje de especificacin de interfaces que permite que un
proceso en Android pueda liamar a un mtodo de un objeto situado en un proceso diferente al suyo. Se trata de un
mecanismo de comunicacin entre procesos similar a COM o Corba, aunque algo ms ligero.
S queremos comunicar dos aplicaciones a travs de este mecanismo seguiremos los siguientes pasos:
1) Escribiremos un fichero AIDL: En el se define la interfaz. es decir los mtodos y los parmetros que luego
podremos utilizar
6http://developer.android.eom/quide/topics/fundamentals.html#rpc
http://developer.android.eom/quide/topics/fundamentals.html%23rpchttp://developer.android.eom/quide/topics/fundamentals.html%23rpchttp://developer.android.eom/quide/topics/fundamentals.html%23rpchttp://developer.android.eom/quide/topics/fundamentals.html%23rpc -
7/27/2019 Capitulo 9 Del Gran Libro de Android
14/19
276
2) Implementaremos los mtodos de la interfaz: Para ello, habr que crear unaclase en Java que implemente estos mtodos
3) Publicar la interfaz a los clientes: Para ello, se extender la clase servicesobrescribiremos el mtodo OnBind(intent) de forma que devuelva una instancia de laclase que implementa la interfaz.
Veamos estos tres pasos ms detenidamente por medio de un ejemplo. Para ello, crea la
siguiente aplicacin:
Proiect name: Servicio-Remoto
Bui Id Target: Android 2.0
Application name: Servicio Remoto
Package ame: org.example.serviciocliente
Create Activity ActividadPrincipal
Min SDK Versin: 5
Reemplaza el cdigo del Layout main.xml por el mismo utilizado en ServicioMusica.Reemplaza los textos de los botones "Arrancar servicio" por"Conectar servicio" y "Detenerservicio" por"Desconectar servicio". Crea dos botones ms. Uno con texto "Reproducir" e id"@*-d/boton_reproducir" y otro con texto "Avanzar" e id "@+id/boton_avanzar".
Copia el fichero res/raw/audio.mp3 a la nueva aplicacin.
9.4.1. Crear la interfaz en AIDL
El lenguaje de especificacin de interfaces AIDL, tiene una sintaxis similar a Java,aunque como su nombre permite nicamente identificar la interfaz de un objeto no suimplementacin.
Una interfaz estar formado por una secuencia de mtodos cada uno con una serie deparmetros y un valor devuelto. Tanto los parmetros como el valor devuelto han de tener untipo. Los tipos permitidos se indican a continuacin:
Tipos primitivos: int, short, byte,char, float, double,long, Boolean.
Uno de los siguientes tipos: string, CharSequence, List, Map.
Una interfaz escrito en AIDL.
Un Objeto Parcelable.
Para seguir con el ejemplo, crea un nuevo fichero con nombre
IServicioMuaica . a idl dentro de arc/org.example. servicioaidl/ con el siguiente cdigo:
package org.example.servicioremoLo; interface IServicioMusica {
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
15/19
277
String reproduce(in String mensaje);
void setpPosicon (int ms);
int get.Posicion ();
}
Como puedes observar la sintaxis es similar a Java aunque existen diferencias. La msdestacable consiste en que los parmetros de los mtodos cuyos tipos no sean primitivos,han de indicar la etiqueta in, out o inout; segn sean parmetros de entrada, salida o de lasdos cosas a la vez. Para los tipos primitivos solo se permite que acten como entrada, porlo tanto se procesan de forma predeterminada comoin.
Nota: Igual como ocurre con las clases en Java los interfaces en
AIDL han de escribirse en fichero con igual nombre que lainterfaz.
9.4.2. Implementar la interfaz
Un vez escrito esta interfaz y almacenado en el fichero .aidl, el P L U G - I N de Eclipsegenerar de forma automtica el fichero
gen/org . example . serviciorernoto/IServicioMusica . java .
Este fichero implementa la interfaz Java IServicioMusica como descendiente de
IInterface. En IServicioMusica se define internamente la clase abstracta Stub que
implementa la interfaz escrito en AIDL. Es decir, la clase Stub contiene tantos mtodosabstractos como mtodos declaramos en la interfaz AIDL. La clase stub tambin define unaserie de mtodos que le permiten el intercambio de informacin cuando se invoquen estosmtodos entre procesos remotos.
Ahora tenemos que darle funcionalidad al interfaz, para ello tendremos que crear una
clase que extienda IServicioMusica.Stub y que implemente todos los mtodos abstractos deesta clase, o lo que es lo mismo, los mtodos declarados en la interfaz AIDL. Un ejemplo decmo podramos implementar estos mtodos se muestra a continuacin. Ms tarde se indicadonde hay que introducir este cdigo:
prva te final IServicioMusica.Stub binder = new IServicioMusica.Stub() {
public String reproduce(String mensaje) {
reproductor.start();
return mensaje;
}
public void setPosicin (int ms) {
reproductor.seekTo(ms);
}
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
16/19
278
public int getPosicion() {
return reproductor.getCurrentPosition()
} };
La variable reproductorser declarada posteriormente de tipoMediaPlayer. Como puedes ver, en
el mtodo reproduce, tanto el parmetro de entrada como el valor devuelto no tienen ninguna
utilidad. Se han introducido para ilustrar el paso de una variable no primitiva.
Cuando implementes los mtodos de una interfaz AIDL has de tener en cuenta lo siguiente:
Si generas una excepcin desde uno de estos mtodos, esta no pasar a la aplicacin que hizo lallamada
Las llamadas son sncronas. Por lo tanto, has de tener cuidado de que cuando se haga unallamada que tarde cierto tiempo en responder, nunca se realice desde el hilo principal de la
aplicacin. Si este hilo queda bloqueado demasiado tiempo, aparecer el incmodo cuadro de
dilogo "La aplicacin no responde". En estos casos, crea un hilo secundario, desde donde se haga
la llamada.
Solo es posible declarar mtodos; no puedes declarar campos estticos en una interfaz AIDL
9.4.3. Publicar a interfaz en un servicio
Otras aplicaciones han de tener visible esta interfaz para poder comunicarse con nosotros. Esto se
consigue creando un servicio que contenga nuestra interfaz.
Para ello has de crear una clase que herede de Service y que reescriba el mtodoencina O . Este
mtodo ser utilizado para devolver un objeto que implementa nuestra interfaz. Veamos cmo se
escribira este servicio:
public class ServicioRemoto extends Service{ MediaPlayer
reproductor;
public void onCreateO (
super.onCreate() ;
reproductor =MediaPlayer.create(ServicioRemoto.this, R.raw.audio);
private final IServicioMusca.Stub binder new IServicioMusica.Stub(){
// Copia agu. e.lcdigo anterior
};
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
17/19
279
@Override
public IBinder onBind(Intent intent){
return this.binder;}
}
Crea una nueva ciase en el proyecto e introduce este cdigo. Para que el servicio sea visible a otras
aplicaciones hay que publicarlo declarndolo enAndroidManitest.xml. Para ello copia el siguiente
cdigo dentro de la etiqueta
.
< servicios android:name="ServicioRemoto"
android:process=":remoto">
El atributo name ha de coincidir con la clase que implementa el servicio. El atributoprocess
permite que el servicio se ejecute en un proceso propio, diferente al resto de los componentes de la
aplicacin. A continuacin, indicaremos dentro de la etiqueta
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
18/19
280
I S erv ic omusca. stub. asinterf ace () pasndole como parmetro esta instancia de
iB inde r para inicializar el objeto declarado en el primer punto.5) Ya puedes llamar a los mtodos del objeto remoto declarados en el punto 1). En nuestro casoreproducir (),setPosicin () y getPosicion (I.
6) Puedes desconectarte del servicio utilizando el mtodo u n b i n d S e r v i c e ( ) .
Realizaremos este trabajo en la clase A c t i v i d a d P r i n c i p a i . Reemplaza su cdigo por el
siguiente:
public class ActividadPrincipal extends Activity {
private IServicioMusica servicio; (1)private Servi ceConnect ion conexin= new ServceConnect ion () (2)
public void onServiceConnected(ComponentName className (4)
IBinder Iservicio){servicio = IServicioMusica.Stub.asInterface(Iservicio) ; Toast..MakeTexc (ActividadPrincipal. this;
"Conectado a Servicio", Toast.LENGTH_SHORT).show();
jpublic void onServiceDisconnected(ComponentName className) { servicio = null;
Toast.. makeText(ActividadPrincipal. this ,
"Se ha perdido la conexin con el Servicio", Toast .LENGTH_SHORT) .show();} }@override
public void onCreate(Bundle savedInstanceState){| super.onCreate!saved InstanceState);
setContentView(R.layout.main)Button botonConectar = (Button) FindViewById(R.id.boton_arrancar);
botonConectar.setOnClickListener(new OnCi ickListener(){ ( public void onClick(Viewv) {
Act ividadPrincipal . this , bindService ({ (3 )new intent (ActividadPrincipal.this, ServicioRemoto.class) conexion,
Context.B1ND_AUT0_CREATE) ;}});
Button botonReproducir= (Button! findViewById R.Id.boton_repproducir);Boton_reproducir.setOnclickListener(new OnClickistener(){
Public void onclick(View v)}try{
Servicio.reproduce(titulo);}Catch(exeption e){
-
7/27/2019 Capitulo 9 Del Gran Libro de Android
19/19
281
Toas Maketext(ActividadPrincipal.this,e.toString();
Toast.LENGTH_SHORT) .showf);
Button botonAvanzar = (Button)findViewById(R. id.boton__avanzar);
botonAvanzar . setOnClickListener (new OnClickListener (){public void onClick(View v) { try {
servicio.setPosicion(servicio.getPosicion() +10 00) ; (5) j catch (Exception e; |
Toast.makeText(ActividadPrincipal.this, e.toString();,Toast.LENGTH _SHORT) .show();
}}});
Button botonDetener =(Button) findViewById(R.id.boton_detener) ; botonDetener . setOnCl ickListener (new OnClickListener (); {
public void onClick;. (View v) { try
ActividadPrincipal.this.unbindService(conexion) ; (6)
} catch (Exception e) {Toast. makeText (ActividadPr incipal. this, r.. toString () ;
Toast . LENGTH_SHORT) . show () ;
}Servicio=null;
}});}}
La acti vidad est formada por 4 botones para realizar las acciones de conectarse alservici o, desconectarse, reproduci r msica y avanzar 1 segundo (1.000 ms). Si losbotones no se activan por el orden adecuado podemos provocar excepciones. Estas son
capturadas y visualizadas mediante untoast , por lo que la aplicacin continuarfuncionando aunque se produzcan. Prueba a ll amar aun mtodo antes de establecer la
conexin o tr ata de desconectar te dos veces para observar las excepciones generadas.