Downloader.cancelDownload() instead of using external Thread logic

This is needed so that downloads can be canceled from within an
IntentService. Since the Downloader classes do not have any Thread logic in
them, they shouldn't use Thread logic within them anyway.

This also removes the unused argument to AsyncDownloader.attemptCancel().
This commit is contained in:
Hans-Christoph Steiner 2016-03-29 19:19:09 +02:00
parent 74274d21b4
commit 591b23b5ab
6 changed files with 55 additions and 11 deletions

View File

@ -556,7 +556,7 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
@Override
protected void onDestroy() {
if (downloadHandler != null && !inProcessOfChangingConfiguration) {
downloadHandler.cancel(false);
downloadHandler.cancel();
cleanUpFinishedDownload();
}
inProcessOfChangingConfiguration = false;
@ -1553,7 +1553,7 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
return;
}
activity.downloadHandler.cancel(true);
activity.downloadHandler.cancel();
activity.cleanUpFinishedDownload();
setProgressVisible(false);
updateViews();

View File

@ -253,12 +253,10 @@ public class ApkDownloader implements AsyncDownloader.Listener {
/**
* Attempts to cancel the download (if in progress) and also removes the progress
* listener
*
* @param userRequested - true if the user requested the cancel (via button click), otherwise false.
*/
public void cancel(boolean userRequested) {
public void cancel() {
if (dlWrapper != null) {
dlWrapper.attemptCancel(userRequested);
dlWrapper.attemptCancel();
}
}

View File

@ -43,9 +43,9 @@ class AsyncDownloadWrapper extends Handler implements AsyncDownloader {
downloadThread.start();
}
public void attemptCancel(boolean userRequested) {
if (downloadThread != null) {
downloadThread.interrupt();
public void attemptCancel() {
if (downloader != null) {
downloader.cancelDownload();
}
}

View File

@ -16,6 +16,6 @@ public interface AsyncDownloader {
void download();
void attemptCancel(boolean userRequested);
void attemptCancel();
}

View File

@ -23,6 +23,8 @@ public abstract class Downloader {
public static final String EXTRA_BYTES_READ = "extraBytesRead";
public static final String EXTRA_TOTAL_BYTES = "extraTotalBytes";
private volatile boolean cancelled = false;
private final OutputStream outputStream;
private final File outputFile;
@ -124,12 +126,19 @@ public abstract class Downloader {
* @throws InterruptedException
*/
private void throwExceptionIfInterrupted() throws InterruptedException {
if (Thread.interrupted()) {
if (cancelled) {
Utils.debugLog(TAG, "Received interrupt, cancelling download");
throw new InterruptedException();
}
}
/**
* Cancel a running download, triggering an {@link InterruptedException}
*/
public void cancelDownload() {
cancelled = true;
}
/**
* This copies the downloaded data from the InputStream to the OutputStream,
* keeping track of the number of bytes that have flowed through for the

View File

@ -6,8 +6,11 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class HttpDownloaderTest {
@ -56,4 +59,38 @@ public class HttpDownloaderTest {
assertTrue(receivedProgress);
}
}
@Test
public void downloadThenCancel() throws IOException, InterruptedException {
final CountDownLatch latch = new CountDownLatch(5);
URL url = new URL("https://f-droid.org/repo/index.jar");
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
final HttpDownloader httpDownloader = new HttpDownloader(url, destFile, null);
httpDownloader.setListener(new Downloader.DownloaderProgressListener() {
@Override
public void sendProgress(URL sourceUrl, int bytesRead, int totalBytes) {
System.out.println("DownloaderProgressListener.sendProgress " + bytesRead + " / " + totalBytes);
receivedProgress = true;
latch.countDown();
}
});
new Thread(){
@Override
public void run() {
try {
httpDownloader.download();
fail();
} catch (IOException e) {
e.printStackTrace();
fail();
} catch (InterruptedException e) {
// success!
}
}
}.start();
latch.await(100, TimeUnit.SECONDS); // either 5 progress reports or 100 seconds
httpDownloader.cancelDownload();
assertTrue(receivedProgress);
}
}