domingo, 3 de junio de 2012

Introducción a los servicios en Android

En el sitio web http://androideity.com han publicado una excelente sección sobre los Servicios en Android, a continuación se las comparto para que todos puendan practicar este excelente bloque de construcción.


Siguiendo con los tutoriales enfocados a componentes de las aplicaciones en Android, hoy vamos a empezar una nueva serie de artículos dedicados a explicar qué son y cómo podemos utilizar servicios.
Los servicios son componentes que se ejecutan en background (o segundo plano) y que no interactúan con el usuario.
La plataforma Android ofrece una gran cantidad de servicios predefinidos, disponibles regularmente a través de la clase Manager. De esta manera, en nuestras actividades podremos accesar a estos servicios a través del método getSystemService().
Por otro lado, si necesitamos utilizar servicios propios, estos deben ir declarados en el archivo AndroidManifest.xml.
Más acerca de los servicios propios
Es posible declarar nuestros propios servicios que lleven a cabo operaciones de larga ejecución sin la interacción del usuario o bien para suministrar alguna funcionalidad a otras aplicaciones. Una actividad puede iniciar un servicio a través del método startService() y detenerlo con stopService(). Si la actividad quiere interactuar con el servicio podemos utilizar el método bindService(), que requiere de un objeto ServiceConnection que nos permitirá conectarnos con el servicio y que retorna un objeto IBinder, el cuál puede ser utilizado para que la actividad pueda comunicarse con el servicio.
Una vez que el servicio se ha iniciado, su método onCreate() es llamado. Posteriormente, se llama al método onStartCommand() con los datos del Intent proporcionados por la actividad. El método startService() también permite definir una bandera para determinar el comportamiento del ciclo de vida de los servicios. De esta forma, START_STICKY se utiliza para los servicios que se inician o detienen de forma explícita. Los servicios iniciados conSTART_NOT_STICKY se finalizan automáticamente después de que se termina de ejecutar el método onStartCommand(). Debes tomar en cuenta que un servicio se inicia en el hilo (thread) principal de la aplicación, por lo tanto, todas las tareas en tiempo de ejecución deben llevarse a cabo en segundo plano.
Como estamos hablando de servicios propios, será necesario que los registremos en el archivo AndroidManifest.xml colocando una etiqueta <service android:name=”TuClase”>dónde “TuClase” es el nombre de la clase Java que debe implementar a la clase Service o alguna de sus subclases que puedes checar en el árbol de herencia de la documentación.
Un caso común es que el servicio y la actividad que la llama estén estrechamente relacionados. Bajo este escenario, el objeto IBinder nos servirá para trabajar sobre la clase que ofrece el servicio que estemos utilizando.
Para ir aterrizando todos estos conceptos que hemos definido, vamos a realizar pequeños tutoriales empezando con el uso de los Broadcast Receivers 

Broadcast Receivers en Android
Para comenzar con los tutoriales prácticos de la serie Servicios en Android, el día de hoy vamos a trabajar con los componentes llamados Broadcast Receivers. Un broadcast receiver es una clase que extiende de BroadcastReceiver y que está registrada como un receptor en una aplicación Android ya sea a través del archivo AndroidManifest.xml o mediante código. La clase BroadcastReceiver será capaz de recibir Intents a través del método sendBroadcast(). También define el método onReceive(), en dónde nuestro objeto broadcast receiver será válido, después de que finalice su ejecución, el sistema considerará que el objeto ya no está activo, por lo que ya no será posible realizar alguna otra tarea asíncrona.
Acerca de los Pending Intents
Para realizar este tutorial haremos uso también de la clase PendingIntent, que es un token que le damos a otra aplicación a través de un Notification ManagerAlarm Manager u otras aplicaciones de terceros, que les permiten a estos componentes utilizar los permisos de nuestra aplicación para ejecutar un trozo de código predefinido.
Para lanzar un broadcast a través de pending Intents debemos trabajar sobre un objeto de la clase con este nombre y que obtenemos con PendingIntent.getBroadcast(). Por otro lado, si necesitáramos lanzar una actividad a través de este componente, la actividad la obtendríamos con el método PendingIntent().getActivity().

El código
Vamos a definir un broadcast receiver que escuche los cambios de estado del teléfono. Si el teléfono recibe una llamada, nuestro receptor será notificado y registrará un mensaje.
1. Creamos un nuevo proyecto llamado BroadcastReceiverTest con la versión Android 2.2.
2. En este caso no necesitaremos una actividad por lo que la clase que hereda de Activity y que nos produce automáticamente el wizzard de nuevos proyectos Android la modificaremos para que en su lugar herede de la clase BroadcastReceiver tal y como te muestro a continuación:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
 
public class BroadcastReceiverTestActivity extends BroadcastReceiver {
    /** Called when the activity is first created. */
 @Override
 public void onReceive(Context context, Intent intent) {
  Bundle extras = intent.getExtras();
  if (extras != null) {
   String state = extras.getString(TelephonyManager.EXTRA_STATE);
   Log.w(""DEBUG---------&gt;", state);
   if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
    String phoneNumber = extras
      .getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
    Log.w(""DEBUG---------&gt;", phoneNumber);
   }
  }
 }
}
Tal y como explicamos en la parte teórica de este tutorial, cuando utilizamos BroadcastReceivers resulta importante la implementación del método onReceive() que es el “equivalente” al método onCreate() en una actividad. Nota que el método onReceive() está sobreescrito de la clase padre. Dentro de este método, obtenemos un objeto Bundle que contiene el estado y la información adicional que trae el Intent que nos permitirá disparar una notificación proveniente del sistema del teléfono, que para este ejemplo es una llamada entrante en nuestro dispositivo. En caso de que la variable extras contenga algo (es decir, que en efecto exista una llamada) utilizamos la constante EXTRA_STATE de la claseTelephonyManager que nos brinda la información correspondiente a la llamada entrante y que guardaremos en una variable para desplegarla en el Log de Eclipse.
Si alguna vez haz intentado imprimir alguna bandera dentro de tu código como normalmente haríamos en Java con el System.out.println quizás hayas notado que esto no funciona en código Android; en cambio, utilizamos Log.w() para desplegar mensajes en la fase de debug de nuestras apps para detectar alguna inconsistencia en nuestro código.
Por último, una vez que hayamos desplegado el estado de la llamada, creamos otra condición por medio de la cuál si el teléfono se encuentra sonando porque hay una llamada, obtenemos el número a través de EXTRA_INCOMING_NUMBER y la guardamos en una variable para inmediatamente imprimirla en el Log.
3. Como hemos eliminado la actividad y en su lugar estamos creando un BroadcastReceiver, es importante que realicemos los cambios correspondientes en nuestro archivoAndroidManifest.xml que deberá quedarte como te muestro a continuación:
Utilizamos la etiqueta <receiver></receiver> para englobar todo lo que tenga que ver con elBroacastReceiver que utilizaremos. Por último, como la aplicación accesa a la información referente al estado del teléfono es necesario definir el permiso correspondiente para que todo vaya sin problemas.

Ejecución del demo
4. Para correr esta aplicación y ver los resultados en Eclipse será necesario simular la llamada a través de una pestaña llamada Emulator Control. ¿Y cómo se hace?
El IDE de Eclipse nos brinda varias herramientas que nos facilitan la vida para monitorear todo lo relacionado a nuestras aplicaciones Android. Generalmente en la parte inferior nos encontramos con un par de pestañas de las cuáles tal vez la de Console sea la que más utilices para ver cómo va el proceso de ejecución de los demos en el emulador.
Además de las pestañas que vienen predefinidas por Eclipse cuando instalaste tu entorno de desarrollo Android, es posible agregar otras pestañas que nos brindarán otras funciones bastante útiles. Para efectos de este tutorial necesitamos agregar la pestaña de LogCat (que es en dónde imprimiremos los mensajes según lo que haga nuestra aplicación) y la deEmulator Control (que nos permitirá simular la llamada entrante al emulador Android).
Para agregarlas nos vamos a la opción Window > Show View y seleccionamos estas dos opciones.
En caso de que en este menú no aparezca alguna de las dos, seleccionamos la opción Other, en donde podremos elegir entre todas las herramientas disponibles para el entorno Android.
5. Ejecutamos nuestro proyecto y esperamos a que cargue el emulador. No te preocupes si te sale una alerta en color rojo en la pestaña de Console, esto es normal ya que te está diciendo que si tratamos de abrirla directamente en el emulador no se podrá porque no contiene una actividad principal que lanzar.
6. Una vez que ya esté el emulador listo, nos vamos a la pestaña de Emulator Control y en el apartado Telephony Actions definimos un número telefónico que será el que supuestamente estará realizando la llamada al emulador. Nota: El número es indistinto, es decir, no es necesario que sea un número real para que funcione.
Ya sólo bastará con presionar el botón Call y automáticamente veremos que se realiza la llamada en el emulador.
7. Ya arrancada la acción vamos a comprobar que nuestro Broadcast Receiver registre las acciones que definimos en la clase, para lo cuál nos situamos en la pestaña de LogCat. Esta pestaña nos muestra 4 columnas: TimepidtagMessage. En los parámetros del métodoLog.w() definimos un tag y un mensaje. Por lo que es más sencillo buscarlo por el tag distintivo que escribimos (DEBUG):
¡Listo! Todo ha funcionado bien. Espero que este tutorial te ayude a comprender los aspectos básicos de para qué sirven los Broadcast Receivers y toda la gama de funciones que podemos implementar según los eventos y estados del teléfono que accesemos. Así también, te invito a que pruebes las herramientas del IDE Eclipse que si bien no forman parte del entorno Android como tal nos ayudan a hacer pruebas más reales y en algunos otros casos nos ayudará a que nuestro código muestre notorias mejoras.
FUENTEhttp://androideity.com/tag/servicios-en-android/

2 comentarios:

  1. Hermoso copy-paste! Un nerd que roba artículos y los publica como suyos.... q porquería...

    ResponderEliminar
  2. Hola Erick, buenos dias! gracias por tu comentario. Si, tenes razon ,por eso, al final puse LA FUENTE: ANDROIDEITY. No es de mi autoria, es mas, la mayoria e los articulos de este blog son para referencia online mia, no de autoria mia. Sepa disculpar si esto lo molestò a usted. Saludos cordiales.

    ResponderEliminar