Les bases du service

 

Les services

Il existe deux types de services:

les services locaux: LocalService, lancés depuis une activité de l'application où se trouve le service

les services distants: RemoteService, lancés depuis une autre application

 

Cycle de de vie des services

Image non trouvée !

Schéma repris du site http://developer.android.com/guide/components/services.html

que l'on retrouve aussi sur http://www.tutorialspoint.com/android/android_services.htm en Anglais.

 

Nous détaillerons ensuite le déroulement de ce cycle...

 

Cycle de vie d'un service local

Comme les activités, les services locaux ont un cycle de vie:

onCreate(), appelée lorsque le processus du service est créé. Il est à noter qu'il n'existe qu'une seule instance d'un service, quelque soit le nombre de démarrage de ce service. (Donc la méthode ne sera appelée qu'une seule fois...). Permettra d'initialiser le service.

public void onDestroy() { ... }, qui est appelée lorsque le service doit s'arrêter.

public int onStartCommand(Intent intent, int flags, int startId), qui est appelé à chaque appel manuel via un autre processus.

En entrée:

intent: L'intention qui a été utilisée pour lancer la requète au service (pourra être null dans le cas d'une relance du service suite à un arrêt de celui-ci).
flags: Valeurs additionnel 0, START_FLAG_REDELIVERY, or START_FLAG_RETRY.
startId Un id unique attribué par le système lors de l'envoi de la requète, permettant de différencier les requètes.

En sortie:

Voir le paragraphe suivant !

Image non trouvée !Les services ont peu de chances d'être supprimés par le système suite à un manque de mémoire. Mais cela peut se produire, et d'autant plus que l'instance d'un service existe depuis longtemps dans le système. Problème, le système n'informe pas par appel à onDestroy() ou autre méthode que le service va être arrêté...Vous pouvez éviter ce risque en passant le service en avant plan. Mais encore faut-il que cela soit indispensable !

 

La classe service

Les services que vous allez créer pourront étendre la classe Service. Les méthodes qui seront utilisées sont:

public IBinder onBind(Intent arg0) { ... } Cette méthode va permettre à une activité d'accéder aux membres et méthodes du service.

Nous verrons plus tard, pour le moment, nous nous contenterons de retourner null.

public int onStartCommand(Intent intent, int flags, int startId) { ... }, qui est appelée lorsqu’un service est lancé

Image non trouvée !Il existait une méthode onStart(Intent intent, int startId). Celle-ci est dépréciée depuis l'API 5.

Image non trouvée !Contrairement aux acitivités, il ne sera pas nécessaire de faire un appel à super.

 

ANR

Image non trouvée !Un service s'exécute dans le thread principal (UI Thread) du processus qui l'a lancé. Il y a donc de gros risque d'ANR si vos traitements devaient prendre du temps !

Bien penser à lancer ces traitements dans un autre thread !

 

Déclarer un service

Dans le fichier manifeste.xml, il suffit d'ajouter entre les balises applications:

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

ou MonService est la classe service développé.

 

Démarrer un service explicitement

Pour exécuter un service, nous pourrons utiliser la méthode startService().

Cette méthode fonctionne de manière similaire à startActivity():

Création d'une intention pour faire un appel explicite:

Intent(contexte d'utilisation (l'instance de la classe Activity en cours), MonServiceActivity.class);

 

Stopper un service

Un service doit normalement exécuter des tâches qui ne durent pas éternellement dans le temps. Un service doit donc s'arrêter au bout d'un moment.

Pour arrêter un service, il faudra appeler la méthode stopService() depuis une activité ou stopSelf() si le service veut s'arrêter lui même.

Cette méthode aura besoin de l'intance de l’intention fournie lors de l’appel startService() correspondant.

 

Passage d'informations

Généralement pour ne pas dire tout le temps, un service aura besoin de communiquer pour effectuer un traitement.

Comme nous passons par des intentions pour lancer un service, le principe de passage d'informations sera exactement le même que pour les activités: Utilisation des extras ou des datas.

 

Exemple

Voici un exemple qui ne fait pas grand chose pour le moment !

Tout d'abord le code du service:

Image non trouvée !Rappel, les run super ne sont pas à mettre dans un service contrairement à une activité (donc @override non plus...).

 

Le fichier AndroidManifest.xml

Et une activité pour tester (Partez sur la création d'un helloworld" pour avoir tout le reste généré...)

Voilà, ce n'est pas difficile, mais en même temps, nous n'avons pas fait grand chose !

 

Priorité d'un service

En cas de manque de mémoires, ou si le système considère qu'un service est resté trop longtemps en mémoire, celui-ci sera tué. Cela peut durer longtemps, mais cela arrivera. Vous obtenez alors un message de type toast indiquant que votre application s'est arrêtée.

Pour éviter ce phénomène, il est possible de passer le service en avant plan. Dans ce cas, le système considère que le service est actuellement utilisé par l'utilisateur. Il ne fera donc quasiement jamais parti des programmes à tuer par manque de mémoire.

La méthode à utiliser est la suivante:

final void startForeground(int id, Notification notification)

Vous devez indiquer à l'utilisateur que votre service tourne en avant plan via une notification.

id est l'identifiant de la notification (similaire à celui que vous positionnez pour envoyer une notification).

notification la notification...

Pour replacer le service en arrière plan, utilisez la méthode stopForeground(boolean removeNotification)

avec removeNotification à true pour demander de retirer la notification qui avait était envoyée par startForeground(). A faux, la notification ne disparaîtra que lors d'un prochain appel demandant à la retirer ou si le service est détruit.

 

onStartCommande

Voici les valeurs qu'il est possible de retourner au système. Ces valeurs permettent d'indiquer au système ce qu'il doit faire du service lorsque le traitement est terminé:

START_STICKY Lorsque le service vient à être tué, relancer le service puis relancer onStartCommande après le redémarrage du service. Il est à noter que intent passé en paramètre à onStartCommande sera à null.

START_NOT_STICKY lorsque le service est tué, le système ne cherchera pas à le relancer. Seul un prochain StartService() pourra le relancer.

START_REDELIVER_INTENT lorsque le service est tué, celui-ci redémarrera si un StartService est fait, ou si le service n'a pas pu faire un StopSelf lui-même, ce qui signifie alors que les traitements en cours pour un intent ne se sont pas terminé comme il faut. Dans ce cas, intent passé en paramètre à onStartCommande sera repositionné à la valeur qu'il avait vant l'arrêt.