dans le manifeste de votre application pour vous assurer que le service est nécessaire / utile. Veuillez expliquer en une courte phrase. font> td> table>
Si vous souhaitez gérer le cycle de vie du service plus en détail> https://developer.android.com/guide/components/services#Lifecycle
~~ Si vous voulez laisser une ambiguïté sur le service à démarrer, définissez un filtre d'intention pour le service, excluez le nom du composant de l'intention, puis setPackage (pour effacer l'ambiguïté du service cible) Vous devez définir le package Intent avec)
. ~~
Générer le service demandé
** Quel est le service demandé: **
Le service a demandé à être généré par un autre composant appelant startService () et utilisant la méthode onStartCommand ().
Lorsqu'un service est démarré, il a son propre cycle de vie, indépendant du composant appelant.
Le service s'exécute indéfiniment en arrière-plan même si le composant appelant est détruit. Ainsi, lorsque le processus est terminé, soit stopSelf () </ font> provoquera l'arrêt du Service, ou stopService () </ font> sera utilisé. Mettre fin au service du composant de.
Les composants d'application tels que les activités peuvent démarrer un service en appelant startService () </ font> et en transmettant Intent </ font>. Intent spécifie le service à démarrer </ font> et transmet les données utilisées par ce service. Le service reçoit cette intention avec la méthode onStartCommand () </ font>.
Par exemple, supposons qu'une activité stocke des données dans une base de données en ligne. L'activité démarre un service compagnon et transmet une intention à startService () afin qu'elle puisse fournir les données qu'elle stocke.
Le service reçoit l'intention par onStartCommand () </ font> et exécute le traitement de la base de données sur Internet. Lorsque le processus est terminé, le service se termine et le service est détruit.
COUTION:
Le service s'exécute dans le même processus que l'application déclarée et, par défaut, s'exécute dans le thread principal de cette application.
Si le Service s'exécute de manière intensive ou effectue une opération de blocage pendant que l'utilisateur travaille sur l'activité de la même application, les performances de l'activité seront dégradées.
Pour éviter la dégradation des performances, créez un nouveau thread dans le service et laissez-le traiter le thread.
|
Une classe extensible pour générer le service demandé
Service
Classe de base pour tous les services.
Le service utilise le thread principal de l'application par défaut, de sorte que le traitement du service peut ralentir les performances de l'activité.
Par conséquent, lors de l'extension de cette classe, il est important de créer un nouveau thread qui termine le processus de service.
IntentService
Une sous-classe de Service qui utilise un thread de travail qui traite toutes les demandes de génération de service une par une. Idéal lorsque le service n'a pas besoin de traiter plusieurs demandes de génération en même temps.
Simplement en implémentant onHandleIntent () </ font>, vous pouvez recevoir l'intention de chaque demande de génération et effectuer un traitement en arrière-plan.
Extension de la classe IntentService
Le service demandé peut être implémenté plus simplement en étendant la classe IntentService qu'en étendant la classe Service. </ font> La meilleure façon d'étendre la classe Service pour gérer les intentions est lorsque le service doit exécuter plusieurs threads (plutôt que de traiter les demandes de démarrage via la file d'attente de travail). est.
La plupart des services demandés pour démarrer n'ont pas besoin de traiter plusieurs demandes en même temps. Concevoir avec le multithreading est dangereux. Il est préférable d'implémenter le service à l'aide de la classe IntentService </ font>.
Fonctionnement de la classe IntentService </ font>.
--Créez un fil de discussion pour exécuter toutes les intentions fournies à onStartCommand () </ font>. Ce thread se sépare du thread principal de l'application.
--Créez une file d'attente de travail qui transmet les intentions un par un à onHandleIntent () </ font> afin que vous n'ayez pas à créer plusieurs threads.
- Vous n'avez pas besoin d'utiliser stopSelf () << / font> car cela arrêtera le service après avoir traité toutes les demandes de démarrage.
- onBind () </ font> est implémenté par défaut. Le onBind () implémenté renvoie null.
- onStartCommand () </ font> est implémenté par défaut. OnStartCommand () implémenté envoie une intention et un onHandleIntent () </ font> implémenté à la file d'attente de travail.
Implémentez onHandleIntent () </ font> pour terminer le travail demandé par le client, mais le service nécessite un constructeur.
<Référence> Exemple d'implémentation d'IntenService </ font>
public class HelloIntentService extends IntentService {
/**
* the super <code><a href="/reference/android/app/IntentService.html#IntentService(java.lang.String)">IntentService(String)</a></code>
*Appeler super dans le constructeur (obligatoire)
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
*IntentService est l'intention qui a démarré le service.
*Appelez cette méthode à partir du thread de travail par défaut.
*Lorsque cette méthode revient, IntentService arrête le service si nécessaire.
*/
@Override
protected void onHandleIntent(Intent intent) {
//Normalement, cette méthode fonctionne comme le téléchargement d'un fichier.
//Dans l'exemple, je code le processus pour qu'il veille pendant 5 secondes
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
C'est tout le traitement requis par IntentService (), comme l'implémentation et le constructeur de onHandleIntent () </ font>.
Si vous souhaitez remplacer d'autres méthodes de rappel telles que onCreate (), onStartCommend (), onDestory () </ font>, appelez la super-implémentation (implémentation parente). Gérez correctement le cycle de vie d'IntentService.
onStartCommand () </ font> renvoie l'implémentation par défaut d'une manière qui fournit des intentions à onHandleIntent () </ font>.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
Outre onHandleIntent () </ font>, onBind () </ font> est la seule méthode qui n'a pas besoin d'appeler la superclasse. Ces implémentations sont requises pour autoriser la liaison du service.
Extension de classe de service
Si vous devez exécuter le multithreading, étendez le service et utilisez chaque intention pour traiter la demande de démarrage au lieu de la traiter via la file d'attente de travail.
Le même traitement que le code d'IntentService ci-dessus est implémenté en étendant la classe Service ci-dessous. Pour chaque demande de démarrage, le thread de travail exécute les travaux, traite et traite une seule demande à la fois.
public class HelloService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
//Le gestionnaire reçoit un message du fil
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//Normalement, vous le faites ici, comme pour télécharger un fichier
//Voici un exemple de code qui dort pendant 5 secondes
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
//Lorsqu'il y a plusieurs demandes de traitement
//Arrêtez le service à l'aide de l'ID de démarrage
//Vous ne pouvez pas vous arrêter sans utiliser l'ID de départ
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
//Démarrez le thread qui exécute le service
//Traitement du service dans un thread séparé pour garantir les performances du thread principal
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
//Obtient le boucleur de thread pour la poignée et le transmet à la poignée.
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();
//Lorsque vous démarrez la demande, envoyez un message au processus que vous avez démarré et envoyez également l'ID de démarrage.
//Lorsque le processus est terminé, le travail à arrêter peut être confirmé par ID.
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
//Si le service est tué, revenez ici et redémarrez
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();
}
}
Puisque chaque appel à onStartCommand () </ font> est exécuté par le service lui-même, il est possible d'exécuter plusieurs requêtes en même temps. Si cela convient à votre situation, vous pouvez créer un nouveau thread pour chaque requête et l'exécuter immédiatement (pas besoin d'attendre que la requête précédente se termine).
La méthode onStartCommand () doit renvoyer un entier </ font>. Cet entier est une valeur qui indique comment continuer le service lorsque le système arrête le service (ci-dessous).
-
START_NOT_STICKY
-
Si le système tue le service après être revenu de onStartCommand () </ font>, le système ne redémarrera pas le service à moins qu'il y ait des intentions en attente de livraison. .. Il s'agit de l'option la plus sûre pour éviter d'exécuter des services indésirables si vous n'en avez pas besoin et que votre application peut reprendre des travaux incomplets.
-
START_STICKY
-
Si le système tue le service après être revenu de onStartComand () </ font>, recréez le service et onStartCommand () Appelle </ font> mais ne redistribue pas le dernier intent. Le système appelle à la place onStartCommand () </ font> avec une intention nulle, sauf si l'intention de déployer le service est en attente. S'il y a une intention en attente, cette intention sera livrée. Cela convient aux lecteurs multimédias (et aux services similaires) qui n'exécutent pas de commandes, mais s'exécutent indéfiniment et attendent les travaux.
-
START_REDELIVER_INTENT
-
Si le système tue le service après être revenu de onStartCommand () </ font>, recréez le service et <font avec la dernière intention livrée au service. Appelez color = "# 099"> onStartComannd () </ font>. Toutes les intentions en attente seront livrées en séquence. Cela convient aux services qui exécutent des processus tels que le téléchargement de fichiers et doivent être redémarrés immédiatement après la fin.
Début du service
Intent </ font> (spécifiez le service de démarrage) de l'activité ou d'un autre composant d'application, startService () </ font> ou <font color Passez-le à = "# 099"> startForegroundService () </ font> pour démarrer le service.
Le système Android appelle la méthode onStartCommand () du service et transmet l'intention. L'intention spécifie le service à démarrer.
Note:
Si l'application est API 26 ou version ultérieure et que l'application n'est pas au premier plan, le système impose des restrictions sur l'utilisation et la génération de services d'arrière-plan. Si vous souhaitez générer votre application avec ForegroundService, utilisez startForegroundService () strong> font>. Une fois qu'un service est créé, il doit appeler la méthode startForegroun () font> dans les 5 secondes.
|
<Référence>
Utilisation d'intention explicite dans startService ()
Exemple de code pour démarrer le service
Intent intent = new Intent(this,HelloService.class);
startService(intent);
La méthode startService () </ font> oblige le système Android à exécuter la méthode onStartCommand () </ font> du service. Si le service n'est pas déjà en cours d'exécution, le système exécute d'abord onCreate () </ font>, puis onStartCommand () </ font> > Est exécuté.
Lorsque le service ne fournit pas de liaison, l'intention fournie par startService () </ font> est le seul moyen de communication entre le composant d'application et le service.
Cependant, si le service renvoie un résultat, le client qui demande le service peut créer un PendingIntent </ font> pour la diffusion ( getBroadcast () < (Utilisez / font>), il peut être livré à Intent </ font> du Service demandé. Le Service peut ensuite utiliser la diffusion pour fournir les résultats.
S'il y a plusieurs demandes de service, plusieurs appels seront effectués à onStartCommand () </ font> pour les traiter, mais pour arrêter, Un seul # 099 "> stopSelf () </ font> ou stopService () </ font> est requis.
Aire d'autoroute
Après avoir démarré le service, gérez le cycle de vie du service. Après avoir exécuté onStartCommand () </ font>, le service fonctionnera indéfiniment et le système n'arrêtera ni ne détruira le service, sauf lors de la récupération de la mémoire système. Pour arrêter le service, le service lui-même exécute stopSelf () </ font> ou stopService () </ font> à partir d'un autre composant Courez et faites-le.
Une fois que stopSelf () </ font> ou stopService </ font> est exécuté, le système détruit immédiatement le service.
Lorsque le service traite plusieurs demandes à onStartCommand () </ font>, une demande s'arrête car toutes les autres demandes sont arrêtées par un seul arrêt de traitement. N'arrêtez pas le service lorsqu'il est terminé.
Utilisez stopSelf (int) pour arrêter le service qui gère plusieurs demandes. Cette méthode garantit que les demandes d'arrêt du service sont toujours basées sur la dernière demande de démarrage.
Plus précisément, stopSelf (int) </ font> transmet l'ID de la demande de démarrage en fonction de la demande que vous souhaitez arrêter (startId envoyé à onStartCommand ()). Si le service reçoit une nouvelle demande de démarrage avant que stopSelf (int) </ font> ne puisse être exécuté, l'ID de la demande de démarrage et l'ID de la fourniture d'arrêt ne correspondront pas, de sorte que Le service ne s'arrête pas.
COUTION:
Pour éviter de gaspiller les ressources du système et d'épuiser la batterie, arrêtez toujours le service lorsque l'application est terminée.
Si nécessaire, arrêtez le service en exécutant stopService () strong> à partir d'autres composants.
Si la liaison de service est activée et que le service s'exécute avec onStartCommand () strong>, utilisez stopSelf () pour arrêter le service lui-même. font> td> table>
Créer un service lié
La liaison à un service avec bindService () permet au composant d'application de se connecter pendant une longue période (généralement le service ne peut pas être démarré par le composant appelant starService ()).
Génère un service lié lorsqu'il répond aux activités d'une application, d'autres composants et services, ou fournit des fonctionnalités d'application à d'autres applications via une communication inter-processus.
Créer un service lié
--Implemented onBind () Renvoie IBinder qui définit l'interface de communication avec le service
--Appel du composant d'application bindService () Obtenir l'interface IBinder et commencer à appeler la méthode de service
Lorsqu'il n'y a plus de composants liés, le système détruit le service (le service lié n'a pas besoin d'être arrêté de la même manière qu'il a été démarré avec onStartCommand ()).
Pour générer un service lié, vous devez définir une interface. Cette interface spécifie comment communiquer avec le client et le service. L'interface responsable de la communication entre le client et le service doit implémenter IBinder </ font> et Servise appelle onBind () </ font>. Doit être un IBinder retourné par la méthode back. Une fois que le client reçoit l'IBilder, il peut faire fonctionner le service via l'interface.
Plusieurs clients peuvent se lier au service en même temps. Lorsqu'un client termine une opération de service, il exécute unbindService () </ font> pour le dissocier. S'il n'y a plus de clients à lier au service, le système détruira le service.
Il existe plusieurs façons d'implémenter un service lié, et cette implémentation est plus compliquée que le démarrage d'un service, alors consultez ce document pour plus d'informations> https://developer.android.com/guide/components/bound- services.html
Envoyer des notifications aux utilisateurs
Une fois que le service est opérationnel, vous pouvez notifier l'utilisateur avec une notification toast ou une notification de barre d'état. Une notification toast est un message qui apparaît à l'écran pendant un moment. Les notifications de la barre d'état affichent une icône avec un message dans la barre d'état. L'utilisateur peut choisir l'action à opérer à partir de la notification (comme le démarrage du service).
Les notifications de la barre d'état sont généralement la meilleure technique pour faire des choses en arrière-plan qui termineraient un téléchargement de fichier. Lorsque l'utilisateur sélectionne une notification dans la vue développée, l'activité peut être démarrée à partir de la notification (pour afficher le fichier téléchargé).
En savoir plus sur les notifications toast et les notifications de la barre d'état>
En savoir plus sur les notifications toast> https://developer.android.com/guide/topics/ui/notifiers/toasts.html
Plus de détails Notifications de la barre d'état> https://developer.android.com/guide/topics/ui/notifiers/notifications.html
Exécuter le service au premier plan
ForegroundService est un état dans lequel l'utilisateur peut reconnaître le service, donc même s'il manque de mémoire, il n'est pas candidat à l'arrêt forcé par le système. ForegroundService devrait vous avertir dans la barre d'état et apparaîtra sous la rubrique «En cours». La notification ne disparaîtra que si le service est arrêté ou supprimé du premier plan.
COUTION: Restrictions d'utilisation du service Foreground
ForegroundService n'est disponible que si vous savez que l'application est sur la bonne voie et que vous devez l'exécuter sans que l'utilisateur n'ait à interagir directement avec l'application.
ForegroundService définit l'importance des notifications et les affiche dans la barre d'état pour s'assurer que les utilisateurs savent ce que fait l'application.
Vous devez envisager d'utiliser le traitement planifié au lieu du service pour les actions qui ont la plus faible importance.
Les applications qui utilisent Service mettent une charge sur le système et consomment des ressources système. La définition de faible importance et le masquage des notifications peuvent nuire aux performances de l'application que l'utilisateur utilise, donc si vous souhaitez exécuter le service avec la plus faible importance, le bas du tiroir de notification Appelez l'application avec. font> (Est-il probable que la partie inférieure du tiroir de notification soit fermée de force pour des raisons système?) Font> font>
|
Les lecteurs de musique qui jouent de la musique sur le service doivent être configurés pour s'exécuter sur le premier plan afin que l'utilisateur reconnaisse explicitement l'exécution de l'application. Les notifications dans la barre d'état affichent la musique en cours de lecture ou utilisent le lecteur de musique pour activer toute activité. De même, les applications qui suivent le voyage d'un utilisateur nécessitent un service de premier plan qui suit l'emplacement de l'utilisateur.
Note:
Les applications utilisant Foreground Service sur Android 9 (API 28) ou version ultérieure nécessitent une autorisation FOREGROUND_SERVICE strong>. Il s'agit d'une autorisation normale, le système autorisera donc automatiquement l'application demandeuse.
Si vous créez un ForegroundService à l'API 28 ou une version antérieure sans demander FOREGROUND_SERVICE, le système lèvera une exception de sécurité.
|
Foreground Sercice
Le service Foreground doit afficher la notification et ne peut pas être rejeté sauf si le service est arrêté ou si le service est supprimé du premier plan.
Créer un service de premier plan
Exécutez startForeground (Id, notification)
・ Notification
· Intention
・ PendingIntent
・ Notification.setLatestEventInfo (this, title, text, PendingIntent)
・ StartForeground (Id, notification) </ font>
<Référence>
la nouvelle notification est actuellement obsolète. Utiliser notificationCompat
setLatestEventInfo est actuellement obsolète. Utilisons le constructeur
startForegroundService est API26 ou supérieur </ font>
Notification notification = new Notification(
R.drawable.icon,
getText(R.string.ticker_text),
System.currentTimeMillis()
);
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(
this,
getText(R.string.notification_title),
getText(R.string.notification_message),
pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
0 est NG pour l'ID transmis à startForeground () </ font>
Suppression de Foregourd Service
stopForeground()
・ Supprimer le service du premier plan
・ Nous acceptons également les valeurs booléennes qui indiquent s'il faut supprimer les notifications.
・ Le service ne s'arrête pas </ font>
Toutefois, si le service est toujours en cours d'exécution et arrêté au premier plan, la notification sera supprimée.
Gestion du cycle de vie de service
réduction
|