androiddownloadinputstreamdatainputstream

Interrupt download which uses dataInputStream


Have a pretty simple code for download file.

class Downloader {
private static Downloader Dinstance = null;
private boolean isAborted = false;

void setAborted(boolean isAborted) {
    isAborted = true;
}

int getAborted() {
    return isAborted;
}

static Downloader getInstance(@NonNull Context context) {
        if (Dinstance == null)
            Dinstance = new Downloaderr(context.getApplicationContext());
        return Dinstance;
    }

private Downloader() {
    ...
    }

function download() {
    ...
    try {
            URL url = new URL(RequestedURL);
            InputStream inputStream = url.openStream();
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            FileOutputStream fileOutputStream = new FileOutputStream(FileName);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = dataInputStream.read(buffer)) > 0) {
                fileOutputStream.write(buffer, 0, bytesRead);
                if (getAborted()) {
                    Log.d(static_variables.TAG, "Aborting 1");
                    fileOutputStream.close();
                    Log.d(static_variables.TAG, "Aborting 2");
                    dataInputStream.close();
                    Log.d(static_variables.TAG, "Aborting 3");
                    inputStream.close();
                    Log.d(static_variables.TAG, "All closed");                        
                    file.delete();
                    downloadFinished = true;
                    Log.d(static_variables.TAG, "Returning");
                    return false;
                    }
            fileOutputStream.close();
            dataInputStream.close();
            inputStream.close();
        } catch (IOException e) {
            downloadFinished = true;
            return false;
        }
    ...
    }
}

In MainActivity

First button listener(start download):

function onClick() {
   new Thread(new Runnable() {
       @Override
       public void run() {
           Downloader.getInstance().download(...);
           }
       }).start();
   }

Second button listener:

function onClick() {
   Downloader.getInstance().setAborted(true);
   }

Download going in thread. In logs time for dataInputStream.close(); is biggest. And other research shows that streams won't close before file will be fully downloaded.

How I can terminate InputStream in progress?


Solution

  • During research I found two things.

    1. Download aborts with this approach, but there is a buffer and for small files(songs, in my case) it's almost untrackable. For 500Mb file download, when you press abort on 15Mb downloaded, then after 16-17 it will stop.

    2. If you want(as I am) terminate download faster, then you should use another approach. When starting Thread, save pointer int variable.

    Thread threadDownload = new Thread(...);
    threadDownload.start();
    

    then abort using

    threadDownload.interrupt();
    

    Beware. You'll need remove temporary file by yourself. File which you use in OutputStream.

    You also will have some buffer overhead, but it will be not 1-2Mb, but 200-300Kb.