Как да спрете принудително изпълнение на Intent Service?

Имам услуга за намерения, която изтегля няколко гигабайта видеоклипове. Имам бутон "Стоп", за да спра изтеглянето, ако случайно натиснете "Старт" или каквото и да е друго. Знам, че това е задавано няколко пъти, но без работещ отговор за мен.

Опитвам се да се обадя на stopService(), не става. Това просто извиква IntentService.OnDestroy(). Опитах се да извикам stopSelf() вътре в onDestroy, също не работи.

Опитах се да имам нещо като флаг, но onHandleIntent не се извиква, ако вече се изпълнява, изчаква текущата работа да приключи и тогава се изпълнява. И дори ако това щеше да проработи, трябваше да имам нещо като гигантско if изявление, това е гадно

Единствената ми възможност наистина ли е да го пренапиша на обикновен сервиз?

//Отговор

public class SyncService extends IntentService {

    boolean isCanceled;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent.hasExtra("action")) {

            // Set the canceling flag
            isCanceled= intent.getStringExtra("action").equals("cancel");

        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        // Clean up the possible queue
        if (intent.hasExtra ("action")) {
            boolean cancel = intent.getStringExtra ("action"). Equals ("cancel");
            if (cancel) {
                return;
            }
        }

        ...

        Get your inputStream from HttpUrlConnection or whatever

        ...

        while ((bytesRead = in.read(buffer)) > 0) {
            if (isCanceled) {
                isCanceled = false;
                break;
            }

            ...
        }

    }
}

И го задействайте с

Intent intent = new Intent(context, SyncService.class);
intent.putExtra("action", "cancel");
context.startService(intent);

person urSus    schedule 18.04.2013    source източник
comment
Може да обмислите премахването на вашето решение от вашия въпрос и вместо това да го предоставите като решение.   -  person jbaums    schedule 06.02.2014


Отговори (2)


Мисля, че имате два отделни проблема:

  1. Как да спрете текущото изтегляне

  2. Как да спрете изтегляния на опашка, които трябва да се изпълнят, след като текущото завърши

Първият ще трябва да бъде "нещо като флаг", който проверявате, докато изтегляте данните. В противен случай нищо няма да спре операцията ви по изтегляне. Ако използвате типична HttpUrlConnection рецепта, проверявате този флаг във вашия цикъл, където четете от HTTP InputStream и пишете на вашия FileOutputStream. Задавате този флаг чрез извикване на startService() с определена структура Intent, идентифицирайки го като операция "отказ". Ще трябва да замените onStartCommand() във вашия IntentService, да погледнете Intent, да го използвате, за да зададете флага, ако това е отмяната Intent, или верига към суперкласа за всеки друг вид Intent.

Ако също може да имате други команди на опашка (сценарий #2), ще трябва да проверите и този флаг в горната част на onHandleIntent().

person CommonsWare    schedule 18.04.2013
comment
Да точно както казвате. Ако го пренапиша в услуга, ще мога ли да го изключа принудително или ще бъде същото като тук? - person urSus; 19.04.2013
comment
@VlastoBennyLava: Горе-долу ще бъде същото като тук. Ще имате по-добра възможност да използвате stopService() и onDestroy(), за да зададете флага, но ще трябва да управлявате своя собствена фонова нишка и работна опашка. - person CommonsWare; 19.04.2013
comment
Редактирах въпроса си с псевдокод на отговора, може да искате да го проверите. Благодаря - person urSus; 19.04.2013
comment
@VlastoBennyLava: Бих използвал AtomicBoolean, а не boolean, тъй като ще се манипулира в паралелни нишки. В противен случай това трябва да работи. - person CommonsWare; 19.04.2013

Като се има предвид, че не сте публикували как точно се справяте с изтеглянето на видео, това може да не работи (ще има някакъв цикъл вътре onHandleIntent, където се изпълняват изтеглянията). Можете да използвате променлива на статичен клас вътре в IntentService, която държи състоянието Stop/Start на изтеглянето, така че да може да бъде зададено от Activity. След това, вътре в onHandleIntent, ще трябва рутинно да проверявате състоянието, за да знае кога да отмени операциите.

person Michael Zajac    schedule 18.04.2013