Как принудительно остановить 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