urSus
urSus

Reputation: 12739

How to force stop Intent Service in progress?

I have an intent service which downloads several gigabytes of videos. I have a "Stop" button, to stop the download if accidentally hit "Start" or whatever. I know this has been asked a couple of times but with no working answer for me.

I try to call stopService(), doesn't work. That just calls IntentService.OnDestroy(). I tried to call stopSelf() inside onDestroy, doesn't work either.

I tried to have something like a flag, but onHandleIntent doesn't get called if its already running, it waits till current work is finished and executes then. And even if this would have worked, I would have to have something like a giant if statement, that sucks

Is my only option really to rewrite it to a regular Service?

//Answer

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;
            }

            ...
        }

    }
}

And trigger it with

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

Upvotes: 12

Views: 8045

Answers (2)

Michael Zajac
Michael Zajac

Reputation: 55569

Given that you haven't posted how you're handling the video download exactly, this may not work (there would be some sort of loop inside onHandleIntent where the downloads are executed). You can use a static class variable inside the IntentService that holds the Stop/Start state of the download, so that it can be set by an Activity. Then, inside onHandleIntent, you would have to routinely check the state so it would know when to cancel the operations.

Upvotes: 2

CommonsWare
CommonsWare

Reputation: 1006539

You have two separate issues, I would think:

  1. How to stop the current download

  2. How to stop queued up downloads, that should execute after the current one completes

The first one is going to have to be "something like a flag", that you check as you download the data. Otherwise, nothing is going to stop your download operation. If you are using a typical HttpUrlConnection recipe, you check that flag in your loop where you read from the HTTP InputStream and write to your FileOutputStream. You set that flag via a call to startService() with a particular Intent structure, identifying it as a "cancel" operation. You would need to override onStartCommand() in your IntentService, look at the Intent, use it to set the flag if it is the cancel Intent, or chain to the superclass for any other sort of Intent.

If you also may have other commands queued up (scenario #2), you would need to check that flag at the top of onHandleIntent() as well.

Upvotes: 12

Related Questions