Crear Service en Android

Buenas tardes, en esta entrada y en las siguientes, vamos a enfocarnos sobre un aspecto importante de Android, los Services o Servicios.


Un Service es una aplicación en Android que se ejecuta en background sin tener que interactuar con el usuario. Por ejemplo, cuando usamos una aplicación, puede que queramos ejecutar algo de música en background a la vez. En este caso, el código que está ejecutando la música en background no necesita interactuar con el usuario, y por ello puede ejecutarse como un Service. Los Services son ideales tambien para situaciones en las cuales no tenemos que tener presente una UI para el usuario. Un buen ejemplo de este scenario es una aplicación que continuamente crea un log de coordenadas geográficas del dispositivo. En este caso podemos escribir un Service que haga algo en background.

Para comenzar, vamos a crear un Service, aunque lo único que haremos es crearlo y parar su ejecución, no hará ninguna función mas, pero aprenderemos a crearlo. En entradas posteriores veremos como podemos hacer que haga algo y ver mejor como funcionan.

Con esta pequeña introducción, vamos a ponernos manos a la obra:

  • Creación del Proyecto

    Para crear nuestro proyecto, vamos a pinchar en File -> New -> Android Application Project. En el caso de que la última opción no aparezca, podemos pinchar en “Other” con el cual nos aparecerá una ventana para elegir entre una lista. Para filtrar los resultados, podemos escribir “Android” en el cuadro de texto que encontraremos y así nos será mas fácil.

    Una vez se nos muestra la primera ventana del asistente, elegiremos un nombre para nuestro proyecto, yo en mi caso lo he llamado “EjemploService”, aunque no es importante y podeis poner el que querais. El resto de opciones podeis dejarlas como querais.

    A medida que avanzamos en el asistente vamos a encontrar una ventana donde se nos permitirá dar un nombre a nuestra Activity principal, yo en mi caso lo he llamado ServiceActivity, y su archivo layout se llama activity_service.xml. Este archivo layout se encuentra en la carpeta res/layoout, y en él definiremos la interfaz gráfica de nuestra Activity.

    Con esto, tendremos nuestro proyecto ya creado, y podemos continuar con la construcción de la aplicación.

  • ServiceActivity

    Una vez tenemos creado nuestro proyecto, tendremos nuestra clase Activity y su layout, ubicado como bien hemos especificado en la carpeta res/layout. Modificaremos su código para que quede como este:

    		<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    		    xmlns:tools="http://schemas.android.com/tools"
    		    android:layout_width="match_parent"
    		    android:layout_height="match_parent"
    		    android:orientation="vertical"
    		    tools:context=".ServiceACtivity" >
    		
    		    <Button
    		        android:id="@+id/btnStart"
    		        android:layout_width="fill_parent"
    		        android:layout_height="wrap_content"
    		        android:onClick="onClickComenzar"
    		        android:text="Comenzar Servicio" />
    		
    		    <Button
    		        android:id="@+id/btnStop"
    		        android:layout_width="fill_parent"
    		        android:layout_height="wrap_content"
    		        android:onClick="onClickParar"
    		        android:text="Parar Servicio" />
    		
    		</LinearLayout>
    		

    Podemos observar que tenemos 2 View del tipo Button, los cuales serán los encargados de comenzar el Service y de pararlo cuando deseemos. Hemos establecido valores en el atributo onClick, para luego crear métodos en la activity con el valor de estos atributos.

    Por otro lado, tenemos la clase ServiceActivity.java, cuya funcionalidad principal será comenzar el Service y pararlo cuando pulsemos el botón de detenerlo. Su código es el siguiente:

    		package com.example.services;
    
    		import android.app.Activity;
    		import android.content.Intent;
    		import android.os.Bundle;
    		import android.view.View;
    		
    		public class ServiceActivity extends Activity {
    		
    			@Override
    			protected void onCreate(Bundle savedInstanceState) {
    				super.onCreate(savedInstanceState);
    				setContentView(R.layout.activity_service);
    			}
    			
    			public void onClickComenzar(View v){
    				startService(new Intent(getBaseContext(), MyService.class));
    			}
    			
    			public void onClickParar(View v){
    				stopService(new Intent(getBaseContext(), MyService.class));
    			}
    		
    		}
    		

    El código de nuestra Activity es bastante simple, lo único que hacemos es crear los 2 métodos para que los botones tengan funcionalidad

    • public void onClickComenzar(View v)

      En este método llamamos a otro método, llamado startService, y como argumento le pasamos un Intent el cual recibe el context de nuestra aplicación, y la clase MyService.class, que será la que contenga el servicio (Aún no la hemos creado).

      				public void onClickComenzar(View v){
      					startService(new Intent(getBaseContext(), MyService.class));
      				}
      				
    • public void onClickParar(View v)

      En este otro método invocaremos el método stopService el cual acepta como argumento un Intent el cual hemos creado nuevo con el context de nuestra Activity y el nombre de la clase de nuestro Service (MyService.class), que como he dicho anteriormente aún no hemos creado, pero será el siguiente paso.

      				public void onClickParar(View v){
      					stopService(new Intent(getBaseContext(), MyService.class));
      				}
      				
  • MyService

    Ahora vamos a crear nuestra clase para el Service, la cuál heredará de la clase Service. Para ello nos dirigimos a nuestro package (com.example.services en mi caso) y crearemos una nueva clase en su interior.

    Una vez nuestra clase esté creada, vamos a modificarla para que quede como la siguiente:

    		package com.example.services;
    
    		import android.app.Service;
    		import android.content.Intent;
    		import android.os.IBinder;
    		import android.widget.Toast;
    		
    		public class MyService extends Service {
    		
    			@Override
    			public IBinder onBind(Intent arg0) {
    				// TODO Auto-generated method stub
    				return null;
    			}
    		
    			@Override
    			public int onStartCommand(Intent intent, int flags, int startId) {
    				// TODO Auto-generated method stub
    				Toast.makeText(this, "Servicio en Ejecucion", Toast.LENGTH_SHORT).show();
    				return START_STICKY;
    			}
    		
    			@Override
    			public void onDestroy() {
    				// TODO Auto-generated method stub
    				super.onDestroy();
    				Toast.makeText(this, "Servicio destruido", Toast.LENGTH_SHORT).show();
    			}
    		}
    		

    Vamos a explicar un poco los métodos que vemos:

    • onBind(Intent arg0)

      Vamos a ver su código:

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

      Este método permite ligar una actividad a un servicio. Esto permite a la activity tener acceso a los miembros y métodos en el interior del Service. Por ahora, retornamos null para este método ya que en esta entrada solo veremos como crearlo.

    • onStartCommand(Intent intent, int flags, int startID)

      Vamos a ver su código:

      				@Override
      				public int onStartCommand(Intent intent, int flags, int startId) {
      					// TODO Auto-generated method stub
      					Toast.makeText(this, "Servicio en Ejecucion", Toast.LENGTH_SHORT).show();
      					return START_STICKY;
      				}
      				

      Este método es llamado cuando hacemos que el servicio se ejecute explícitamente mediante un método startService(). Este método ejecutará todo el código que necesitemos que haga nuestro Service. Finalmente, retornamos la constante START_STICKY para que nuestro service siga ejecutandose hasta que lo detengamos explícitamente.

    • onDestroy()

      Vamos a ver su código:

      				@Override
      				public void onDestroy() {
      					// TODO Auto-generated method stub
      					super.onDestroy();
      					Toast.makeText(this, "Servicio destruido", Toast.LENGTH_SHORT).show();
      				}
      				

      Este método es llamado cuando el servicio es detenido usando el método stopService(), aquí es donde limpiamos los recursos que hayan sido usados por nuestro service.

  • AndroidManifest.xml

    Finalmente, para que nuestro Service puede usarse, tenemos que declararlo en el AndroidManifest de nuestra aplicación. A continuación vemos como se hace:

    		<?xml version="1.0" encoding="utf-8"?>
    		<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    		    package="com.example.services"
    		    android:versionCode="1"
    		    android:versionName="1.0" >
    		
    		    <uses-sdk
    		        android:minSdkVersion="8"
    		        android:targetSdkVersion="17" />
    		
    		    <application
    		        android:allowBackup="true"
    		        android:icon="@drawable/ic_launcher"
    		        android:label="@string/app_name"
    		        android:theme="@style/AppTheme" >
    		        <activity
    		            android:name="com.example.services.ServiceActivity"
    		            android:label="@string/app_name" >
    		            <intent-filter>
    		                <action android:name="android.intent.action.MAIN" />
    		
    		                <category android:name="android.intent.category.LAUNCHER" />
    		            </intent-filter>
    		        </activity>
    		        <service android:name=".MyService" />
    		    </application>
    		
    		</manifest>
    		

    Vemos que hemos agregado la línea:

    		 <service android:name=".MyService" />
    		

    Si quisieramos que nuestro service estuviera disponible para otras aplicaciones, podríamos añadir un action:

    		<service android:name=".MyService">
    			<intent-filter>
    				<action android:name="sekth.droid.Services.MyService" />	
    			</intent-filter>
    		</service>
    		

Con esto ya tendríamos nuestra aplicación funcional, podemos ejecutarla en el emulador y ver como funciona, aunque realmente no haga nada interesante.

Podemos ver unas capturas aunque tengan poco contenido:

Principal Service ejecucion Service Ajustes Service detenido

A continuación un video sobre la aplicación en tiempo real:



Con esta entrada, hemos visto la manera en la que podemos crear un Service en Android, aunque en este caso no haga naad mas que ocupar ram haciendo nada, pero en futuras entrada podemos ver un poco mas el enfoque que podemos darle para que haga diferentes tareas.

El código del ejemplo podeis descargarlo de aquí.

Sin más, cualquier aporte o corrección es bienvenido.

Saludos!!!

  • Eduardo

    Hola, muy buen ejemplo, me preguntaba como puedo hacer que un servicio se inicie al terminar de instalar mi app, o como puedo comprobar si mi servicio ya se inicio, para evitar iniciarlo otra vez o reiniciarlo.

    • Buenas Eduardo,

      Por lo que sé ejecutar un servicio nada mas instalar una aplicación no se puede. No estoy seguro al 100% pero creo que no se permite, como mínimo la aplicación debe de ser ejecutada por el usuario por primera vez para poder hacer este tipo de cosas, lo cual si es así lo veo totalmente lógico (Imagina que según instalas una aplicación sin abrirla, te consume todos los datos, sin saber la causa ni nada, el usuario desde luego al ver el consumo podría incluso desinstalarla).

      Por otro lado, para saber si un servicio de tu aplicación ha sido iniciado o está en ejecución, puedes usar el sistema interno de Android para saberlo.

      Hago referencia a este link de StackOverflow donde usando la clase ActivityManager y sus métodos para acceder a los servicios actualmente funcionando.

      Espero que esto te pueda servir de ayuda Eduardo.

      Saludos!!

  • jaime

    Muchas gracias, no sabia como detener mi proceso en background 😀 , nuevamente muchas gracias