0

I have class that represents a download task unit.

import android.os.Environment;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

/**
 * Created by Sergey Shustikov (sergey.shustikov@youshido.com) at 2015.
 */
public class DownloadTask extends Thread implements DownloadActions
{

    private DownloadStateListener mListener;
    private String mDownloadLink;

    public DownloadTask(String downloadLink)
    {
        mDownloadLink = downloadLink;
    }

    @Override
    public void cancel()
    {
        interrupt();
        mListener.onDownloadCanceled(mDownloadLink);
    }

    @Override
    public void setDownloadStateChangedListener(DownloadStateListener listener)
    {
        mListener = listener;
    }

    @Override
    public void run()
    {
        int count;
        try {
            mListener.onDownloadStarted(mDownloadLink);
            URL url = new URL(mDownloadLink);
            URLConnection connection = url.openConnection();
            connection.connect();

            // this will be useful so that you can show a tipical 0-100%
            // progress bar
            int contentLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());

            // Output stream
            OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/Download/");

            byte data[] = new byte[1024];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                // After this onProgressUpdate will be called
                mListener.onDownloadProgress(mDownloadLink, (int) ((total * 100) / contentLength));

                // writing data to file
                output.write(data, 0, count);
            }

            close(connection, input, output);
            mListener.onDownloadFinished(mDownloadLink);

        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
            mListener.onDownloadFailed(mDownloadLink, new DownloadError(e.getMessage()));
        }

    }

    private synchronized void close(URLConnection connection, InputStream input, OutputStream output)
    {
        try {
            // flushing output
            if (output != null) {
                output.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // closing streams
        try {
            // flushing output
            if (output != null) {
                output.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // flushing output
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

I need to stop downloading, clear downloaded data and close connection when i call cancel() method.

I know - there are many discussion about stop mechanism in Java.

I can't use this answer :

You can create a boolean field and check it inside run:

public class Task implements Runnable {

   private volatile boolean isRunning = true;

   public void run() {

       while (isRunning) {
       //do work
       }
   } 
   public void kill() {
         isRunning = false;
   }

}

To stop it just call

task.kill();

This should work.

because it is no operation in loop.

So how i can correctly do that?

Community
  • 1
  • 1
Sergey Shustikov
  • 15,377
  • 12
  • 67
  • 119

3 Answers3

2

You have to interrupt your (potentially long-running) reading process:

while ((count = input.read(data)) != -1 && isRunning) {
    // perform reading
}
Smutje
  • 17,733
  • 4
  • 24
  • 41
  • I think it is not a good idea. I can cancel task when code leave loop. For example - in `out.close()` method. – Sergey Shustikov Jun 01 '15 at 13:14
  • @SergeyShustikov you can do that after the while loop... Just as you are doing. This answer does what you are asking for. – Balduz Jun 01 '15 at 13:16
  • Balduz, i understand what i'm need to do. You offer to me check everywhere with `boolean` expression,(after each line for the best) but is that good practice? – Sergey Shustikov Jun 01 '15 at 13:20
  • You should identify which operations are blocking or long-running - when you exit the while-loop, the expensive part should be done anyway, so why "interrupt" at that point? – Smutje Jun 01 '15 at 13:22
1

You cant interrupt a thread unless the code you let the thread run is interruptable - that is - checking for itself if it was interrupted.

EDIT In your case - something like :

final Thread cancelable = new Thread() {

            @Override
            public void run() {
                int count;
                try {
                    ...

                    while ((count = input.read(data)) != -1 && !Thread.interrupted()) {
                        total += count;
                        // publishing the progress....
                        // After this onProgressUpdate will be called
                        mListener.onDownloadProgress(mDownloadLink, (int) ((total * 100) / contentLength));

                        // writing data to file
                        output.write(data, 0, count);
                    }
                    if ( Thread.interrupted() ) {
                        mListener.onDownloadCanceled(mDownloadLink);
                    }
                    ...
                }
            }
            }
        });

and to stop the download you must call :

cancelable.interrupt();
Ofek Ron
  • 8,354
  • 13
  • 55
  • 103
0
public class Task implements Runnable {

   private boolean cancel;

   public void run() {

     try{

       while (yourCondition) {
       //do work
          if(cancel){
             throw new DownloadCancelException();
          }
       }
     }catch(DownloadCancelException e){
        //clear downloaded stuff over here
     }

   } 
   public void kill() {
         cancel = true;
   }

}
shobhan
  • 1,460
  • 2
  • 14
  • 28