Un Service
est un
composant d'application qui peut effectuer
des opérations de longue durée en arrière-plan. Il ne fournit pas d'interface utilisateur. Une fois
démarré, un service peut continuer à fonctionner pendant un certain temps, même après que l'utilisateur est passé à un autre
application. De plus, un composant peut se lier à un service pour interagir avec lui et même effectuer
la communication inter-processus (IPC). Par exemple, un service peut gérer des transactions réseau, lire
de la musique, effectuer des E/S de fichiers ou interagir avec un fournisseur de contenu, le tout en arrière-plan.
Attention:Un service s'exécute dans le thread principal de son hébergement processus ; le service ne crée pas son propre thread et ne peut pas s'exécuter dans un processus distinct, sauf indication contraire. Vous devez exécuter toutes les opérations bloquantes sur un thread distinct au sein du service pour éviter qu'une application Erreurs ANR (Pas de réponse).
Types de services
Voici les trois différents types de services:
- Premier plan
-
Un service de premier plan effectue une opération visible pour utilisateur. Par exemple, une application audio utilise un service de premier plan pour lire la piste audio. Les services de premier plan doivent afficher une notification. Les services de premier plan continuent de s'exécuter même lorsque l'utilisateur n'interagit pas avec l'application.
Lorsque vous utilisez un service de premier plan, vous devez afficher une notification pour que les utilisateurs savent activement que le service est en cours d'exécution. Cette notification ne peut pas peuvent être ignorées, sauf si le service est soit arrêté, soit supprimé au premier plan.
En savoir plus sur la configuration services de premier plan dans votre l'application.
Remarque:La L'API WorkManager offre un moyen flexible de planifier des tâches et est capable de exécuter ces tâches en tant que services de premier plan si nécessaire. Dans de nombreux cas, l'utilisation WorkManager est préférable à l'utilisation directe de services de premier plan.
- Arrière-plan
- Un service d'arrière-plan effectue une opération qui n'est pas directement remarquée par
l'utilisateur. Par exemple, si une application utilise un service
pour compacter son espace de stockage,
il s'agit généralement
d'un service d'arrière-plan.
Remarque:Si votre application cible le niveau d'API 26 ou supérieur, le système impose des restrictions sur l'exécution en arrière-plan. lorsque l'application n'est pas au premier plan. Dans la plupart des cas situations, par exemple, vous ne devez pas accéder aux informations de localisation ou un arrière-plan. À la place, planifier des tâches à l'aide de WorkManager
- Associé
- Un service est lié lorsqu'un composant d'application s'y lie en appelant
bindService()
. Un service lié offre un service client-serveur qui permet aux composants d'interagir avec le service, d'envoyer des requêtes, de recevoir des résultats, et même d'un processus à l'autre grâce à la communication inter-processus (IPC). Un service lié s'exécute uniquement tant qu'un autre composant d'application y est lié. Plusieurs composants peuvent être liés service en même temps, mais lorsqu'ils sont tous dissociés, le service est détruit.
Bien que cette documentation traite généralement
des services démarrés et liés séparément,
votre service peut fonctionner dans les deux sens : il peut être démarré (pour fonctionner indéfiniment) et autoriser
liée. Il s'agit simplement d'implémenter deux méthodes de rappel: onStartCommand()
pour autoriser les composants à le démarrer et onBind()
pour autoriser la liaison.
Que votre service soit démarré, lié ou les deux, tout composant d'application
peut utiliser le service (même à partir d'une application distincte) de la même manière que n'importe quel composant
une activité, en la démarrant par un Intent
. Vous pouvez toutefois déclarer
définir le service comme privé dans le fichier manifeste et bloquer l'accès d'autres applications.
Ce point est abordé plus en détail dans la section Déclarer le service dans le
fichier manifeste.
Choisir entre un service et un thread
Un service est simplement un composant qui peut s'exécuter en arrière-plan, même lorsque l'utilisateur avec votre application. Vous ne devez donc créer un service que s'il s'agit besoin.
Si vous devez effectuer des tâches en dehors de votre thread principal, mais uniquement lorsque l'utilisateur interagit
avec votre application, créez plutôt un nouveau thread dans le contexte d'une autre application
. Par exemple, si vous voulez écouter de la musique, mais uniquement lorsque votre activité est en cours d'exécution,
vous pouvez créer un fil de discussion dans onCreate()
,
commencez à l'exécuter dans onStart()
,
et arrêtez-le dans onStop()
.
Envisagez également d'utiliser des pools de threads et des exécuteurs à partir du package java.util.concurrent
ou les coroutines Kotlin,
Thread
. Consultez le
Exécution de threads sur Android pour en savoir plus
déplacer l'exécution vers des threads en arrière-plan.
N'oubliez pas que si vous utilisez un service, il s'exécute toujours dans le thread principal de votre application en par défaut. Vous devez donc toujours créer un thread dans le service s'il effectue des tâches intensives des opérations de blocage.
Principes de base
Pour créer un service, vous devez créer une sous-classe de Service
ou en utiliser une.
de ses sous-classes existantes. Dans votre implémentation, vous devez remplacer certaines méthodes de rappel qui
gérer les aspects clés du cycle de vie du service et fournir
un mécanisme qui permet aux composants de
au service, le cas échéant. Voici les méthodes de rappel les plus importantes
remplacement:
onStartCommand()
- Le système appelle cette méthode en appelant
startService()
lorsqu'un autre composant (tel qu'une activité) demande le démarrage du service. Lorsque cette méthode est exécutée, le service est démarré et peut s'exécuter dans en arrière-plan indéfiniment. Si vous mettez en œuvre cela, il est de votre responsabilité d'arrêter le service lorsque son travail est terminé en appelantstopSelf()
oustopService()
. Si vous souhaitez uniquement fournir une liaison, vous ne devez pas devez implémenter cette méthode. onBind()
- Le système appelle cette méthode en appelant
bindService()
lorsqu'un autre composant souhaite se lier au service (pour effectuer un RPC, par exemple). Dans votre implémentation de cette méthode, vous devez fournir une interface que les clients utiliser pour communiquer avec le service en renvoyant unIBinder
. Vous devez toujours mettre en œuvre cette méthode ; Toutefois, si vous ne voulez pas autoriser la liaison, vous devez renvoyer "null". onCreate()
- Le système appelle cette méthode pour effectuer des procédures de configuration ponctuelles lorsque le service est
créé initialement (avant d'appeler
onStartCommand()
ouonBind()
). Si le service est déjà en cours d'exécution, cette méthode n'est pas appelé. onDestroy()
- Le système appelle cette méthode lorsque le service n'est plus utilisé et est en cours de destruction. Votre service doit implémenter cela pour nettoyer toutes les ressources, telles que les threads, des écouteurs ou des récepteurs. Il s'agit du dernier appel que le service reçoit.
Si un composant démarre le service en appelant startService()
(ce qui entraîne un appel à onStartCommand()
), le service
continue de s'exécuter jusqu'à ce qu'elle s'arrête avec stopSelf()
ou une autre
l'arrête en appelant stopService()
.
Si un composant appelle
bindService()
pour créer le service et que onStartCommand()
n'est pas appelé, le service s'exécute
tant que le composant y est lié. Une fois le service dissocié
de tous ses clients,
le système le détruit.
Le système Android n'arrête un service que lorsque la mémoire est faible et qu'il doit récupérer le système
pour l'activité axée sur l'utilisateur. Si le service est lié à une activité dont le rôle
concentré, il est moins
susceptible de semer la mort ; si le service est déclaré pour s'exécuter au premier plan, il est rarement arrêté.
Si le service est en cours d'exécution et que son exécution est longue, le système baisse sa position
dans la liste des tâches en arrière-plan au fil du temps, et le service devient très sensible
arrêt : si votre service est démarré, vous devez le concevoir pour gérer correctement les redémarrages.
par le système. Si le système arrête votre service, il le redémarre dès que des ressources
disponible, mais cela dépend également de la valeur renvoyée par onStartCommand()
. Pour en savoir plus,
pour savoir quand le système peut détruire un service, consultez la page Processus et exécutions de threads
document.
Dans les sections suivantes, vous verrez comment créer
startService()
et
bindService()
et leur utilisation.
à partir d'autres composants d'application.
Déclarer un service dans le fichier manifeste
Vous devez déclarer tous les services dans le fichier manifeste, tout comme pour les activités et les autres composants.
Pour déclarer votre service, ajoutez un élément <service>
en tant qu'enfant du <application>
;
. Voici un exemple :
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
Voir l'élément <service>
pour en savoir plus sur la déclaration de votre service dans le fichier manifeste.
Vous pouvez inclure d'autres attributs dans l'élément <service>
pour
définir des propriétés telles que les autorisations requises pour démarrer le service et le processus
que le service doit exécuter. android:name
est le seul attribut obligatoire : il spécifie le nom de classe du service. Après
vous publiez votre application, ne modifiez pas son nom pour éviter toute interruption
du code, car il dépend d'intents explicites pour démarrer ou lier le service (consultez l'article de blog Things
Cela ne peut pas être modifié).
Attention: Pour vous assurer que votre application est sécurisée, utilisez toujours un
intent explicite lors du démarrage d'une Service
et ne déclarez pas de filtres d'intent pour
vos services. L'utilisation d'un intent implicite pour démarrer un service représente un risque de sécurité, car vous ne pouvez pas
être certain du service qui répond à l'intent, et l'utilisateur ne peut pas voir quel service
démarre. À partir d'Android 5.0 (niveau d'API 21), le système génère une exception si vous appelez
bindService()
avec un intent implicite.
Pour vous assurer que votre service n'est disponible que pour votre application, procédez comme suit :
y compris android:exported
et en le définissant sur false
. Cela empêche les autres applications de démarrer votre
même en utilisant un intent explicite.
Remarque:
Les utilisateurs peuvent voir les services en cours d'exécution sur leur appareil. S'ils voient
un service qu’ils ne reconnaissent pas
ou ne font pas confiance, ils peuvent arrêter le service. Dans
pour éviter que votre service ne soit arrêté accidentellement par les utilisateurs, vous devez
pour ajouter
android:description
à la variable
<service>
dans le fichier manifeste de votre application. Dans la description,
Fournissez une courte phrase expliquant la fonction du service et ses avantages
qu'il fournit.
Créer un service démarré
Un service démarré est un service qu'un autre composant commence par appeler startService()
, ce qui entraîne un appel au service
onStartCommand()
.
Lorsqu'un service est démarré, son cycle de vie est indépendant du
qui l'a lancée. Le service peut s'exécuter en arrière-plan indéfiniment, même si
le composant qui l'a démarré est détruit. Le service doit donc s'arrêter
est terminée en appelant stopSelf()
, ou un autre composant peut
l'arrêter en appelant stopService()
.
Un composant d'application, tel qu'une activité, peut démarrer le service en appelant startService()
et en transmettant un Intent
.
spécifiant le service et incluant toutes les données que le service doit utiliser. Le service reçoit
cette Intent
dans la méthode onStartCommand()
.
Par exemple, supposons qu'une activité doive enregistrer des données dans une base de données en ligne. L'activité
peut démarrer un service associé et lui fournir les données à économiser en transmettant un intent à startService()
. Le service reçoit l'intent dans onStartCommand()
, se connecte à Internet et effectue l'action
transaction de base de données. Une fois la transaction terminée, le service s'arrête et
détruit.
Attention:Un service s'exécute dans le même processus que l'application. où elles sont déclarées et dans le thread principal de cette application par défaut. Si votre service effectue des opérations intensives ou bloquantes pendant que l'utilisateur interagit avec une activité du même application, le service ralentit les performances de l'activité. Pour éviter toute incidence sur l'application des performances, démarrez un nouveau thread dans le service.
La classe Service
est la classe de base
pour tous les services. Lorsque vous étendez cette classe, il est important de créer un nouveau fil de discussion dans lequel
le service peut terminer
tout son travail ; le service utilise le thread principal de votre application
par défaut, ce qui peut ralentir les performances de toute activité exécutée par votre application.
Le framework Android fournit également le IntentService
sous-classe de Service
qui utilise un
thread de travail pour gérer toutes les requêtes de démarrage, une par une. L'utilisation de cette classe n'est pas
recommandé pour les nouvelles applications. En effet, elle ne fonctionnera pas correctement à partir d'Android 8 Oreo, en raison de la
Introduction des limites d'exécution en arrière-plan.
De plus, elle sera obsolète à partir d'Android 11.
Vous pouvez utiliser JobIntentService
Remplacement de IntentService
, compatible avec les versions plus récentes d'Android.
Les sections suivantes décrivent comment implémenter votre propre service personnalisé, mais vous devez envisagez plutôt d'utiliser WorkManager pour la plupart des cas d'utilisation. Consultez le guide du traitement en arrière-plan sur Android. pour voir s'il existe une solution adaptée à vos besoins.
Étendre la classe Service
Vous pouvez étendre la classe Service
.
pour gérer chaque intent entrant. Voici à quoi pourrait ressembler une implémentation de base:
Kotlin
class HelloService : Service() { private var serviceLooper: Looper? = null private var serviceHandler: ServiceHandler? = null // Handler that receives messages from the thread private inner class ServiceHandler(looper: Looper) : Handler(looper) { override fun handleMessage(msg: Message) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000) } catch (e: InterruptedException) { // Restore interrupt status. Thread.currentThread().interrupt() } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1) } } override fun onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply { start() // Get the HandlerThread's Looper and use it for our Handler serviceLooper = looper serviceHandler = ServiceHandler(looper) } } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show() // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job serviceHandler?.obtainMessage()?.also { msg -> msg.arg1 = startId serviceHandler?.sendMessage(msg) } // If we get killed, after returning from here, restart return START_STICKY } override fun onBind(intent: Intent): IBinder? { // We don't provide binding, so return null return null } override fun onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show() } }
Java
public class HelloService extends Service { private Looper serviceLooper; private ServiceHandler serviceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000); } catch (InterruptedException e) { // Restore interrupt status. Thread.currentThread().interrupt(); } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work doesn't disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = serviceHandler.obtainMessage(); msg.arg1 = startId; serviceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
L'exemple de code gère tous les appels entrants dans onStartCommand()
et publie la tâche dans un Handler
exécuté sur un thread d'arrière-plan. Il fonctionne comme un IntentService
et traite toutes les requêtes les unes après les autres.
Vous pouvez modifier le code pour exécuter la tâche sur un pool de threads, par exemple si vous souhaitez exécuter plusieurs requêtes simultanément.
Notez que la méthode onStartCommand()
doit renvoyer une
entier. Le nombre entier est une valeur qui décrit la façon dont le système doit poursuivre le service
que le système le tue. La valeur renvoyée
de onStartCommand()
doit correspondre à l'un des éléments suivants :
constantes:
START_NOT_STICKY
- Si le système supprime le service après le retour de
onStartCommand()
, ne recréez pas le service, sauf s'il existe les intents à livrer. Il s'agit de l'option la plus sûre pour éviter d'exécuter votre service lorsque cela n'est pas nécessaire et quand votre application peut simplement redémarrer les tâches inachevées. START_STICKY
- Si le système arrête le service après le retour de
onStartCommand()
, recréez le service et appelezonStartCommand()
, mais ne renvoyez pas le dernier intent. À la place, le système appelleonStartCommand()
avec un un intent nul, sauf s'il existe des intents en attente pour démarrer le service. Dans ce cas, ces intents sont fournis. Ceci est adapté aux lecteurs multimédias (ou services similaires) qui ne sont pas des commandes en cours d'exécution, mais qui s'exécutent indéfiniment et attendent un job. START_REDELIVER_INTENT
- Si le système supprime le service après le retour de
onStartCommand()
, recréez-le et appelezonStartCommand()
avec le dernier intent transmis au Google Cloud. Tous les intents en attente sont transmis l'un après l'autre. Cela convient aux services l'exécution active d'une tâche qui doit reprendre immédiatement, telle que le téléchargement d'un fichier.
Pour en savoir plus sur ces valeurs renvoyées, consultez la documentation de référence pour chaque constante.
Démarrer un service
Vous pouvez démarrer un service à partir d'une activité ou d'un autre composant d'application
en transmettant un Intent
à startService()
ou startForegroundService()
. La
Le système Android appelle la méthode onStartCommand()
du service et lui transmet Intent
,
qui spécifie le service à démarrer.
Remarque: Si votre application cible le niveau d'API 26 ou supérieur, le système
impose des restrictions sur l'utilisation ou la création des services d'arrière-plan, sauf si l'application
se trouve au premier plan. Si une appli doit créer un service de premier plan,
l'application doit appeler startForegroundService()
. Cette méthode crée un service d'arrière-plan, mais
indique au système que le service va être promu
au premier plan. Une fois le service créé, il doit appeler sa méthode
startForeground()
dans
pendant cinq secondes.
Par exemple, une activité peut démarrer l'exemple de service de la section précédente (HelloService
) à l'aide d'un intent explicite avec startService()
, comme indiqué ci-dessous:
Kotlin
startService(Intent(this, HelloService::class.java))
Java
startService(new Intent(this, HelloService.class));
La méthode startService()
renvoie immédiatement un résultat.
le système Android appelle la méthode onStartCommand()
du service. Si le service n'est pas déjà en cours d'exécution, le système appelle d'abord onCreate()
, puis il appelle
onStartCommand()
Si le service ne fournit pas également de liaison, l'intent fourni avec startService()
est le seul mode de communication entre
le composant d'application et le service. Cependant, si vous souhaitez que
le service renvoie un résultat,
le client qui démarre le service peut créer un PendingIntent
pour une diffusion.
(avec getBroadcast()
) et le livrer au service
dans le Intent
qui démarre le service. Le service peut alors utiliser
diffuser pour fournir un résultat.
Plusieurs requêtes de démarrage du service entraînent plusieurs appels correspondants aux appels du service
onStartCommand()
Cependant, une seule demande d'arrêt
le service (avec stopSelf()
ou stopService()
) est requis pour l'arrêter.
Arrêter un service
Un service démarré doit gérer son propre cycle de vie. Autrement dit, le système
ne s'arrête pas ou
détruire le service, sauf s'il doit récupérer la mémoire système et le service
continue de s'exécuter après le retour de onStartCommand()
. La
service doit s'arrêter en appelant stopSelf()
ou un autre
peut l'arrêter en appelant stopService()
.
Une fois que vous avez demandé l'arrêt avec stopSelf()
ou stopService()
, le système détruit le service
possible.
Si votre service traite plusieurs requêtes simultanément vers onStartCommand()
, vous ne devez pas arrêter
lorsque vous avez terminé de traiter une requête de démarrage, car vous avez peut-être reçu une nouvelle
start request (l'arrêt à la fin de la première requête met fin à la seconde). Pour éviter
ce problème, vous pouvez utiliser stopSelf(int)
pour vous assurer que votre demande à
le service est toujours basé sur
la requête de démarrage la plus récente. Autrement dit, lorsque vous appelez stopSelf(int)
, vous transmettez l'ID de la requête de démarrage (startId
envoyé à onStartCommand()
) auquel votre demande d'interruption de service
correspond. Ensuite, si le service reçoit une nouvelle requête de démarrage avant que vous ne puissiez appeler stopSelf(int)
, l'ID ne correspond pas et le service ne s'arrête pas.
Attention:Pour éviter de gaspiller des ressources système et de consommer
de la batterie, assurez-vous que votre application
arrête ses services une fois qu'elle a fini de fonctionner.
Si nécessaire, d'autres composants peuvent arrêter le service en appelant stopService()
. Même si vous activez la liaison pour le service,
vous devez toujours arrêter le service vous-même s'il reçoit un appel vers onStartCommand()
.
Pour en savoir plus sur le cycle de vie d'un service, consultez la section ci-dessous sur la gestion du cycle de vie d'un service.
Créer un service lié
Un service lié est un service qui permet aux composants d'application de s'associer à celui-ci en appelant bindService()
pour créer une connexion à long terme.
Il n'autorise généralement pas les composants à le démarrer en appelant startService()
.
Créer un service lié lorsque vous souhaitez interagir avec celui-ci à partir d'activités et d'autres composants de votre application, ou pour exposer certaines fonctionnalités de votre application d'autres applications via la communication inter-processus (IPC).
Pour créer un service lié, implémentez la méthode de rappel onBind()
afin de renvoyer un IBinder
qui
définit l'interface de communication avec le service. D'autres composants d'application peuvent ensuite appeler
bindService()
pour récupérer l'interface et
commencer à appeler des méthodes sur le service. Le service ne réside que pour diffuser le composant d'application
est lié au service. Par conséquent, lorsqu'aucun composant n'est lié au service, le système le détruit.
Vous n'avez pas besoin d'arrêter un service lié comme vous le feriez lorsque le service
a commencé jusqu'au onStartCommand()
.
Pour créer un service lié, vous devez définir l'interface qui indique comment un client peut
communiquer avec le service. Cette interface entre le service
et un client doit être une implémentation de IBinder
. C'est ce que votre service doit faire
renvoyé par la méthode de rappel onBind()
. Une fois que le client a reçu l'IBinder
, il peut commencer
interagissant avec le service
via cette interface.
Plusieurs clients peuvent s'associer au service simultanément. Lorsqu'un client a fini d'interagir avec
le service, il appelle unbindService()
pour annuler la liaison.
Si aucun client n'est lié au service, le système le détruit.
Il existe plusieurs façons d'implémenter un service lié, plus compliqué qu'un service en cours de démarrage. C'est pourquoi la discussion sur le service lié apparaît dans un document distinct sur les services liés.
Envoyer des notifications à l'utilisateur
Lorsqu'un service est en cours d'exécution, il peut informer l'utilisateur d'événements à l'aide de notifications snackbar ou de notifications dans la barre d'état.
Une notification de snackbar est un message qui apparaît à la surface de la fenêtre actuelle pour une quelques instants avant de disparaître. Une notification de barre d'état contient une icône dans la barre d'état avec une que l'utilisateur peut sélectionner pour effectuer une action (par exemple, lancer une activité).
En général, une notification dans la barre d'état est la meilleure technique à utiliser lorsque des tâches en arrière-plan le téléchargement d’un fichier est terminé et l’utilisateur peut maintenant agir dessus. Lorsque l'utilisateur sélectionne la notification dans la vue développée, la notification peut lancer une activité (pour afficher le fichier téléchargé, par exemple).
Gérer le cycle de vie d'un service
Le cycle de vie d'un service est beaucoup plus simple que celui d'une activité. Cependant, il est encore plus il est important de porter une attention particulière à la façon dont votre service est créé et détruit, service peut s'exécuter en arrière-plan à l'insu de l'utilisateur.
Le cycle de vie d'un service, de sa création à sa destruction, peut suivre l'un des deux chemins suivants:
- Un service démarré
Le service est créé lorsqu'un autre composant appelle
startService()
. Le service fonctionne ensuite indéfiniment et doit s'arrêter en appelantstopSelf()
. Un autre composant peut également arrêter service en appelantstopService()
. Lorsque le service est arrêté, le système le détruit. - Un service lié
Le service est créé lorsqu'un autre composant (un client) appelle
bindService()
. Le client communique ensuite avec le service via une interfaceIBinder
. Le client peut fermer la connexion en appelantunbindService()
Plusieurs clients peuvent être liés à le même service et lorsqu'ils sont tous dissociés, le système le détruit. Le service n'a pas besoin de s'arrêter automatiquement.
Ces deux chemins ne sont pas entièrement distincts. Vous pouvez lier à un service qui est déjà
a commencé par startService()
. Par exemple, vous pouvez
démarrer un service de musique de fond en appelant startService()
avec un Intent
qui identifie la musique à lire. Plus tard,
Par exemple, lorsque l'utilisateur souhaite exercer un certain contrôle sur le lecteur ou obtenir des informations
titre actuel, une activité peut s'associer au service en appelant bindService()
. Dans ce cas, stopService()
ou stopSelf()
n'arrête pas réellement le service jusqu'à ce que tous les clients soient dissociés.
Implémenter les rappels de cycle de vie
Comme une activité, un service possède des méthodes de rappel de cycle de vie que vous pouvez implémenter pour surveiller les changements d'état du service et effectuer le travail aux moments appropriés. Le squelette suivant illustre chacune des méthodes du cycle de vie:
Kotlin
class ExampleService : Service() { private var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that bind private var allowRebind: Boolean = false // indicates whether onRebind should be used override funonCreate
() { // The service is being created } override funonStartCommand
(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return startMode } override funonBind
(intent: Intent): IBinder? { // A client is binding to the service with bindService() return binder } override funonUnbind
(intent: Intent): Boolean { // All clients have unbound with unbindService() return allowRebind } override funonRebind
(intent: Intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } override funonDestroy
() { // The service is no longer used and is being destroyed } }
Java
public class ExampleService extends Service { int startMode; // indicates how to behave if the service is killed IBinder binder; // interface for clients that bind boolean allowRebind; // indicates whether onRebind should be used @Override public voidonCreate
() { // The service is being created } @Override public intonStartCommand
(Intent intent, int flags, int startId) { // The service is starting, due to a call tostartService()
return startMode; } @Override public IBinderonBind
(Intent intent) { // A client is binding to the service withbindService()
return binder; } @Override public booleanonUnbind
(Intent intent) { // All clients have unbound withunbindService()
return allowRebind; } @Override public voidonRebind
(Intent intent) { // A client is binding to the service withbindService()
, // after onUnbind() has already been called } @Override public voidonDestroy
() { // The service is no longer used and is being destroyed } }
Remarque:Contrairement aux méthodes de rappel du cycle de vie d'une activité, ne sont pas nécessaires pour appeler l'implémentation de la super-classe de ces méthodes de rappel.
La figure 2 illustre les méthodes de rappel types pour un service. Bien que la figure sépare
services créés par startService()
à partir de ces
créé par bindService()
, conserver
à l'esprit que n'importe quel service, quelle que soit la façon dont il a été démarré, peut potentiellement permettre aux clients de s'y lier.
Un service initialement démarré avec onStartCommand()
(par un client appelant startService()
)
peut toujours recevoir un appel à onBind()
(lorsqu'un client appelle
bindService()
).
En mettant en œuvre ces méthodes, vous pouvez surveiller ces deux boucles imbriquées du réseau cycle de vie:
- La durée de vie complète d'un service se produit entre le moment où
onCreate()
est appelé et celui oùonDestroy()
renvoie. Comme une activité, un service effectue sa configuration initiale dansonCreate()
et libère toutes les ressources restantes dansonDestroy()
. Par exemple, un Le service de lecture de musique peut créer le thread dans lequel la musique est lue dansonCreate()
, puis l'arrêter dansonDestroy()
.Remarque:
onCreate()
etonDestroy()
sont appelées pour tous les services, que ce soit elles sont créées parstartService()
oubindService()
. - La durée de vie active d'un service commence par un appel à
onStartCommand()
ouonBind()
. Chaque méthode reçoit leIntent
qui a été transmis àstartService()
oubindService()
.Si le service est démarré, la durée de vie active se termine au moment où se termine (le service est toujours actif même après le retour de
onStartCommand()
). Si le service est lié, la durée de vie active se termine lorsqueonUnbind()
est renvoyé.
Remarque:Bien qu'un service démarré soit arrêté par un appel à
stopSelf()
ou stopService()
, il n'y a pas de rappel respectif pour la méthode
(il n'y a pas de rappel onStop()
). À moins que le service ne soit lié à un client,
le système le détruit lorsque le service est arrêté. onDestroy()
est le seul rappel reçu.
Pour en savoir plus sur la création d'un service fournissant une liaison, consultez le document Services liés.
qui contient davantage d'informations sur les onRebind()
.
de rappel de la section Gérer le cycle de vie
un service lié.