43 votes

Android O - L'ancien service de démarrage au premier plan fonctionne toujours ?

Ainsi, avec Android O, vous devez faire fonctionner votre service en tant que service de premier plan si vous voulez recevoir plus que quelques mises à jour de localisation par heure.

J'ai remarqué que l'ancienne méthode pour démarrer un service en avant-plan semble fonctionner sur O. c'est-à-dire

startForeground(NOTIFICATION_ID, getNotification());

Selon le guide des changements de comportement ici : https://developer.Android.com/preview/behavior-changes.html

La méthode NotificationManager.startServiceInForeground() démarre un service en avant-plan. L'ancienne méthode pour démarrer un service en avant-plan ne fonctionne plus.

Bien que la nouvelle méthode ne fonctionne qu'en ciblant O, il semble que l'ancienne méthode fonctionne toujours sur un appareil O, qu'il cible O ou non.

Modifier Y compris l'exemple :

Le projet d'exemple de Google, LocationUpdatesForegroundService, contient un exemple fonctionnel qui vous permet de constater le problème de visu. https://github.com/googlesamples/Android-play-location/tree/master/LocationUpdatesForegroundService

La méthode startForeground semble fonctionner sans problème, qu'elle soit ciblée et compilée par rapport au niveau 25 de l'API OU ciblée et compilée par rapport au niveau O (comme indiqué ici) : https://developer.Android.com/preview/migration.html#uya )

Donc, pour reproduire :

  1. Configurez l'application gradle comme mentionné dans le lien précédent.
  2. Ouvrez l'application
  3. Demander des mises à jour de l'emplacement
  4. Fermez l'application (soit par le bouton retour, soit par le bouton d'accueil).

Le service est en cours d'exécution au premier plan (indiqué par une icône dans l'ombre de notification). Les mises à jour de localisation arrivent comme prévu (toutes les 10 secondes), même sur un appareil fonctionnant sous O. Qu'est-ce que j'ai raté ?

1 votes

Mon interprétation de cette partie de la documentation est qu'en utilisant startServiceinForeground() est moins risqué, au cas où vous seriez en arrière-plan et sur le point de perdre la possibilité de lancer des services d'arrière-plan.

0 votes

D'après la lecture de la section developer.Android.com/preview/behavior-changes.html#abll Il est écrit que le démarrage d'un service au premier plan ne fonctionne pas du tout dans Android O (du moins lorsqu'on le cible). J'ai juste été surpris de voir que cela fonctionne malgré cette phrase dans la documentation. Donc, si une application conserve le SDK cible < 26 et s'assure de démarrer un service au premier plan en utilisant l'ancienne méthode startForeground(), tout devrait bien se passer ?

0 votes

Il vaut mieux que ça aille, sinon beaucoup d'applications vont se casser.

57voto

Bikram Pandit Points 744

Cela a marché pour moi.

  1. Dans la classe Activity, démarrez le service en utilisant startForegroundService() au lieu de startService()
    Intent myService = new Intent(this, MyService.class);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(myService);
    } else {
        startService(myService);
    }
  1. Maintenant, dans la classe Service de onStartCommand() faire comme suit
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    ......
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(text)
                .setAutoCancel(true);

        Notification notification = builder.build();
        startForeground(1, notification);

    } else {

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(text)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true);

        Notification notification = builder.build();

        startForeground(1, notification);
    }
    return START_NOT_STICKY;
}

Remarque : L'utilisation de Notification.Builder au lieu de NotificationCompat.Builder l'ont fait fonctionner. Ce n'est que dans Notification.Builder que vous devrez fournir l'ID du canal, qui est une nouvelle fonctionnalité d'Android Oreo.

J'espère que ça marchera !

1 votes

Il suffit de passer de NotificationCompat de la v7 à la v4 pour obtenir la méthode avec le paramètre ChannelId (import Android.support.v4.app.NotificationCompat ;) conformément à medium.com/google-developers/

0 votes

"Impossible de résoudre cette méthode". J'obtiens cette erreur lorsque j'utilise startForegroundService().

0 votes

@chetan vous devez utiliser startForegroundService() dans la classe Activity pour démarrer un service. Ne l'utilisez pas dans la classe de service

13voto

android developer Points 20939

Dans l'activité (ou tout contexte qui démarre le service de premier plan), appelez ceci :

Intent intent = new Intent(this, MyService.class)
ContextCompat.startForegroundService(context, intent);

Une fois que le service a démarré, créez un canal de notification en utilisant un code similaire à celui de l'opération suivante La documentation d'Android dit et ensuite créer une construction et l'utiliser :

final Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID).setSmallIcon(...)//
            .setPriority(...).setCategory(...).setContentTitle(...).setContentText(...).setTicker(...);
// and maybe other preparations to the notification...
startForeground(notificationId, builder.build());

0 votes

Merci, +1 pour ContextCompat.startForegroundService

0 votes

@the_new_mr Cette réponse devrait être marquée comme étant la bonne, car elle permet à Google de procéder à de futurs changements "en coulisses".

6voto

greywolf82 Points 3730

Habituellement, vous démarrez votre service à partir d'un récepteur de diffusion utilisant startService . Ils disent qu'il n'est plus possible (ou fiable) de téléphoner à la Commission européenne. startService parce qu'il y a maintenant des limitations de fond, donc vous devez appeler startServiceInForeground à la place. Cependant, la documentation ne précise pas vraiment quand cela se produit, car l'application est mise sur liste blanche lorsqu'elle reçoit une intention de diffusion, ce qui ne permet pas de savoir exactement à quel moment startService jette IllegalStateException .

1 votes

Oui, je suis d'accord pour dire que ce n'est pas clair et merci pour votre réponse. Le problème, c'est que lorsque j'ai essayé de démarrer un service et de le mettre au premier plan, il semblait toujours fonctionner, qu'il cible O ou non. C'est ce qui me fait me demander si je ne manque pas quelque chose. Je vais mettre à jour ma question pour y inclure un exemple (tiré des propres échantillons de code de Google, rien de moins).

0 votes

À mon avis, l'API fonctionne toujours, mais ils parlent du cas particulier où vous ne pouvez pas lancer un service à partir d'un récepteur et où votre application est en "état de cache".

0 votes

Je vois ce que vous voulez dire. Nous avons juste besoin de clarté sur le sujet. Ce qui est plus déroutant, c'est le fait que l'échantillon de code de Google fonctionne de la manière dont il est écrit sur un appareil O.

3voto

balendran Points 124

L'ancienne méthode de démarrage d'un service de premier plan fonctionne toujours lorsque l'application est au premier plan, mais la méthode recommandée pour démarrer un service de premier plan pour les applications ciblant le niveau 26 de l'API/Android O est d'utiliser la nouvelle méthode NotificationManager#startServiceInForeground pour créer un service de premier plan en premier lieu.

L'ancienne méthode consistant à lancer le service en arrière-plan puis à le promouvoir au premier plan ne fonctionnera pas si l'application est en mode arrière-plan, en raison des limitations d'exécution en arrière-plan d'Android O.

Le processus et les étapes de la migration sont documentés ici. https://developer.Android.com/preview/features/background.html#migration

9 votes

NotificationManager. startServiceInForeground a été supprimé. context.startForegroundService à sa place.

0 votes

Le service startService fonctionnera-t-il en arrière-plan si le service est déjà lancé et en cours d'exécution au premier plan ? Je l'utilise pour envoyer des informations à mon service

3voto

einsA Points 71

Comme l'a également mentionné @Kislingk dans un commentaire NotificationManager.startServiceInForeground a été supprimé. Il a été marqué comme obsolète par la directive commettre 08992ac .

Du message de livraison :

Plutôt que d'exiger qu'une notification a-priori soit fournie afin de service directement au premier plan, nous adoptons une opération composée en deux temps pour entreprendre un travail de service en cours, même à partir d'un état d'exécution en arrière-plan. état d'exécution en arrière-plan. Le Context#startForegroundService() n'est pas soumis à des restrictions d'arrière-plan, avec l'exigence que le service doit officiellement passer à l'état d'avant-plan via startForeground() dans un délai de 5 secondes. 5 secondes. Si le service ne le fait pas, il est arrêté par le système d'exploitation et l'application est blâmée avec un service ANR.

0 votes

StartServiceInForeground n'est même pas mentionné sur cette page.

0 votes

@Neo42 bien sûr vous devez regarder dans la classe NotificationManager pour trouver cette méthode ! Android.googlesource.com/platform/frameworks/base/+/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X