diff --git a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java index 5dfc80f6e..8be443376 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java @@ -10,6 +10,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; +import java.util.Timer; +import java.util.TimerTask; public abstract class Downloader { @@ -25,6 +27,9 @@ public abstract class Downloader { public static final String EXTRA_TOTAL_BYTES = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES"; private volatile boolean cancelled = false; + private volatile int bytesRead; + private volatile int totalBytes; + private Timer timer; private final OutputStream outputStream; @@ -42,6 +47,9 @@ public abstract class Downloader { void sendProgress(URL sourceUrl, int bytesRead, int totalBytes); } + /** + * For sending download progress, should only be called in {@link #progressTask} + */ private DownloaderProgressListener downloaderProgressListener; protected abstract InputStream getDownloadersInputStream() throws IOException; @@ -123,6 +131,9 @@ public abstract class Downloader { private void throwExceptionIfInterrupted() throws InterruptedException { if (cancelled) { Utils.debugLog(TAG, "Received interrupt, cancelling download"); + if (timer != null) { + timer.cancel(); + } throw new InterruptedException(); } } @@ -140,16 +151,17 @@ public abstract class Downloader { * progress counter. */ private void copyInputToOutputStream(InputStream input, int bufferSize) throws IOException, InterruptedException { - - int bytesRead = 0; - int totalBytes = totalDownloadSize(); + bytesRead = 0; + totalBytes = totalDownloadSize(); byte[] buffer = new byte[bufferSize]; + timer = new Timer(); + timer.scheduleAtFixedRate(progressTask, 0, 100); + // Getting the total download size could potentially take time, depending on how // it is implemented, so we may as well check this before we proceed. throwExceptionIfInterrupted(); - sendProgress(bytesRead, totalBytes); while (true) { int count; @@ -168,19 +180,25 @@ public abstract class Downloader { } bytesRead += count; - sendProgress(bytesRead, totalBytes); outputStream.write(buffer, 0, count); - } + timer.cancel(); + timer.purge(); outputStream.flush(); outputStream.close(); } - private void sendProgress(int bytesRead, int totalBytes) { - if (downloaderProgressListener != null) { - downloaderProgressListener.sendProgress(sourceUrl, bytesRead, totalBytes); + /** + * Send progress updates on a timer to avoid flooding receivers with pointless events. + */ + private final TimerTask progressTask = new TimerTask() { + @Override + public void run() { + if (downloaderProgressListener != null) { + downloaderProgressListener.sendProgress(sourceUrl, bytesRead, totalBytes); + } } - } + }; /** * Overrides every method in {@link InputStream} and delegates to the wrapped stream.