En este artículo, discutiremos un componente importante en el desarrollo de aplicaciones Android: Android Service. A diferencia de Activity, Service se ejecuta en segundo plano en Android, no tiene interfaz y su ciclo de vida también es diferente al de Activity. Usando Service se pueden realizar operaciones en segundo plano, como cargar una página web desde un servidor remoto. Podemos usar Service para implementar multitarea en Android.
Descripción general de Android Service
Sabemos que si los recursos del sistema se vuelven escasos, la Activity de Android puede iniciarse, detenerse, destruirse e incluso posiblemente recrearse. Service está diseñado para tener un ciclo de vida más largo. Service en Android puede iniciarse desde una Activity, un receptor de transmisión (Broadcast receiver) o desde otros Services.
Es importante tener en cuenta que usar Service no crea automáticamente un nuevo hilo. Por lo tanto, si queremos implementar una lógica simple en Service que no requiera un procesamiento prolongado, no es necesario ejecutarla en un hilo separado. Sin embargo, si necesitamos implementar una lógica compleja que consuma mucho tiempo, debemos tener cuidado al crear nuevos hilos; de lo contrario, debido a que Service se ejecuta en el hilo principal, podría causar el problema ANR (Aplicación sin respuesta).
Los principales escenarios de uso de Service en Android son los siguientes:
- Implementar multitarea (multi-task)
- Comunicación entre procesos (IPC)
Un ejemplo típico del primer caso es cuando la aplicación necesita descargar datos desde un servidor remoto. En esta situación, se puede usar una Activity que interactúe con el usuario y, mientras el usuario usa la aplicación, iniciar un Service para completar el trabajo en segundo plano. También hay un escenario en el que Service envía información al usuario cuando ha completado la tarea.
En el segundo caso, queremos 'compartir' algunas funciones comunes para que diferentes aplicaciones puedan reutilizarlas. Por ejemplo, supongamos que tenemos un Service que puede enviar correos electrónicos y queremos compartir este servicio entre varias aplicaciones para no tener que reescribir el mismo código nuevamente. En tal caso, podemos usar IPC para que el Service exponga una interfaz 'remota' que otras aplicaciones puedan invocar.
Conceptos básicos de Service
Ahora que sabemos más sobre Service, vamos a crearlo. Para crear un Service en Android, necesitamos heredar de la clase Service.
public class TestService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
Podemos ver que solo hemos implementado un método llamado onBinde. En el ejemplo anterior, usamos un servicio local, por lo que el método devuelve null. Como se mencionó antes, Service tiene su propio ciclo de vida, por lo que podemos sobrescribir algunos métodos de devolución de llamada para manejar sus diferentes estados:
public class TestService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
El primer método, onCreate, solo se llama en el momento en que se crea el Service. Si el Service ya está en ejecución, este método no se llamará. No podemos invocarlo directamente; el sistema es responsable de llamarlo.
El método OnStartCommand es el más importante, ya que se llama cuando necesitamos iniciar Service. En este método, tenemos el Intent que se pasa al ejecutar el Service, de modo que podemos intercambiar información con el Service. Aquí implementamos nuestra propia lógica: si no es una operación que consume mucho tiempo, se puede ejecutar directamente en este método; de lo contrario, se puede crear un hilo. Como puedes ver, este método debe devolver un valor entero. Este entero representa cómo debe manejar el sistema este Service:
- START_STICKY: con este valor de retorno, si el sistema mata nuestro Service, será recreado. Sin embargo, el Intent enviado al Service no se volverá a entregar. Así, el Service se mantiene en ejecución.
- START_NOT_STICKY: si el sistema mata el Service, no se recreará a menos que el cliente invoque explícitamente el comando onStart.
- START_REDELIVER_INTENT: su funcionamiento es similar a START_STICKY. Además, en este caso, el Intent se volverá a entregar al Service.
OnDestory es el método que el sistema llama cuando el Service será destruido.
Una vez que tengamos una clase de Service personalizada, debemos declararla en Manifest.xml para poder usarla.
<service android:name=".TestService"
android:enabled="true"/>
Iniciar y detener Service
Como sabemos, un Service se inicia y eventualmente se detiene para poder completar su tarea. Supongamos que lo iniciamos desde una Activity; podemos usar un Intent para pasar información al Service. Supongamos que nuestra Activity tiene dos botones, uno para iniciar y otro para detener el Service:
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, TestService.class);
i.putExtra("name", "SurvivingwithAndroid");
MainActivity.this.startService(i);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, TestService.class);
MainActivity.this.stopService(i);
}
});
En la línea 5 del código de ejemplo anterior, creamos un Intent que pasa el nombre de la clase para manejar nuestro servicio, y establecemos algunos parámetros como el nombre. Luego, en la línea 7, iniciamos este Service. De la misma manera, en la línea 17 detenemos este Service.

Al hacer clic en el botón de inicio, obtenemos el siguiente Log:

Se puede notar que el método onCreate fue llamado. Debido a que esta es la primera vez que iniciamos este Service, si hacemos clic nuevamente en el botón de inicio, el sistema no llamará al método onCreate. Cuando hacemos clic en el botón de detener, el sistema destruye este Service.
IntentService
Como mencionamos anteriormente, Service se ejecuta en el hilo principal. Por lo tanto, debemos tener mucho cuidado al implementar lógica en Service. Hay que considerar que si esta lógica es una operación de bloqueo o tarda mucho tiempo en terminar, podría provocar el problema ANR. En ese caso, debemos mover la lógica a un hilo independiente. Esto significa crear un hilo dentro del método onStartCommand y luego ejecutarlo.
Otra clase, IntentService, derivada de Service, puede simplificar nuestro desarrollo. Esta clase es útil cuando no es necesario manejar múltiples solicitudes al mismo tiempo. Esta clase crea un hilo de trabajo para procesar diferentes solicitudes. Las operaciones que realiza son las siguientes:
- Crear un hilo separado para manejar las solicitudes.
- Crear una cola de solicitudes y pasar un Intent de vez en cuando.
- Crear una implementación predeterminada de onStartCommand.
- Finalizar el Service después de que todas las solicitudes se hayan ejecutado.
Si queremos crear un IntentService, necesitamos heredar de la clase IntentService en lugar de la clase Service:
public class TestIntentService extends IntentService {
public TestIntentService() {
super("TestIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
}
}
En este ejemplo, solo necesitamos implementar el método onHandleIntent. La lógica externa implementada aquí no necesita preocuparse de si la operación consume mucho tiempo, porque este método se llama en un hilo separado.
Iniciar Service automáticamente
Muchas veces queremos iniciar nuestro servicio automáticamente, por ejemplo, al encender el dispositivo. Sabemos que se necesita un componente para iniciar Service. Entonces, ¿cómo lograr el inicio automático? Podemos usar un receptor de transmisión (Broadcast receiver) para iniciar el servicio. Por ejemplo, si queremos iniciarlo cuando el teléfono inteligente se enciende, podemos crear primero un receptor de transmisión que escuche este evento (encendido) y luego iniciar el Service.
public class BootBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent intent) {
ctx.startService(new Intent(ctx, TestService.class));
}
}
Declarar en Manifest.xml:
<receiver android:name=".BootBroadcast">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Fuente: http://www.importnew.com/9019.html