Aller au contenu
Tous les articles

Les types de services au premier plan sur Android en 2026 : choisir celui auquel votre fonctionnalité correspond vraiment

Un guide pratique des restrictions de types de services au premier plan d'Android — dataSync, mediaPlayback, specialUse, shortService — et comment choisir le bon sans se faire tuer ou rejeter.

MFKAPPS 6 min de lecture

Démarrer un service au premier plan tenait autrefois en une ligne et une notification. Ce n’est plus le cas. Chaque service au premier plan, sur un SDK cible actuel, doit déclarer un type dans le manifeste, demander la permission correspondante, et dans quelques cas justifier sa propre existence auprès de Google avant que l’application ne sorte. Rien de tout cela n’est de la bureaucratie gratuite — chaque type porte une garantie de durée de vie différente, et choisir le mauvais type est la façon dont une fonctionnalité qui marchait très bien en test se fait tuer silencieusement sur un appareil réel des semaines plus tard. Voici comment choisir concrètement, en prenant comme exemple la décision qu’a dû prendre le minuteur de concentration de Mintly.

Pourquoi « démarrer simplement un service au premier plan » a cessé de fonctionner

L’ancien modèle était permissif : on appelait startForeground(), on affichait une notification, et le système vous laissait globalement tranquille tant que la notification restait visible. Cela a fait des services au premier plan un aimant à abus — un service de « synchronisation » qui ne synchronisait jamais rien, un service « d’écoute » qui ne faisait que maintenir le processus en vie. La réponse de la plateforme a été de lier chaque service au premier plan à un type déclaré, chacun avec sa propre permission et son propre contrat sur la durée pendant laquelle il peut tourner sans supervision. Vous ne pouvez plus dire « faites-moi confiance, c’est important ». Vous dites quel genre d’important, et le système applique le reste.

<service
    android:name=".timer.FocusSessionService"
    android:foregroundServiceType="specialUse"
    android:exported="false">
    <property
        android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
        android:value="active-focus-timer" />
</service>

Omettez la déclaration de type et le service ne démarrera tout simplement pas sur un SDK cible actuel — startForeground() lève une exception, il ne se contente pas d’avertir.

Les types qui correspondent vraiment à la plupart des fonctionnalités indie

La liste sélectionnée couvre des cas comme camera, microphone, location, phoneCall, mediaPlayback et connectedDevice — chacun étroitement délimité à ce que son nom suggère, chacun verrouillé par une permission qui correspond à la capacité réelle (FOREGROUND_SERVICE_CAMERA nécessite CAMERA, et ainsi de suite). Si votre fonctionnalité joue réellement de l’audio ou diffuse depuis un objet connecté, le type est évident et la permission est probablement une que vous détenez déjà.

Les deux types qui méritent d’être compris plus en profondeur sont ceux qui ne correspondent pas à un capteur unique : dataSync et specialUse.

dataSync est destiné à un transfert en arrière-plan avec une ligne d’arrivée claire — téléverser une sauvegarde, récupérer une mise à jour distante. Ce n’est pas un état de repos ; depuis Android 15, les services dataSync et mediaProcessing disposent d’un budget de temps d’exécution cumulé d’environ six heures sur une fenêtre glissante de 24 heures. Dépassez-le et le système appelle Service.onTimeout(), vous accordant une courte période de grâce pour terminer avant de forcer l’arrêt du service. C’est un compromis raisonnable pour ce à quoi le type est destiné — un transfert censé se terminer — et un mauvais choix pour tout ce qui est censé rester en place indéfiniment.

specialUse : le type pour tout ce qui n’est pas dans la liste

Un minuteur de concentration de 25 minutes n’est ni une synchronisation de données, ni de la lecture multimédia, ni lié à un capteur. C’est exactement le vide que specialUse existe pour combler — un service au premier plan qui est réellement limité dans le temps et initié par l’utilisateur, mais qui ne correspond à aucune des catégories nommées. Le piège, c’est qu’on ne peut pas simplement le déclarer et passer à autre chose : la balise <property> du manifeste exige une chaîne de sous-type décrivant ce que fait le service, et l’examen de l’application par Google Play lit cette chaîne. Déclarez specialUse pour quelque chose qui est en réalité une synchronisation de données déguisée ou un hack de maintien en vie, et c’est exactement le genre d’incohérence signalée pendant l’examen, pas après le lancement.

Pour Mintly, le sous-type est active-focus-timer, et le formulaire de déclaration de service au premier plan de la Play Console énonce la même chose en anglais simple : une session en cours que l’utilisateur a démarrée et regarde activement, se terminant à un moment précis. C’est un cas facile à justifier parce que c’est vrai. Écrire une description honnête d’une ligne de ce que fait le service est un temps mieux investi que d’essayer de trouver un type qui échappe à l’examen minutieux.

shortService : conçu pour la rafale, pas pour la session

L’autre type à connaître est shortService, destiné à un service au premier plan qui n’a besoin que de quelques minutes pour terminer quelque chose — écrire un export volumineux, exécuter un nettoyage ponctuel — moins de temps que les utilisateurs ne toléreraient le démarrage à froid d’un job accéléré WorkManager. Il vient avec un plafond de durée d’exécution strict d’environ trois minutes ; le système ne négocie pas au-delà, et le type existe précisément pour que le travail de courte durée cesse d’abuser de dataSync ou specialUse pour obtenir plus de latitude que nécessaire. Si votre tâche se termine de façon prévisible en moins de trois minutes, c’est le type honnête à utiliser. Si elle traîne parfois en longueur, ce n’est pas le bon, et vous le découvrirez en production, pas en test.

Se tromper de type est un bug de production, pas un avertissement de linter

Le type que vous déclarez n’est pas une métadonnée qu’Android ignore poliment si vous n’êtes pas sûr. Déclarez dataSync pour quelque chose qui tourne huit heures par jour, et le service se fait interrompre en pleine exécution — un état que votre application doit ensuite détecter et récupérer correctement, sinon l’utilisateur voit simplement une fonctionnalité bloquée sans explication. Déclarez specialUse sans sous-type honnête et l’examen de Play peut carrément rejeter la mise à jour, ce qui représente un retard de lancement bien pire que les dix minutes qu’il faut pour choisir le bon type dès le départ.

La décision se réduit à deux questions : ce service correspond-il à une capacité réelle comme camera ou mediaPlayback ? Sinon, le travail est-il naturellement borné en minutes (shortService), en heures avec une fin claire (dataSync), ou ouvert mais initié par l’utilisateur et activement suivi (specialUse, déclaré honnêtement) ? Répondez à ces questions avant d’écrire l’entrée du manifeste, pas après que le rapport de crash soit tombé. Le système de types est pénible à apprendre une fois, puis ce n’est plus qu’un fait sur la plateforme — de la même façon que les Live Updates d’Android 16 se posent sur le service de minuteur de Mintly sans remplacer le besoin de bien choisir son type de service au premier plan en premier lieu.