Disposición inicial

En este caso, nuestra interfaz de usuario será muy sencilla por lo que no utilizaremos ningún código base. Para configurar el servicio es necesario modificar el Manifest y agregar <service android:enabled="true" android:name=".ElServicio" />

Diseño

El diseño presenta dos botones, uno para detener y otro para iniciar el servicio. Se sugiere utilizar layouts, en nuestro caso el código completo del layout es:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
	<TextView
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="Utilización de Servicios"
	    android:gravity="center"
	    android:textSize="20sp"
	    android:padding="20dp"/>
	<LinearLayout
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:gravity="center">
		<Button
			android:text="Inicio"
			android:id="@+id/btnInicio"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content">
		</Button>
		<Button
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="Detener"
			android:id="@+id/btnFin">
		</Button>
	</LinearLayout>
</LinearLayout>

Agregando código

Necesitamos de una clase adicional que represente al servicio, la llamaremos ElServicio y debe heredar de Service (en android.app). Esta clase debe sobrecargar el método onBind pero en este capítulo no nos interesa que haga algo así que únicamente devolverá null.

Para que la clase funcione de la manera deseada, vamos a sobrecargar tres métodos: onCreate, onDestroy y onStart, en cada uno de ellos a través de un toast vamos a verificar cuando el flujo pasa por estos puntos.

En onCreate vamos a inicializar lo que hará el servicio más adelante,  en nuestro ejemplo utilizaremos el media player ya reproducir un sonido, como demo he descargado uno desde soundjay.com luego renombrado a water_droplet por el convenio de nombres que no incluye guiones y por último colocado en /res/raw/

En onStart vamos a iniciar la reproducción del sonido y en onDestroy vamos a detener el sonido que se estaba reproduciendo. En resumen, lo necesario para cada uno de estos métodos es:

  • onCreate: Inicializar el Media Player e indicar que funcionará con un loop reproduciendo el sonido.
  • onDestroy: Detener la reproducción del sonido
  • onStart: Iniciar la reproducción del audio.

Es decir, el código de nuestra clase de servicios completo queda de la siguiente forma:

public class ElServicio extends Service {

	private MediaPlayer player;

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		Toast.makeText(this, "Servicio Creado", Toast.LENGTH_LONG).show();
		player = MediaPlayer.create(this, R.raw.water_droplet);
		player.setLooping(true);
	}

	@Override
	public void onDestroy() {
		Toast.makeText(this, "Servicio Detenido", Toast.LENGTH_LONG).show();
		player.stop();
	}

	@Override
	public void onStart(Intent intent, int startid) {
		Toast.makeText(this, "Servicio Iniciado", Toast.LENGTH_LONG).show();
		player.start();
	}

}

Este código del servicio se ejecutará como una tarea en Background es decir podríamos cerrar la aplicación y la ejecución continuaría. Por lo mismo, adicional al servicio, es necesario construir código para iniciarlo y detenerlo. Esto lo haremos en nuestra actividad principal asociando acciones a los botones previamente mencionados en el diseño.

Dado que tenemos 2 botones que tendrán el mismo listener en lugar de instanciar un OnClickListener como una clase anónima nuestra Actividad implementará a OnClickListener.

public class Main extends Activity implements OnClickListener

Dentro del método onCreate de la actividad asociamos el listener a los botones

Button btnInicio = (Button) findViewById(R.id.btnInicio);
Button btnFin = (Button) findViewById(R.id.btnFin);

btnInicio.setOnClickListener(this);
btnFin.setOnClickListener(this);

Por último es necesario sobrecargar el método onClick y dentro de él distinguimos que botón fue presionado y realizamos la acción asociada en cada caso.

public void onClick(View src) {
  switch (src.getId()) {
  case R.id.btnInicio:
    startService(new Intent(this, ElServicio.class));
    break;
  case R.id.btnFin:
    stopService(new Intent(this, ElServicio.class));
    break;
  }
}

Descargar:

Puedes descargar el código de la aplicación completa y funcional en (Github): Reproducción de sonido en un ciclo infinito.

Conclusión

En este capítulo hemos visto varias cosas sobre los servicios, estos son componentes que representan ciertas acciones que se ejecutaran durante un tiempo muy largo (o indefinido) por lo que funcionan en segundo plano (background). Para interactuar con los servicios es necesaria una actividad que lo inicie y detenga.