Les Services avec Android

Nous allons aujourd’hui découvrir la notion de Service Android et l’utiliser pour implémenter une application qui affichera un Toast (nous verrons ce qu’est un Toast par la suite) lorsque la position GPS du téléphone sera mise à jour.

Rappel : Qu’est-ce qu’un Service?

Un Service est un composant essentiel d’une application Android. Lorsque notre application souhaite effectuer des opération en tâche de fond (en dehors de l’interaction utilisateur), nous devrons utiliser des Services. Ainsi, contrairement à une Activity, un Service ne dispose pas d’une interface graphique. Il permet uniquement d’effectuer des opérations pendant que notre application (ou une autre application) tourne.

Notre player audio (lecteur de musique) permet d’écouter la musique tout en consultant nos emails, etc… Cette fonctionnalité n’est possible qu’à l’aide des Services.

Il existe deux types de services :

  • LocalService : services qui s’exécutent dans le même processus que votre application ;
  • RemoteService : ils s’exécutent dans des processus indépendants de votre application.

Cycle de vie d’un Service

Un service n’a pas de durée définie. Le service est là pour exécuter sa tâche et il fonctionnera tant que c’est nécessaire. On va présenter les différentes méthodes qui correspondent au cycle de vie d’un service. Ces méthodes seront à surcharger quand vous voudrez créer votre service :
  • onCreate() : cette méthode est appelée à la création du service et est en général utilisée pour initialiser ce qui sera nécessaire à votre service ;
  • onStart(Intent i) : le service démarre. Valable uniquement pour les versions du SDK inférieur à 2.0 ;
  • onStartCommand(Intent i, int flags, int startId) : le service démarre. Valable uniquement pour les versions du SDK supérieur à 2.0 ;
  • onDestroy() : appelé à la fermeture du service.

Voici alors ce cycle de vie sous forme de schéma :

Mise en place d’un Service

Nous allons alors mettre en place un service qui va nous permettre d’afficher nos coordonnées GPS dans un Toast chaque fois que celles-ci sont modifiées.

Création du projet

Comme dans le post précédent, nous allons créer un nouveau projet Android sous Eclipse. Ce projet s’appellera GPSTracker. Nous définirons le package suivant : com.yoannzimero.gpstracker et l’Activity suivante : HomeActivity lors du processus de création d’un projet sous Eclipse.

Création de l’Activity

Une fois le projet créé, nous allons créer notre Layout et compléter notre Activity, ce qui permettra de lancer notre service grâce à l’appui sur un bouton.

Nous allons alors créer le layout (fichier main.xml) :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

	<Button
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:text="@string/btn1"
	    android:id="@+id/serviceBtn" />

</LinearLayout>

On vient alors de créer un LinearLayout et d’y ajouter un bouton.

Nous allons alors compléter le fichier strings.xml pour ajouter la clé « btn1 » que nous venons de définir comme identifiant de notre bouton :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">GPSTracker</string>
    <string name="btn1">Lancer le service de geolocalisation</string>
</resources>

Nous allons ensuite compléter l’Activity que nous avons créé (HomeActivity.java) :

package com.yoannzimero.gpstracker;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class HomeActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// on utilisera alors le layout précédemment créé (main)
		setContentView(R.layout.main);

		// On récupère le bouton grâce à son identifiant
		Button serviceBtn = (Button) findViewById(R.id.serviceBtn);
		// On lui ajoute un listener qui permettra de lancer le
		// service lorsque l'on clickera sur le bouton
		serviceBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View actuelView) {
				startService(new Intent(HomeActivity.this,
						GPSTrackerService.class));
			}
		});
	}
}

Nous allons alors créer le Service GPSTrackerService que nous placerons dans le même package que l’Activity HomeActivity :

package com.yoannzimero.gpstracker;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.widget.Toast;

public class GPSTrackerService extends Service {

	private LocationManager locationMgr = null;
	private LocationListener onLocationChange = new LocationListener() {
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {	}

		@Override
		public void onProviderEnabled(String provider) { }

		@Override
		public void onProviderDisabled(String provider) { }

		// Au cours des changements de position GPS du téléphone,
		// on affichera sous forme de Toast les nouvelles
		// coordonnées GPS
		@Override
		public void onLocationChanged(Location location) {
			Double latitude = location.getLatitude();
			Double longitude = location.getLongitude();

			Toast.makeText(
					getBaseContext(),
					"Voici les coordonnées de votre téléphone : "
					+ latitude
					+ " " + longitude, Toast.LENGTH_LONG).show();
		}
	};

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public void onCreate() {
		locationMgr = (LocationManager) getSystemService(
				Context.LOCATION_SERVICE);

		// On récupère les coordonnées du téléphone toutes
		// les 10 secondes en utilisant le wifi pour
		// localiser le téléphone
		locationMgr.requestLocationUpdates(
				LocationManager.NETWORK_PROVIDER,
				10000, 0, onLocationChange);

		// On récupère les coordonnées du téléphone toutes
		// les 10 secondes en utilisant le GPS pour
		// localiser le téléphone
		locationMgr.requestLocationUpdates
				(LocationManager.GPS_PROVIDER,
				10000, 0, onLocationChange);
		super.onCreate();
	}

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

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

Il faudra alors déclarer le Service ainsi créé dans le fichier AndroidManifest.xml et il faudra également ajouter les permissions nécessaires pour exécuter le service de GeoLocalisation :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yoannzimero.gpstracker"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="7" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".HomeActivity"
            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=".GPSTrackerService"/>
    </application>

    <uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_GPS" />
	<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
	<uses-permission android:name="android.permission.LOCATION" />

</manifest>

Et voilà, vous avez terminé la réalisation de notre premier Service Android. Sachez que le service que nous venons de créer ne s’arrêtera pas, même lorsque l’application sera fermée. Il faudra l’arrêter manuellement dans Paramètres -> Applications -> Services en cours d’exécution et clicker sur GPSTrackerService.

Arrêt d’un Service à l’arrêt de l’application

Nous allons voir maintenant comment arrêter un Service Android lors de l’arrêt de l’application.

Pour cela, nous allons surcharger la méthode onBackPressed() de la HomeActivity :

	@Override
	public void onBackPressed() {
		// On affiche une pop-up avec 2 options : quitter l'application et annuler.
		final AlertDialog alertDialog = new AlertDialog.Builder(
				HomeActivity.this).create();
		alertDialog.setTitle("Fermer l'application");
		alertDialog.setMessage("Etes vous sûr de vouloir quitter l'application?");

		// Lorsque l'on clique sur quitter, on arrête le service et on quitte l'application
		alertDialog.setButton("quitter", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				stopService(new Intent(HomeActivity.this,
						GPSTrackerService.class));
				HomeActivity.super.onBackPressed();
			}
		});

		// Lorsque l'on clique sur annuler, on cache simplement la pop-up et on revient au HomeActivity
		alertDialog.setButton2("annuler", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				alertDialog.hide();
			}
		});

		alertDialog.show();
	}

Nous verrons alors dans l’article suivant, comment tester notre application sur un téléphone réel.