CLASE 03

Servicios

¿Qué es un Servicio?

Los servicios son un componente de la aplicación que pueden realizar largas operaciones de “fondo” sin la necesidad de interacción con el usuario.

 

Cualquier otro componente de la aplicación puede iniciar un servicio y este puede seguir “corriendo” aunque el usuario cambie o cierre la app.

 

Por ejemplo un servicio podría reproducir música, manejar conexiones con servicios web o realizar operaciones en el disco desde el “fondo” .

¿Servicio o AsyncTask?

Un Servicio NO NECESARIMENTE corre en el UI Thread (Hilo de Interfaz de Usuario, o Hilo Principal).

 

Entonces, la pregunta es ¿Porque usar un Servicio y no una AsyncTask? O dicho de otra manera: ¿Cuándo usar un Servicio y cuando un AsyncTask?

¿Servicio o AsyncTask?

  • Las AsyncTask están diseñadas para ejecutar tareas que requieran momentánemente gran consumo de recursos.
  • Los Servicios están diseñados para correr continuamente en el fondo.

Por ejemplo, como vimos la clase anterior, si queremos descargar información de un Servicio Web al presionar un Boton, usamos un AsyncTask.

Se podría hacer lo mismo con un Servicio: iniciarlo, tomar los datos, y detenerlo, pero no sólo es más complejo sino que ademas es ineficiente.

La AsyncTask se ejecuta, corre una única vez, y obtiene los datos.

¿Servicio o AsyncTask?

  • Los Servicios son como una Actividad, pero sin interfaz gráfica. Por ejemplo, si quisieramos mostrar actualizaciones del Clima, no usuariamos una Actividad en blanco, sino un Servico

A diferencia del ejemplo que plateábamos antes, como en este caso vamos a estar constántemente consumiendo datos de la Web, es más eficiente utilizar un servicio. Y además ni siquiera necesitamos una actividad para mostrar los datos.

¿Servicio o AsyncTask?

Como regla general, podemos decir que los Servicios son para cuando queremos realizar acciones por más de que nuestra aplicación esté cerrada.

Y las AsyncTask están diseñadas para ejecutar código fuera del Hilo Principal de una manera rápida y sencilla.

TIPOS DE SERVICIOS

Started Service

Un Servico es Started cuando es lanzado por otro componente de una Aplicación mediante el método startService. Una vez que es iniciado el servicio corre de manera indefinida, aunque el componente que lo inició sea destruido. Usualmente este servicio corre una sola tarea y no devuelve ningún resultado a quien lo inició. Cuando la operación finalizó el servicio debe detenerse por sí mismo. Este tipo de Servicio no tiene conexión con el componente que lo inició. Es decir, no pueden directamente realizar actualizaciones de UI

 

Por ejemplo, cuando descargamos un archivo de la web y lo guarda en disco

Bound Service

Un Servico es Bound cuando es lanzado por otro componente de una Aplicación mediante el método bindService. Este servicio ofrece una interfaz cliente-servidor que permite a los componentes interactuar con él. Un servicio de este tipo sólo corre mientras algún componente de la aplicación esté conectado a él. Muchos componentes pueden conectarse con el servicio, pero cuando el último se desconecte el servicio se destruirá. A diferencia de los started, pueden comunicarse con el componente que lo inició.

Por ejemplo, un reproductor de música que envia info sobre el estado del playback y tiempo transcurrido.

STARTED SERVICES

Started Services

Todo servicio debe tener un metodo onBind que es el que se llama cuando un componente se quiere conectar con él. Sólo lo usamos con los Bound Services, por tanto los Started Services, sólo requieren una implementación básica del mismo.

Cuando se inicia un servicio por primera vez con startService, se invoca en método onCreate. Y luego se llama al método onStartCommand. Si el servicio ya se encontraba iniciado, no se llama al onCreate pero sí al onStartCommand.

Started Services

Los parametros que recibe el onStartCommand son: 

  • Intent el intento que dio origen al servicio
  • Flags Banderas que describen el funcionamiento
  • ID ID unica asiganda al proceso en cuesiton. Si el proceso es detenido y luego reiniciado, lo hace con el mismo ID

Started Services

El valor de retorno del onStartCommand indica el comportamiento en caso de que el servicio sea terminado por el sistema:

  • START_STICKY El servicio será reiniciado luego de ser terminado. El intento del nuevo inicio será null (no se vuelve a enviar el mismo intento que lo originó) y el segundo argumento sera START_FLAG_RETRY.
  • START_NOT_STICKY El servicio sólo se reiniciará si hay intentos pendientes, y se pasa ese intento como argumento.
  • START_REDELIVER_INTENT Es una mezcla de ambos. Le dice al sistema que reinicie el servicio y si no hay intentos pendientes, utilice el mismo que lo creo

Crear Servicio

<service android:name=".StartedService"></service>
  • Crear la Clase (con onBind, onCreate y onStartCommand y onDestroy)
  • Agregarlo en el manifiesto

 

  • Lo iniciamos a travez de un Intento
  • Y lo detenemos con el mismo intento

 

Vamos a ver el comportamiento tras iniciar, y volver a iniciar, detener y reiniciar, etc.

Asi como también vamos a ver los diferentes valores de retorno.

Realizar Tarea Temporizada

Una forma de realizar una tarea temporizada, es a travez de un AsyncTask. Necesitamos este AsyncTask para separar el proceso del servicio del proceso de la app.

 

  • Creamos la AsyncTask que reciba ID y devuelva ID
  • Hacemos un Sleep
  • Detenemos al servicio que finalizó su tarea
  • Lanzamos varios Servicios (STICKY y NOT_STICKY)
  • Cancelamos la Tarea al detener el servicio

BOUND SERVICES

Bound Services

Los started Services no pueden retornar valores o resultados, ni interactuar con el componente que los creo. Para esos casos, usamos los bound Services, ya que pueden enviar datos al componente que los inició.

Por eso es que un componente crea un servicio y ademas se "une" o "ata" (bind) a él. Un servicio se puede ligar a varios componentes, y liberarlo (unbind) cuando termine con él.

Bound Services

Cuando el último componente se desligue, recién ahí se destruye el servicio. Internamente, el servicio lleva la cuenta de los componentes que tiene unidos, cada vez que se libera uno, decrementa este valor, y al llegar a CERO lo destruye.

Así mismo, si el componente al que está unido es destruido o finaliza su ciclo de vida, el servicio también se destruye con él.

Bound Services

Cuando un componente se une a un bound services, se crea una interface de comunicación donde pueden enviar y recibir información. Esta interface es de tipo IBinder, y el cliente (componente) la obtiene del método onBind (luego de invocar bindService), a traves de una interfaz ServiceConnnection, la cual debe ser provista por el cliente.

Este IBinder es básicamente una interfaz de comunicación:

 

El cliente invoca métodos de esta interface y la ejecución ocurre en el Servicio

Bound Services

  • Creamos el Servicio
  • Lo agregamos al Manifiesto
  • Creamos una clase interna que es nuestro Binder
public class CronoBinder extends Binder{
    public BoundService obtenerServicio (){
        return BoundService.this;
    }
}
  • En el onCreate creamos una instancia de este IBinder
  • En el método onBind devolvemos una instancia de este IBinder
public IBinder onBind(Intent intent) {
    // Creamos la interfaz de comunicacion (IBinder) y la devolvemos al cliente
    binder = new CronoBinder();

    return binder;
}

Bound Services

  • Nos unimos al Servicio al INICIAR la actividad
bindService(boundIntent, conexion, BIND_AUTO_CREATE);
  • Debemos proveeer un ServiceConnetcion
private ServiceConnection conexion = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        BoundService.CronoBinder binder = (BoundService.CronoBinder) service;
        cronometro = binder.obtenerServicio();
        boundConectado = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        boundConectado = false;
    }
};
  • Nos desligamos del mismo al DETENER la actividad
if (boundConectado == true){
    unbindService(conexion);
    boundConectado = false;
}

Bound Services

  • Creamos nuestros propios métodos en el servicio
  • Invocamos estos métodos desde nuestra actividad

 

Es importante remarcar que los metodos son ejecutados en el mismo hilo (Thread) que el cliente que lo invoca, en este caso el UI Thread, por tanto si la operación es de largo tiempo de ejecución, deberíamos crear un hilo a parte, donde correr este método

 

Vamos a notar los LOGS para ver la evolución del servicio, por sus diferentes estados.

Notar que pasa al cerrar la app y al abrirla

Gracias!

No dejen de consultar cualquier duda que surja

sebasira@gmail.com

Made with Slides.com