Dans cet article, nous abordons un composant important du développement d'applications Android — Android Service. Contrairement à Activity, un Service s'exécute en arrière-plan dans Android. Un Service ne possède pas d'interface utilisateur et son cycle de vie est également différent de celui d'une Activity. À l'aide d'un Service, nous pouvons effectuer certaines opérations en arrière-plan, comme le chargement d'une page Web à partir d'un serveur distant. Nous pouvons utiliser un Service pour implémenter le multitâche dans Android.

Présentation du service Android

Nous savons que si les ressources système deviennent limitées, une Activity Android peut être démarrée, arrêtée, détruite, voire recréée. Un Service, en revanche, est conçu pour avoir un cycle de vie plus long. Un Service dans Android peut être démarré à partir d'une Activity, d'un récepteur Broadcast ou d'autres Services.

Il faut noter que l'utilisation d'un Service ne crée pas automatiquement un nouveau thread. Par conséquent, si nous voulons implémenter une logique simple dans un Service qui ne nécessite pas de traitement long, nous n'avons pas besoin de l'exécuter dans un thread séparé. Cependant, si nous devons implémenter une logique complexe qui prend beaucoup de temps à traiter, nous devons faire attention lors de la création de nouveaux threads ; sinon, comme le Service s'exécute sur le thread principal, cela peut provoquer des problèmes d'ANR (Application Not Responding).

Les principaux scénarios d'utilisation d'un Service dans Android sont les suivants :

  • Implémentation du multitâche (multi-tâche)
  • Communication inter-processus (IPC)

Un exemple typique du premier cas est lorsqu'une application doit télécharger des données depuis un serveur distant. Dans ce cas, vous pouvez utiliser une Activity qui interagit avec l'utilisateur, et démarrer un Service pendant que l'utilisateur utilise l'application, en le laissant terminer le travail en arrière-plan. Il existe également un scénario où le Service envoie des informations à l'utilisateur après avoir terminé sa tâche.

Dans le second cas, nous voulons « partager » une fonctionnalité commune afin que différentes applications puissent la réutiliser. Par exemple, supposons que nous ayons un Service capable d'envoyer des e-mails, et que nous voulions partager ce Service entre plusieurs applications afin de ne pas avoir à réécrire le même code. Dans ce cas, nous pouvons utiliser IPC pour que le Service expose une interface « distante » qui peut être appelée par d'autres applications.

Les bases des Services

Maintenant que nous en savons plus sur les Services, créons-en un. Pour créer un Service dans Android, nous devons hériter de la classe Service.

public class TestService extends Service {

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

}

Comme vous pouvez le voir, nous avons seulement implémenté une méthode appelée onBind. Dans l'exemple ci-dessus, nous avons utilisé un Service local, donc la méthode renvoie null. Comme mentionné précédemment, un Service a son propre cycle de vie, nous pouvons donc redéfinir certaines méthodes de rappel pour gérer ses différents états :

public class TestService extends Service {

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

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

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

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

}

La première méthode, onCreate, n'est appelée que lorsque le Service est créé. Si le Service est déjà en cours d'exécution, cette méthode ne sera pas appelée. Nous ne pouvons pas l'appeler directement ; c'est le système qui l'appelle.

La méthode onStartCommand est la méthode la plus importante car elle est appelée lorsque nous devons démarrer le Service. Dans cette méthode, l'Intent passé lors de l'exécution du Service nous est transmis, ce qui nous permet d'échanger certaines informations avec le Service. Dans cette méthode, nous implémentons notre propre logique : s'il ne s'agit pas d'une opération longue, elle peut être exécutée directement dans cette méthode ; sinon, un thread peut être créé. Comme vous pouvez le voir, cette méthode doit renvoyer une valeur entière. Cet entier représente la façon dont le système doit gérer le Service :

  • START_STICKY : avec cette valeur de retour, si le système tue notre Service, il sera recréé. Cependant, l'Intent qui avait été envoyé au Service ne sera pas retransmis. Ainsi, le Service continue de fonctionner.
  • START_NOT_STICKY : si le système tue le Service, il ne sera pas recréé, sauf si le client appelle explicitement la commande onStart.
  • START_REDELIVER_INTENT : fonctionne de manière similaire à START_STICKY. De plus, dans ce cas, l'Intent sera retransmis au Service.

onDestroy est une méthode appelée par le système lorsque le Service est sur le point d'être détruit.

Une fois que nous avons une classe Service personnalisée, nous devons la déclarer dans Manifest.xml afin de pouvoir l'utiliser.

<service android:name=".TestService"
         android:enabled="true"/>

Démarrer et arrêter un Service

Comme nous le savons, un Service est démarré puis finit par être arrêté, afin qu'il puisse accomplir sa tâche. Supposons que nous le démarrions depuis une Activity ; nous pouvons utiliser un Intent pour transmettre certaines informations au Service. Supposons que notre Activity possède deux boutons, un pour démarrer et un pour arrêter le Service :

btnStart.setOnClickListener(new View.OnClickListener() {
 
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        i.putExtra("name", "SurvivingwithAndroid");        
        MainActivity.this.startService(i);        
    }
});
 
btnStop.setOnClickListener(new View.OnClickListener() {
 
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        MainActivity.this.stopService(i);
    }
});

À la ligne 5 de l'exemple de code ci-dessus, nous créons un Intent qui transmet le nom de classe pour gérer notre Service, et nous définissons certains paramètres tels que name. Ensuite, à la ligne 7, nous démarrons ce Service. De la même manière, à la ligne 17, nous arrêtons ce Service.

android-service-tutorial-1

Lorsque vous cliquez sur le bouton de démarrage, vous obtenez le Log suivant :

android-service-tutorial-2

Vous pouvez remarquer que la méthode onCreate est appelée. Car c'est la première fois que nous démarrons ce Service. Si nous cliquons à nouveau sur le bouton de démarrage, le système n'appellera pas onCreate. Lorsque nous cliquons sur le bouton d'arrêt, le système détruit ce Service.

IntentService

Comme nous l'avons mentionné précédemment, un Service s'exécute sur le thread principal. Par conséquent, nous devons être très prudents lors de l'implémentation de la logique dans un Service. Considérez que si cette logique est une opération bloquante ou prend beaucoup de temps à se terminer, elle peut provoquer des problèmes d'ANR. Dans de tels cas, nous devons déplacer la logique vers un thread séparé. Cela signifie créer un thread dans la méthode onStartCommand, puis l'exécuter.

Une autre classe dérivée de Service, IntentService, peut simplifier notre développement. Cette classe est utile lorsque nous n'avons pas besoin de gérer plusieurs requêtes en même temps. Elle crée un thread de travail pour gérer différentes requêtes. Les opérations effectuées sont les suivantes :

  • Crée un thread séparé pour gérer les requêtes.
  • Crée une file d'attente de requêtes et lui transmet occasionnellement un Intent.
  • Crée une implémentation par défaut de onStartCommand.
  • Arrête le Service une fois que toutes les requêtes ont été exécutées.

Si nous voulons créer un IntentService, nous devons hériter de la classe IntentService au lieu de la classe Service :

public class TestIntentService extends IntentService {
 
    public TestIntentService() {
        super("TestIntentService");        
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
 
    }
 
}

Dans cet exemple, nous devons seulement implémenter la méthode onHandleIntent. La logique externe implémentée ici n'a pas besoin de se soucier de savoir si l'opération prend du temps, car cette méthode est appelée dans un thread séparé.

Démarrage automatique d'un Service

Bien souvent, nous voulons démarrer notre Service automatiquement, par exemple, le démarrer automatiquement au démarrage. Nous savons qu'un composant est nécessaire pour démarrer un Service. Alors, comment pouvons-nous le faire automatiquement ? Nous pouvons utiliser un broadcast receiver pour démarrer le Service. Par exemple, si nous voulons le démarrer lorsque le smartphone démarre, nous pouvons d'abord créer un broadcast receiver qui écoute cet événement (boot), puis démarrer le Service.

public class BootBroadcast extends BroadcastReceiver {

    @Override
    public void onReceive(Context ctx, Intent intent) {        
        ctx.startService(new Intent(ctx, TestService.class));

    }

}

Déclarez-le dans Manifest.xml :

<receiver android:name=".BootBroadcast">    
    <intent-filter >
        <action android:name="android.intent.action.BOOT_COMPLETED"/>                
    </intent-filter>
</receiver>

Source : http://www.importnew.com/9019.html