Refactor AsyncDownloader to be an interface.
The interface is used by both AsyncDownloadWrapper and AsyncDownloaderFromAndroid.
This commit is contained in:
parent
d0d287f668
commit
0a9941d93d
98
F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java
Normal file
98
F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java
Normal file
@ -0,0 +1,98 @@
|
||||
package org.fdroid.fdroid.net;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class AsyncDownloadWrapper extends Handler implements AsyncDownloader {
|
||||
|
||||
private static final String TAG = "AsyncDownloadWrapper";
|
||||
|
||||
private static final int MSG_DOWNLOAD_COMPLETE = 2;
|
||||
private static final int MSG_DOWNLOAD_CANCELLED = 3;
|
||||
private static final int MSG_ERROR = 4;
|
||||
private static final String MSG_DATA = "data";
|
||||
|
||||
private final Downloader downloader;
|
||||
private DownloadThread downloadThread = null;
|
||||
|
||||
private final Listener listener;
|
||||
|
||||
/**
|
||||
* Normally the listener would be provided using a setListener method.
|
||||
* However for the purposes of this async downloader, it doesn't make
|
||||
* sense to have an async task without any way to notify the outside
|
||||
* world about completion. Therefore, we require the listener as a
|
||||
* parameter to the constructor.
|
||||
*/
|
||||
public AsyncDownloadWrapper(Downloader downloader, Listener listener) {
|
||||
this.downloader = downloader;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public int getBytesRead() {
|
||||
return downloader.getBytesRead();
|
||||
}
|
||||
|
||||
public int getTotalBytes() {
|
||||
return downloader.getTotalBytes();
|
||||
}
|
||||
|
||||
public void download() {
|
||||
downloadThread = new DownloadThread();
|
||||
downloadThread.start();
|
||||
}
|
||||
|
||||
public void attemptCancel(boolean userRequested) {
|
||||
if (downloadThread != null) {
|
||||
downloadThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives "messages" from the download thread, and passes them onto the
|
||||
* relevant {@link AsyncDownloader.Listener}
|
||||
*/
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.arg1) {
|
||||
case MSG_DOWNLOAD_COMPLETE:
|
||||
listener.onDownloadComplete();
|
||||
break;
|
||||
case MSG_DOWNLOAD_CANCELLED:
|
||||
listener.onDownloadCancelled();
|
||||
break;
|
||||
case MSG_ERROR:
|
||||
listener.onErrorDownloading(message.getData().getString(MSG_DATA));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private class DownloadThread extends Thread {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
downloader.download();
|
||||
sendMessage(MSG_DOWNLOAD_COMPLETE);
|
||||
} catch (InterruptedException e) {
|
||||
sendMessage(MSG_DOWNLOAD_CANCELLED);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "I/O exception in download thread", e);
|
||||
Bundle data = new Bundle(1);
|
||||
data.putString(MSG_DATA, e.getLocalizedMessage());
|
||||
Message message = new Message();
|
||||
message.arg1 = MSG_ERROR;
|
||||
message.setData(data);
|
||||
AsyncDownloadWrapper.this.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(int messageType) {
|
||||
Message message = new Message();
|
||||
message.arg1 = messageType;
|
||||
AsyncDownloadWrapper.this.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,106 +9,17 @@ import org.fdroid.fdroid.ProgressListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Given a {@link org.fdroid.fdroid.net.Downloader}, this wrapper will conduct the download operation on a
|
||||
* separate thread. All progress/status/error/etc events will be forwarded from that thread to the thread
|
||||
* that {@link AsyncDownloader#download()} was invoked on. If you want to respond with UI feedback
|
||||
* to these events, it is important that you execute the download method of this class from the UI thread.
|
||||
* That way, all forwarded events will be handled on that thread.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AsyncDownloader extends Handler {
|
||||
public interface AsyncDownloader {
|
||||
|
||||
private static final String TAG = "AsyncDownloadWrapper";
|
||||
|
||||
private static final int MSG_DOWNLOAD_COMPLETE = 2;
|
||||
private static final int MSG_DOWNLOAD_CANCELLED = 3;
|
||||
private static final int MSG_ERROR = 4;
|
||||
private static final String MSG_DATA = "data";
|
||||
|
||||
private final Downloader downloader;
|
||||
private final Listener listener;
|
||||
private DownloadThread downloadThread = null;
|
||||
|
||||
/**
|
||||
* Normally the listener would be provided using a setListener method.
|
||||
* However for the purposes of this async downloader, it doesn't make
|
||||
* sense to have an async task without any way to notify the outside
|
||||
* world about completion. Therefore, we require the listener as a
|
||||
* parameter to the constructor.
|
||||
*/
|
||||
public AsyncDownloader(Downloader downloader, Listener listener) {
|
||||
this.downloader = downloader;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void download() {
|
||||
downloadThread = new DownloadThread();
|
||||
downloadThread.start();
|
||||
}
|
||||
|
||||
public void attemptCancel(boolean userRequested) {
|
||||
if (downloadThread != null) {
|
||||
downloadThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives "messages" from the download thread, and passes them onto the
|
||||
* relevant {@link AsyncDownloader.Listener}
|
||||
* @param message
|
||||
*/
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.arg1) {
|
||||
case MSG_DOWNLOAD_COMPLETE:
|
||||
listener.onDownloadComplete();
|
||||
break;
|
||||
case MSG_DOWNLOAD_CANCELLED:
|
||||
listener.onDownloadCancelled();
|
||||
break;
|
||||
case MSG_ERROR:
|
||||
listener.onErrorDownloading(message.getData().getString(MSG_DATA));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int getBytesRead() {
|
||||
return downloader.getBytesRead();
|
||||
}
|
||||
|
||||
public int getTotalBytes() {
|
||||
return downloader.getTotalBytes();
|
||||
}
|
||||
|
||||
public interface Listener extends ProgressListener {
|
||||
interface Listener extends ProgressListener {
|
||||
void onErrorDownloading(String localisedExceptionDetails);
|
||||
void onDownloadComplete();
|
||||
void onDownloadCancelled();
|
||||
}
|
||||
|
||||
private class DownloadThread extends Thread {
|
||||
int getBytesRead();
|
||||
int getTotalBytes();
|
||||
void download();
|
||||
void attemptCancel(boolean userRequested);
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
downloader.download();
|
||||
sendMessage(MSG_DOWNLOAD_COMPLETE);
|
||||
} catch (InterruptedException e) {
|
||||
sendMessage(MSG_DOWNLOAD_CANCELLED);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "I/O exception in download thread", e);
|
||||
Bundle data = new Bundle(1);
|
||||
data.putString(MSG_DATA, e.getLocalizedMessage());
|
||||
Message message = new Message();
|
||||
message.arg1 = MSG_ERROR;
|
||||
message.setData(data);
|
||||
AsyncDownloader.this.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(int messageType) {
|
||||
Message message = new Message();
|
||||
message.arg1 = messageType;
|
||||
AsyncDownloader.this.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import java.io.OutputStream;
|
||||
* A downloader that uses Android's DownloadManager to perform a download.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
public class AsyncDownloaderFromAndroid extends AsyncDownloader {
|
||||
public class AsyncDownloaderFromAndroid implements AsyncDownloader {
|
||||
private final Context context;
|
||||
private final DownloadManager dm;
|
||||
private File localFile;
|
||||
@ -42,7 +42,6 @@ public class AsyncDownloaderFromAndroid extends AsyncDownloader {
|
||||
* parameter to the constructor.
|
||||
*/
|
||||
public AsyncDownloaderFromAndroid(Context context, Listener listener, String appName, String appId, String remoteAddress, File localFile) {
|
||||
super(null, listener);
|
||||
this.context = context;
|
||||
this.appName = appName;
|
||||
this.appId = appId;
|
||||
|
@ -5,7 +5,6 @@ import android.os.Build;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class DownloaderFactory {
|
||||
@ -62,7 +61,7 @@ public class DownloaderFactory {
|
||||
if (canUseDownloadManager(url)) {
|
||||
return new AsyncDownloaderFromAndroid(context, listener, title, id, url.toString(), destFile);
|
||||
} else {
|
||||
return new AsyncDownloader(create(context, url, destFile), listener);
|
||||
return new AsyncDownloadWrapper(create(context, url, destFile), listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user