web-dev-qa-db-fra.com

Quelle est la bonne façon d'arrêter un service fonctionnant en premier plan

J'essaie d'arrêter un service qui s'exécute en tant que service de premier plan.

Le problème actuel est que lorsque j'appelle stopService() la notification reste.

Donc, dans ma solution, j'ai ajouté un récepteur auquel je m'inscris dans la onCreate()

Dans la méthode onReceive() j'appelle stopforeground(true) et elle masque la notification. Et puis stopself() pour arrêter le service.

À l'intérieur de la onDestroy() J'ai désenregistré le récepteur.

Existe-t-il un moyen plus approprié de gérer cela? parce que stopService () ne fonctionne tout simplement pas.

@Override
public void onDestroy(){
  unregisterReceiver(receiver);
  super.onDestroy();
}
30
user1940676

À partir de votre activité, appelez startService(intent) et transmettez-lui des données qui représenteront une clé pour arrêter le service.

Depuis votre service, appelez stopForeground(true) puis stopSelf() juste après.

51
Ilya Gazman

pour démarrer et arrêter un service de premier plan à partir d'une activité, utilisez:

//start
    Intent startIntent = new Intent(MainActivity.this, ForegroundService.class);
    startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
    startService(startIntent);
//stop
    Intent stopIntent = new Intent(MainActivity.this, ForegroundService.class);
    stopIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
    startService(stopIntent);

dans votre service de premier plan - utilisez (au moins) ce code:

@Override
 public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
        Log.i(LOG_TAG, "Received Start Foreground Intent ");
        // your start service code
    }
    else if (intent.getAction().equals( Constants.ACTION.STOPFOREGROUND_ACTION)) {
        Log.i(LOG_TAG, "Received Stop Foreground Intent");
    //your end servce code
        stopForeground(true);
        stopSelf();
    }
    return START_STICKY;
}
24
Elad

En plus d'autres réponses, j'ai terminé avec cet extrait en utilisant Android oreo et laters pour arrêter les services de travail.

Intent intent = new Intent(getApplicationContext(), LocationService.class);
intent.setAction(status);
ContextCompat.startForegroundService(getApplicationContext(), intent);

Et en service

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
  startForeground(121, notification);
  if (intent.getAction().equals("StopService")) {
    stopForeground(true);
    stopSelf();
  }

startForeground () est obligatoire sauf si l'application se bloque sans l'appeler

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

https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html

1
Nerius Jok

Comme indiqué ici: https://developer.Android.com/guide/components/services#Stopping

Un service démarré doit gérer son propre cycle de vie. Autrement dit, le système n'arrête ni ne détruit le service à moins qu'il ne doive récupérer la mémoire système et que le service continue de s'exécuter après le retour de onStartCommand () . Le service doit s'arrêter en appelant stopSelf () , ou un autre composant peut l'arrêter en appelant stopService () .

Une fois demandé d'arrêter avec stopSelf () ou stopService () , le système détruit le service dès que possible.

Vous pouvez donc appeler stopService () à partir de l'activité que vous avez utilisée pour appeler startService (). Je l'ai fait ici:

start_button.setOnClickListener {
        applicationContext.startForegroundService(Intent(this, ServiceTest::class.Java))
    }
    stop_button.setOnClickListener {
        applicationContext.stopService(Intent(this, ServiceTest::class.Java))
    }

J'ai créé deux boutons pour démarrer et arrêter le service et cela fonctionne.

1
Ahmed Shahid

Si vous souhaitez arrêter le service, puis mettre à jour la notification, vous pouvez d'abord appeler stopSelf () puis notifier (). stopForeground (false) rend la notification annulable.

 private final BroadcastReceiver myBgWorkCompleteReceiver= new BroadcastReceiver() {
        @Override
  public void onReceive(Context context, Intent intent) {
            stopSelf();
            notificationLayoutExpanded.setTextViewText(R.id.file_download_notify_download_percentage, "Background work completed");
            manager.notify(mNotificationId, notification);
            stopForeground(false);
        }
};


 public void onDestroy() {
        super.onDestroy();
        // cancel any running threads here
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myBgWorkCompleteReceiver);
    }
0
LincyTonita

J'ai trouvé que la meilleure façon d'arrêter un service est de s'arrêter. De cette façon, vous êtes sûr qu'il s'arrêtera et préservera l'intégrité des données. Si vous voulez le faire de l'extérieur (activité), j'utilise généralement un attribut statique global.

Vérifiez ma réponse ici: https://stackoverflow.com/a/57833370/7795547

0
D Dimitrov