J’ai un IntentService qui est lancé à partir d’une activité et je voudrais pouvoir arrêter le service immédiatement à partir de l’activité avec un bouton “annuler” dans l’activité. Dès que ce bouton “annuler” est pressé, je veux que le service arrête d’exécuter des lignes de code.
J’ai trouvé un certain nombre de questions similaires (c.-à-d. Ici , ici , ici , ici ), mais pas de bonnes réponses. Activity.stopService()
et Service.stopSelf()
exécutent la méthode Service.onDestroy()
immédiatement, puis laissez le code dans onHandleIntent()
terminer complètement avant de détruire le service.
Comme il n’ya apparemment pas de moyen garanti pour terminer le thread du service immédiatement, la seule solution recommandée que je peux trouver ( ici ) est d’avoir une variable membre booléenne dans le service qui peut être commutée dans la méthode onDestroy()
, chaque ligne du code dans onHandleIntent()
enveloppée dans sa propre clause “if” regardant cette variable. C’est une façon terrible d’écrire du code.
Est-ce que quelqu’un connaît une meilleure façon de faire cela dans IntentService?
Arrêter immédiatement un thread ou un processus est souvent une mauvaise chose. Cependant, cela devrait aller si votre service est apasortingde.
Déclarez le service comme un processus distinct dans le manifeste:
Et quand vous voulez arrêter son exécution, tuez simplement ce processus:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List runningAppProcesses = am.getRunningAppProcesses(); Iterator iter = runningAppProcesses.iterator(); while(iter.hasNext()){ RunningAppProcessInfo next = iter.next(); Ssortingng pricessName = getPackageName() + ":service"; if(next.processName.equals(pricessName)){ Process.killProcess(next.pid); break; } }
Voici le truc, utilisez une variable statique volatile et vérifiez que la condition continue dans certaines des lignes de votre service que le service continu doit être vérifié:
class MyService extends IntentService { public static volatile boolean shouldContinue = true; public MyService() { super("My Service"); } @Override protected void onHandleIntent(Intent intent) { doStuff(); } private void doStuff() { // do something // check the condition if (shouldContinue == false) { stopSelf(); return; } // continue doing something // check the condition if (shouldContinue == false) { stopSelf(); return; } // put those checks wherever you need } }
et dans votre activité faites ceci pour arrêter votre service,
MyService.shouldContinue = false;
J’ai utilisé un BroadcastReceiver dans le service qui met simplement un stop booléen à true. Exemple:
private boolean stop=false; public class StopReceiver extends BroadcastReceiver { public static final Ssortingng ACTION_STOP = "stop"; @Override public void onReceive(Context context, Intent intent) { stop = true; } } @Override protected void onHandleIntent(Intent intent) { IntentFilter filter = new IntentFilter(StopReceiver.ACTION_STOP); filter.addCategory(Intent.CATEGORY_DEFAULT); StopReceiver receiver = new StopReceiver(); registerReceiver(receiver, filter); // Do stuff .... //In the work you are doing if(stop==true){ unregisterReceiver(receiver); stopSelf(); } }
Ensuite, à partir de l’appel d’activité:
//STOP SERVICE Intent sIntent = new Intent(); sIntent.setAction(StopReceiver.ACTION_STOP); sendBroadcast(sIntent);
Arrêter le service
PD: J’utilise un booléen parce que dans mon cas, j’arrête le service en boucle mais vous pouvez probablement appeler unregisterReceiver et stopSelf dans onReceive.
PD2: N’oubliez pas d’appeler unregisterReceiver si le service se termine normalement ou si vous obtenez une erreur de IntentReceiver.
Dans le cas d’ IntentService, il ne s’arrête pas ou prend toute autre requête via une action intentionnelle jusqu’à ce que sa méthode onHandleIntent
termine la requête précédente.
Si nous essayons de redémarrer IntentService avec une autre action, onHandleIntent
sera appelé uniquement lorsque l’intention / la tâche précédente est terminée.
Également stopService(intent);
ou stopSelf();
ne fonctionne pas tant que la méthode onHandleIntent()
n’a pas terminé sa tâche.
Je pense donc que la meilleure solution consiste à utiliser le Service
normal ici.
J’espère que cela aidera!
Si vous utilisez un IntentService
, alors je pense que vous êtes coincé à faire quelque chose comme vous décrivez, où le code onHandleIntent()
doit interroger son signal “stop”.
Si votre tâche en arrière-plan est potentiellement longue et que vous devez être capable de l’arrêter, je pense que vous devriez plutôt utiliser un Service
ordinaire. Au plus haut niveau, écrivez votre service à:
AsyncTask.cancel(true)
ou demander à onDestroy () d’appeler AsyncTask.cancel(true)
. En échange de la possibilité d’annuler le travail de fond, le Service assume les responsabilités suivantes:
doInBackground()
devra gérer doInBackground()
InterruptedException et / ou vérifier périodiquement l’existence de Thread.interrupted () et renvoyer «tôt». stopSelf()
est appelé (peut-être dans AsyncTask onPostExecute / onCancelled). @Override protected void onHandleIntent(Intent intent) { Ssortingng action = intent.getAction(); if (action.equals(Action_CANCEL)) { stopSelf(); } else if (action.equals(Action_START)) { //handle } }
Esperons que ça marche.
Comme @budius a déjà mentionné dans son commentaire, vous devez définir un booléen sur le Service
lorsque vous cliquez sur ce bouton:
// your Activity.java public boolean onClick() { //... mService.performTasks = false; mService.stopSelf(); }
Et dans votre gestion des Intent
, avant de faire la tâche importante de valider / envoyer les informations d’intention, utilisez simplement ce booléen:
// your Service.java public boolean performTasks = true; protected void onHandleIntent(Intent intent) { Bundle intentInfo = intent.getBundle(); if (this.performTasks) { // Then handle the intent... } }
Sinon, le service effectuera sa tâche de traitement de cette Intent
. C’est comme ça que c’était censé être utilisé, parce que je ne vois pas comment vous pourriez le résoudre autrement si vous regardez le code de base.
Voici un exemple de code pour démarrer / arrêter le service
Commencer,
Intent GPSService = new Intent(context, TrackGPS.class); context.startService(GPSService);
Arrêter,
context.stopService(GPSService);
context.stopService(GPSService);