Desarrollo de Android Apps - Servicios

  • Jose Luis Navarro Jose Luis Navarro
  • hace 6 años
Desarrollo de Android Apps - Servicios

Desarrollo Android Apps - Servicios

En mi primer tutorial voy a hablar sobre algo bastante útil en Android: servicios. Gracias a este componente, vamos a poder ejecutar procesos en segundo plano sin necesidad de la interacción del usuario. Por lo tanto, mientras se hace un uso normal del smartphone, en nuestra aplicación vamos a poder estar leyendo la localización, obtener eventos del calendario, enviar una notificación cuando se cumpla cierta condición, ...

CREAR UN SERVICIO NUEVO

Si trabajamos con Android Studio, lo cual recomiendo, para crear un nuevo servicio simplemente tendremos que hacer clic derecho -> New -> Service -> Service.

ServiciosI

 Crear un servicio nuevo en Android Studio

De esta forma, el servicio se declarará de forma atuomática en el manifest, y se creará automáticamente la clase que hereda de Service.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jlnavarro.services" >

    <application
        android:allowBackup="true"       
        android:label="@string/app_name"
                .
                .
                .

        <service
            android:name="com.jlnavarro.services.MyService"
            android:enabled="true"
            android:exported="true" >
        </service>    
   
    </application>

</manifest>

 Servicio declarado en el manifest

public class MyService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

 Clase MyService que hereda de Service

En caso de trabajar con Eclipse, tendremos que crear una clase nueva y hacer esto manualmente.

INICIAR Y DETENER UN SERVICIO

Desde una actividad podemos iniciar o detener un servicio con los métodos startService() stopService() respectivamente.

startService(new Intent(MyActivity.this, MyService.class));
stopService(new Intent(MyActivity.this, MyService.class));

Métodos para iniciar o detener un servicio

FUNCIONAMIENTO DE UN SERVICIO

Si nos fijamos en el servicio MyService anteriormente creado, apreciamos que existen 4 métodos.

Al iniciar un servicio, en primer lugar se ejecutará el método onCreate(). Posteriormente, se invoca el método onStartCommand(Intent, int, int), que recibe el Intent proporcionado por la actividad. En caso de detener el servicio, se llamará al método onDestroy(). Por último, el método onBind() se emplea para la comunicación entre procesos.

EJEMPLO DE APLICACIÓN

Con el objetivo de comprobar el funcionamiento del servicio creado, vamos a hacer una App muy simple que nos permita activar y desactivar el servicio. Para dotar de alguna funcionalidad a nuestro servicio, haremos que nos muestre la hora actual cada 5 segundos en una Toast.

Lo primero que vamos a hacer es agregar en el layout de la actividad principal un par de botones con los que podamos activar y desactivar el servicio.

ServiciosII

Layout de la App

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="@string/textDescription"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp" />

    <Button
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:text="@string/buttonOn"
        android:id="@+id/buttonOn"
        android:layout_marginTop="50dp"
        android:layout_below="@+id/textView"
        android:layout_alignLeft="@+id/buttonOff"
        android:layout_alignStart="@+id/buttonOff" />

    <Button
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:text="@string/buttonOff"
        android:id="@+id/buttonOff"
        android:layout_below="@+id/buttonOn"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp" />

</RelativeLayout>

 Código del layout

A continuación, desde la actividad principal, iniciaremos o detendremos el servicio dependiendo de si pulsemos el botón On Off.

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.buttonOn).setOnClickListener(mClickListener);
        findViewById(R.id.buttonOff).setOnClickListener(mClickListener);
    }

    View.OnClickListener mClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.buttonOn:
                    // Start Service
                    startService(new Intent(MainActivity.this, MyService.class));
                    break;
                case R.id.buttonOff:
                    // Stop Service
                    stopService(new Intent(MainActivity.this, MyService.class));
                    break;
            }
        }
    };
}

 Código de la Actividad Principal

Para terminar, definimos un AsyncTask (para más información sobre los AsyncTask, podéis consultar este post) en el servicio anteriormente creado. Desde aquí obtendremos la hora actual cada 5 segundos y la mostraremos con una Toast. En el método onStartCommand() se ejecutará el AsyncTask y en el onDestroy() se cancelará.

public class MyService extends Service {

    MyTask myTask;

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this, "Servicio creado!", Toast.LENGTH_SHORT).show();
        myTask = new MyTask();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        myTask.execute();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "Servicio destruído!", Toast.LENGTH_SHORT).show();
        myTask.cancel(true);
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private class MyTask extends AsyncTask<String, String, String> {

        private DateFormat dateFormat;
        private String date;
        private boolean cent;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dateFormat = new SimpleDateFormat("HH:mm:ss");
            cent = true;
        }

        @Override
        protected String doInBackground(String... params) {
            while (cent){
                date = dateFormat.format(new Date());
                try {
                    publishProgress(date);
                    // Stop 5s
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            Toast.makeText(getApplicationContext(), "Hora actual: " + values[0], Toast.LENGTH_SHORT).show();
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            cent = false;
        }
    }
}

 Código del Servicio

Dentro de la aplicación, si pulsamos el botón On, observaremos que se muestra la hora actual aunque salgamos de la aplicación. Esto no parará de ejecutarse hasta que volvamos a la aplicación y pulsemos el botón de desactivar el servicio.

Hasta aquí una breve explicación de cómo utilizar servicios en Android, y si tenéis alguna duda, no dudéis en preguntar!

Un saludo!

¿Qué opinas?