startForeground fail après la mise à jour vers Android 8.1 : solution en Kotlin

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Votre foreground service a « planté » après la mise à jour ? Vous n'êtes pas seul

\n

Imaginez : vous lancez votre application, elle doit fonctionner en arrière-plan en affichant une notification importante. Tout fonctionnait parfaitement sur Android 7.0, les utilisateurs sont satisfaits. Mais voilà que la mise à jour vers Android 8.1 sort — et l'application plante avec l'erreur mystérieuse startForeground fail. Cela vous dit quelque chose ? Si vous avez déjà rencontré ce problème, vous savez à quel point il peut déstabiliser. Sur Stack Overflow, cette question a recueilli des milliers de vues, ce qui signifie qu'elle a touché de nombreux développeurs. Dans cet article, nous allons analyser pourquoi cela se produit, comment corriger l'erreur en Kotlin et, surtout, comment l'éviter à l'avenir.

\n\n

Qu'est-ce que startForeground et à quoi sert-il ?

\n

Dans Android, un foreground service (service de premier plan) est un service qui effectue des actions visibles pour l'utilisateur. Par exemple, la lecture de musique, l'enregistrement d'un tracé GPS ou le téléchargement d'un fichier. Contrairement à un service classique, un foreground service doit afficher une notification permanente dans la barre d'état. Cela se fait via l'appel à startForeground(), qui prend un ID de notification et l'objet Notification lui-même.

\n

À partir d'Android 8.0 (API 26), Google a introduit des restrictions strictes sur les services en arrière-plan. Désormais, si vous essayez de lancer un foreground service sans une notification correctement configurée, le système lèvera une exception ForegroundServiceStartNotAllowedException ou ignorera simplement l'appel. Sous Android 8.1, ces restrictions sont devenues encore plus strictes, et l'erreur startForeground fail est devenue massive.

\n\n

Pourquoi l'erreur startForeground fail se produit-elle sous Android 8.1 ?

\n

La raison principale est l'absence ou la mauvaise configuration du canal de notification (Notification Channel). Avant Android 8.0, les notifications pouvaient être créées sans canaux. Après la mise à jour, Google a obligé les développeurs à créer au moins un canal pour chaque type de notification. Si vous appelez startForeground() avec une notification qui n'a pas de canal, le système ne sait tout simplement pas comment l'afficher et lève une erreur.

\n

La deuxième raison est un problème de timing. Vous devez appeler startForeground() dans les 5 premières secondes suivant le démarrage du service. Si vous ne le faites pas, le service sera tué et l'application peut planter.

\n

La troisième raison est la tentative de lancer le service depuis l'arrière-plan. À partir d'Android 8.0, il est interdit de lancer un foreground service depuis un contexte d'arrière-plan (par exemple, depuis un BroadcastReceiver ou un autre service). L'exception est uniquement si l'application est au premier plan.

\n\n

Comment corriger : guide étape par étape en Kotlin

\n

Réécrivons votre service pour qu'il fonctionne sous Android 8.1 et versions ultérieures. Nous utiliserons Kotlin, un langage moderne et concis.

\n\n

Étape 1 : Créez un canal de notification

\n

Le canal doit être créé avant d'afficher la notification. Le meilleur endroit est dans la méthode onCreate() de votre service ou dans la classe Application. Voici un exemple :

\n
class MyForegroundService : Service() {\n    companion object {\n        const val CHANNEL_ID = "my_foreground_channel"\n        const val NOTIFICATION_ID = 1\n    }\n\n    override fun onCreate() {\n        super.onCreate()\n        createNotificationChannel()\n    }\n\n    private fun createNotificationChannel() {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            val channel = NotificationChannel(\n                CHANNEL_ID,\n                "Foreground Service Channel",\n                NotificationManager.IMPORTANCE_LOW\n            ).apply {\n                description = "Channel for foreground service notifications"\n            }\n            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\n            notificationManager.createNotificationChannel(channel)\n        }\n    }\n}
\n

Notez que nous vérifions la version du SDK. Sur les anciens appareils, les canaux ne sont pas nécessaires, et

Blogs

Book Recommendations