Context.startForegroundService () n’a alors pas appelé Service.startForeground ()

J’utilise la classe de Service sur le système d’exploitation Android.

Je prévois d’utiliser le Service en arrière-plan.

La recommandation Android stipule que startService doit utiliser startForegroundService.

Si vous utilisez startForegroundService, le Service Context.startForegroundService() un Context.startForegroundService() qui n’appelle pas alors l’erreur Service.startForeground() .

Qu’est-ce qui ne va pas avec ça?

Des changements de comportement de Google Documents sur Android 8.0 :

Le système permet aux applications d’appeler Context.startForegroundService () même lorsque l’application est en arrière-plan. Toutefois, l’application doit appeler la méthode startForeground () de ce service dans les cinq secondes suivant la création du service.

Solution: Appelez startForeground dans Oncreate () pour le service que vous utilisez Context.startForegroundService ().

Voir aussi: Limites d’exécution en arrière – plan pour Android 8.0 (Oreo)

J’ai appelé ContextCompat.startForegroundService(this, intent) pour démarrer le service puis

En service onCreate

  @Override public void onCreate() { super.onCreate(); if (Build.VERSION.SDK_INT >= 26) { Ssortingng CHANNEL_ID = "my_channel_01"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } } 

Votre application va planter si vous appelez Context.startForegroundService(...) , puis appelez Context.stopService(...) avant d’appeler Service.startForeground(...) .

J’ai un reproche clair à l’ adresse suivante : https://github.com/paulpv/ForegroundServiceAPI26/blob/repro/app/src/main/java/com/github/paulpv/foregroundserviceapi26/MainService.kt#L28

J’ai ouvert un bug à ce sujet: https://issuetracker.google.com/issues/76112072

Plusieurs bugs ont été ouverts et fermés. Won’t Fix.

J’espère que le mien avec des étapes de reprographie claires fera la coupe.

J’ai fait des recherches à ce sujet pendant quelques jours et j’ai obtenu la solution. Maintenant, dans Android O, vous pouvez définir la limitation de l’arrière-plan comme ci-dessous

Le service qui appelle une classe de service

 Intent serviceIntent = new Intent(SettingActivity.this,DetectedService.class); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){ SettingActivity.this.startForegroundService(serviceIntent); }else{ startService(serviceIntent); } 

et la classe de service devrait être comme

 public class DetectedService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public void onCreate() { super.onCreate(); int NOTIFICATION_ID = (int) (System.currentTimeMillis()%10000); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForeground(NOTIFICATION_ID, new Notification.Builder(this).build()); } // Do whatever you want to do here } } 

Pourquoi ce problème est-il dû au fait que le framework Android ne peut pas garantir que votre service démarre dans les 5 secondes mais que le cadre ne limite pas la notification de premier plan dans les 5 secondes, sans vérifier si le framework a essayé de démarrer le service .

Ceci est sans aucun doute un problème de cadre, mais tous les développeurs confrontés à ce problème ne font pas tout leur possible:

  1. startForeground Une notification doit être à la fois sur onCreate et onStartCommand, car si votre service est déjà créé et que votre activité essaie de le redémarrer, onCreate ne sera pas appelé.

  2. ID de notification ne doit pas être 0 sinon le même plantage se produira même si ce n’est pas la même raison.

  3. stopSelf ne doit pas être appelé avant startForeground.

Avec tout ce qui précède 3, ce problème peut être un peu réduit mais toujours pas une solution, le vrai correctif ou disons que la solution de contournement consiste à rétrograder votre version cible de SDK à 25.

Et notez que très probablement Android P portera toujours ce problème parce que Google refuse même de comprendre ce qui se passe et ne croit pas que ce soit leur faute, lisez # 36 ici: https://issuetracker.google.com/issues/76112072 .

https://developer.android.com/reference/android/content/Context.html#startForegroundService(android.content.Intent)

Semblable à startService (Intent), mais avec une promesse implicite que le service appellera startForeground (int, android.app.Notification) une fois qu’il commence à s’exécuter. Pour ce faire, le service se voit atsortingbuer une durée comparable à l’intervalle ANR, sinon le système arrête automatiquement le service et déclare l’application ANR.

Contrairement à startService (Intent) ordinaire, cette méthode peut être utilisée à tout moment, que l’application hébergeant le service se trouve ou non dans un état de premier plan.

assurez-vous d’appeler le Service.startForeground(int, android.app.Notification) sur le onCreate () pour vous assurer qu’il sera appelé .. si vous avez des conditions qui pourraient vous empêcher de le faire, alors vous feriez mieux de en utilisant le Context.startService(Intent) normal et appelez le Service.startForeground(int, android.app.Notification) vous-même.

Il semble que le Context.startForegroundService() ajoute un chien de garde pour vous assurer que vous avez appelé le Service.startForeground(int, android.app.Notification) avant sa destruction …

Juste un coup de tête alors que je perdais beaucoup d’heures là-dessus. J’ai continué à obtenir cette exception même si startForeground(..) comme première chose dans onCreate(..) . En fin de compte, j’ai constaté que le problème était dû à l’utilisation de NOTIFICATION_ID = 0 . Utiliser une autre valeur semble résoudre ce problème.

Problème avec Android O API 26

Si vous arrêtez le service tout de suite (de sorte que votre service ne fonctionne pas vraiment (libellé / compréhension) et que vous respectez l’intervalle ANR, vous devez quand même appeler startForeground avant d’arrêter

https://plus.google.com/116630648530850689477/posts/L2rn4T6SAJ5

Essayé cette approche Mais cela crée toujours une erreur: –

 if (Util.SDK_INT > 26) { mContext.startForegroundService(playIntent); } else { mContext.startService(playIntent); } 

J’utilise ceci jusqu’à ce que l’erreur soit résolue

 mContext.startService(playIntent); 

Je suis confronté au même problème et après avoir passé du temps à trouver des solutions que vous pouvez essayer sous le code. Si votre Service utilise alors ce code dans onCreate else, vous utilisez Intent Service puis placez ce code dans onHandleIntent.

 if (Build.VERSION.SDK_INT >= 26) { Ssortingng CHANNEL_ID = "my_app"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "MyApp", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } 

Cette erreur se produit également sur Android 8+ lorsque Service.startForeground (int id, notification notification) est appelé alors que id est défini sur 0.

id int: Identifiant de cette notification selon NotificationManager.notify (int, Notification); ne doit pas être 0 .

Tant de personnes ont répondu mais aucune n’a fonctionné dans mon cas.

J’ai commencé le service comme ça.

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(intent); } else { startService(intent); } 

Et dans mon service dans onStartCommand

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID) .setContentTitle(getSsortingng(R.ssortingng.app_name)) .setContentText("SmartTracker Running") .setAutoCancel(true); Notification notification = builder.build(); startForeground(NOTIFICATION_ID, notification); } else { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setContentTitle(getSsortingng(R.ssortingng.app_name)) .setContentText("SmartTracker is Running...") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setAutoCancel(true); Notification notification = builder.build(); startForeground(NOTIFICATION_ID, notification); } 

Et n’oublie pas de définir NOTIFICATION_ID non nul

finale statique privée Ssortingng ANDROID_CHANNEL_ID = “com.xxxx.Location.Channel”; final statique final int NOTIFICATION_ID = 555;

Donc, tout était parfait, mais toujours sur 8.1, la cause était la suivante.

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { stopForeground(true); } else { stopForeground(true); } 

J’ai appelé stop avant plan avec suppression de notification, mais une fois la notification de service supprimée, le service d’arrière-plan devient impossible et le service d’arrière-plan ne peut pas s’exécuter en arrière-plan. commencé après la poussée reçue.

Donc, le mot magique est

  stopSelf(); 

Jusqu’à présent, toutes les raisons pour lesquelles votre service tombe en panne, suivez toutes les étapes ci-dessus et profitez-en.

Même après avoir appelé startForeground dans Service , il se bloque sur certains périphériques si nous appelons stopService juste avant l’appel de stopService . Donc, j’ai corrigé ce problème en démarrant le service avec un indicateur supplémentaire:

 Intent intent = new Intent(context, YourService.class); intent.putExtra("request_stop", true); context.startService(intent); 

et ajouté un check-in onStartCommand pour voir s’il a réellement commencé à s’arrêter:

 @Override public int onStartCommand(Intent intent, int flags, int startId) { //call startForeground first boolean stopService = false; if (intent != null) { stopService = intent.getBooleanExtra("request_stop", false); } if (stopService) { stopSelf(); return START_STICKY; } //Continue with the background task return START_STICKY; } 

PS Si le service n’était pas en cours d’exécution, il lancera d’abord le service, ce qui représente une surcharge.

Je sais que c’est une réponse tardive mais, je pense que cela pourrait aider à l’avenir, j’ai juste utilisé JobIntentService au lieu d’ IntentService qui inclut son JobScheduler et gère tout pour moi. regardez cet exemple

Assurez-vous que tous les chemins de code appellent la méthode startForeground, par exemple le code peut générer une exception sur la méthode onCreate de votre service qui empêche l’appel de startForeground

  @Override public void onCreate() { try{ } catch(Exception e) { } finally{ startForeground(1, notificationbuilder.build()); } } 

Tout cela disparaît si vous réécrivez votre service pour qu’il démarre w / bindService.

Un exemple de la façon de procéder est disponible à l’ adresse suivante : https://github.com/paulpv/ForegroundServiceAPI26/tree/bound

Un diff de ma twig “repro” peut être vu sur: https://github.com/paulpv/ForegroundServiceAPI26/compare/repro…bound?expand=1