29

I made an app that downloads videos from our server. The issue is:

When i cancel the downloading i call:

myAsyncTask.cancel(true)

I noticed, that myAsyncTask doesn't stops on calling cancel... my ProgressDialog still goes up and its like jumping from status to status showing me that each time I cancel and start again an AsyncTask by clicking the download button, a new AsyncTask starts... Each time I click download.. then cancel, then again download a separate AsyncTask starts.

Why is myAsynTask.cancle(true) not cancelling my task ? I don't want it anymore on the background. I just want to completely shut it down if I click cancel.

How to do it ?

E D I T:

Thanks to gtumca-MAC, and the others who helped me did it by:

while (((count = input.read(data)) != -1) && (this.isCancelled()==false)) 
{
    total += count;
    publishProgress((int) (total * 100 / lenghtOfFile));
    output.write(data, 0, count);
}

Thanks!!!

Android
  • 1,420
  • 4
  • 13
  • 23
Adam Varhegyi
  • 11,307
  • 33
  • 124
  • 222
  • Have you seen this link? http://stackoverflow.com/questions/2735102/ideal-way-to-cancel-an-executing-asynctask – Shrikant Ballal Jun 04 '12 at 13:58
  • 1
    @AdamVarhegyi: It is inherently impossible for Java to automatically cancel your task. Aborting a thread is very dangerous. – SLaks Jun 04 '12 at 14:10
  • 1
    @AdamVarhegyi If you Override onCancelled() it is called instead of onPostExecute after doInBackGround(). This has nothing to do with Java. AsyncTask.cancel() does not call onCancelled() it sets the flag that your code should honor. And it is all well documented here https://developer.android.com/reference/android/os/AsyncTask.html – Dirk Jäckel Jun 04 '12 at 14:35

7 Answers7

59

AsyncTask does not cancel process on

myAsynTask.cancel(true) 

For that you have to stop it manually.

for example you are downloading video in doInBackground(..) in while/for loop.

protected Long doInBackground(URL... urls) {

         for (int i = 0; i < count; i++) {
          // you need to break your loop on particular condition here

             if(isCancelled())
                  break;             
         }
         return totalSize;
     }
MAC
  • 15,799
  • 8
  • 54
  • 95
  • who is saying it canceled the async task ?? I have tried it and the code works but in actual async never stops. why you have used For loop ?? if I dont want to use loop why should I stop this. – Ahmad Arslan Jan 12 '15 at 06:27
  • 4
    can somebody tell me when iscancelled() will be get called ?? – abh22ishek Feb 19 '15 at 12:17
  • While the ASyncTask operation is running, and you write task.cancal(true). It will simply set the cancel flag to true without killing/stopping the ASyncTask. After that, you have to implement code if(isCancelled) {...} inside the ASyncTask to check the flag and accordingly do the ASyncTask process flow (by handling inside condition). – Rahul Raina May 30 '18 at 06:10
6

Declare in your class

DownloadFileAsync downloadFile = new DownloadFileAsync();

then On Create

DownloadFileAsync downloadFile = new DownloadFileAsync();
downloadFile.execute(url);

in Your Background ()

if (isCancelled())
    break;

@Override
protected void onCancelled(){

}

and you can kill your AsyncTask by

downloadFile.cancel(true);
Mohamed Hussien
  • 1,084
  • 13
  • 14
3

When you start a separate thread(AyncTask) it has to finish. You have to manually add a cancel statement to your code inside the AsyncTask.

A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)

Checkout more in the documentation: http://developer.android.com/reference/android/os/AsyncTask.html

Zelleriation
  • 2,834
  • 1
  • 23
  • 23
0

I have been researching from the last 2 weeks and I don't get to know that how we kill the Async operation manually. Some developers use BREAK; while checking in for loop. But on my scenario I am not using the loop inside of background thread. But I have got to know how it woks its a stupid logic but works perfectly fine.

downloadFile.cancel(true);   //This code wont work in any case.

Instead of canceling and doing so much work on background thread turn off the wifi programmatically

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(false);

where do you want to kill the operation and turn on it where do you need that.

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true);

What happens is your try block jumps in to the IOException killing the background tasks.

Ahmad Arslan
  • 4,498
  • 8
  • 38
  • 59
0

You better use vogella asyncTask library which have a lot of features like priority and canceling background task. And a great tutorial or using it is here

Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
0

You can use this code. I am downloading a OTA file as follow:

static class FirmwareDownload extends AsyncTask<String, String, String> {

        public String TAG = "Super LOG";
        public String file;
        int lenghtOfFile;
        long total;

        @Override
        protected String doInBackground(String... f_url) {
            try {
                int count;
                Utilies.getInternet();

                URL url = new URL(f_url[0]);
                URLConnection connection = url.openConnection();
                connection.connect();
                lenghtOfFile = connection.getContentLength();
                mProgressBar.setMax(lenghtOfFile);
                InputStream input = new BufferedInputStream(url.openStream(), 8192);
                String fileName = f_url[0].substring(f_url[0].lastIndexOf("/"), f_url[0].length());
                File root = Environment.getExternalStorageDirectory();
                File dir = new File(root.getAbsolutePath() + fileName);

                Log.d(TAG, "trying to download in : " + dir);
                dir.getAbsolutePath();
                OutputStream output = new FileOutputStream(dir);
                byte data[] = new byte[1024];


                while ((count = input.read(data)) != -1) {

                    if (isCancelled())
                        break;

                    total += count;
                    mProgressBar.setProgress(Integer.parseInt("" + total));
                    Log.d("Downloading " + fileName + " : ", " " + (int) ((total * 100) / lenghtOfFile));
                    mPercentage.post(new Runnable() {
                        @Override
                        public void run() {
                            mPercentage.setText(total / (1024 * 1024) + " Mb / " + lenghtOfFile / (1024 * 1024) + " Mb");
                        }
                    });
                    output.write(data, 0, count);
                }

                output.flush();
                output.close();
                input.close();

                //new InstallHelper().commandLine("mkdir data/data/ota");

                File fDest = new File("/data/data/ota/" + fileName);
                copyFile(dir, fDest);
                FirmwareInstaller fw = new FirmwareInstaller();
                fw.updateFirmware();

            } catch (Exception a) {
                System.out.println("Error trying donwloading firmware " + a);
                new InstallHelper().commandLine("rm -r  data/data/ota");
                dialog.dismiss();

            }
            return null;
        }

    }

So, If you want to cancel, just use this code:

 fDownload.cancel(true);
Victor Ruiz.
  • 1,706
  • 22
  • 22
-1

I have used with success inside an activity with TextView onclick ...

        //inside the doInBackground() ...

        try {
        while (true) {
        System.out.println(new Date());

        //should be 1 * 1000 for second
        Thread.sleep(5 * 1000);
        if (isCancelled()) {
              return null;
        }
          }

        } catch (InterruptedException e) {

        }

and in my onCreate() ...

     //set Activity
     final SplashActivity sPlashScreen = this;

     //init my Async Task
     final RetrieveFeedTask syncDo = new RetrieveFeedTask();
     syncDo.execute();

     //init skip link
     skip_text = (TextView) findViewById(R.id.skip_text);
     skip_text.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            //cancel Async
            syncDo.cancel(true);

            //goto/start another activity
            Intent intent = new Intent();
            intent.setClass(sPlashScreen, MainActivity.class);
            startActivity(intent);
            finish();

        }
    });

and my xml TextView element ...

   <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/skip_text"
        android:layout_marginTop="20dp"
        android:text="SKIP"
        android:textColor="@color/colorAccent"/>
BENN1TH
  • 2,003
  • 2
  • 31
  • 42