Revision 0a9941d9

View differences:

F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java
1
package org.fdroid.fdroid.net;
2

  
3
import android.os.Bundle;
4
import android.os.Handler;
5
import android.os.Message;
6
import android.util.Log;
7

  
8
import java.io.IOException;
9

  
10
class AsyncDownloadWrapper extends Handler implements AsyncDownloader {
11

  
12
    private static final String TAG = "AsyncDownloadWrapper";
13

  
14
    private static final int MSG_DOWNLOAD_COMPLETE  = 2;
15
    private static final int MSG_DOWNLOAD_CANCELLED = 3;
16
    private static final int MSG_ERROR              = 4;
17
    private static final String MSG_DATA            = "data";
18

  
19
    private final Downloader downloader;
20
    private DownloadThread downloadThread = null;
21

  
22
    private final Listener listener;
23

  
24
    /**
25
     * Normally the listener would be provided using a setListener method.
26
     * However for the purposes of this async downloader, it doesn't make
27
     * sense to have an async task without any way to notify the outside
28
     * world about completion. Therefore, we require the listener as a
29
     * parameter to the constructor.
30
     */
31
    public AsyncDownloadWrapper(Downloader downloader, Listener listener) {
32
        this.downloader = downloader;
33
        this.listener = listener;
34
    }
35

  
36
    public int getBytesRead() {
37
        return downloader.getBytesRead();
38
    }
39

  
40
    public int getTotalBytes() {
41
        return downloader.getTotalBytes();
42
    }
43

  
44
    public void download() {
45
        downloadThread = new DownloadThread();
46
        downloadThread.start();
47
    }
48

  
49
    public void attemptCancel(boolean userRequested) {
50
        if (downloadThread != null) {
51
            downloadThread.interrupt();
52
        }
53
    }
54

  
55
    /**
56
     * Receives "messages" from the download thread, and passes them onto the
57
     * relevant {@link AsyncDownloader.Listener}
58
     */
59
    public void handleMessage(Message message) {
60
        switch (message.arg1) {
61
            case MSG_DOWNLOAD_COMPLETE:
62
                listener.onDownloadComplete();
63
                break;
64
            case MSG_DOWNLOAD_CANCELLED:
65
                listener.onDownloadCancelled();
66
                break;
67
            case MSG_ERROR:
68
                listener.onErrorDownloading(message.getData().getString(MSG_DATA));
69
                break;
70
        }
71
    }
72

  
73
    private class DownloadThread extends Thread {
74

  
75
        public void run() {
76
            try {
77
                downloader.download();
78
                sendMessage(MSG_DOWNLOAD_COMPLETE);
79
            } catch (InterruptedException e) {
80
                sendMessage(MSG_DOWNLOAD_CANCELLED);
81
            } catch (IOException e) {
82
                Log.e(TAG, "I/O exception in download thread", e);
83
                Bundle data = new Bundle(1);
84
                data.putString(MSG_DATA, e.getLocalizedMessage());
85
                Message message = new Message();
86
                message.arg1 = MSG_ERROR;
87
                message.setData(data);
88
                AsyncDownloadWrapper.this.sendMessage(message);
89
            }
90
        }
91

  
92
        private void sendMessage(int messageType) {
93
            Message message = new Message();
94
            message.arg1 = messageType;
95
            AsyncDownloadWrapper.this.sendMessage(message);
96
        }
97
    }
98
}
F-Droid/src/org/fdroid/fdroid/net/AsyncDownloader.java
9 9

  
10 10
import java.io.IOException;
11 11

  
12
/**
13
 * Given a {@link org.fdroid.fdroid.net.Downloader}, this wrapper will conduct the download operation on a
14
 * separate thread. All progress/status/error/etc events will be forwarded from that thread to the thread
15
 * that {@link AsyncDownloader#download()} was invoked on. If you want to respond with UI feedback
16
 * to these events, it is important that you execute the download method of this class from the UI thread.
17
 * That way, all forwarded events will be handled on that thread.
18
 */
19
@SuppressWarnings("serial")
20
public class AsyncDownloader extends Handler {
12
public interface AsyncDownloader {
21 13

  
22
    private static final String TAG = "AsyncDownloadWrapper";
23

  
24
    private static final int MSG_DOWNLOAD_COMPLETE  = 2;
25
    private static final int MSG_DOWNLOAD_CANCELLED = 3;
26
    private static final int MSG_ERROR              = 4;
27
    private static final String MSG_DATA            = "data";
28

  
29
    private final Downloader downloader;
30
    private final Listener listener;
31
    private DownloadThread downloadThread = null;
32

  
33
    /**
34
     * Normally the listener would be provided using a setListener method.
35
     * However for the purposes of this async downloader, it doesn't make
36
     * sense to have an async task without any way to notify the outside
37
     * world about completion. Therefore, we require the listener as a
38
     * parameter to the constructor.
39
     */
40
    public AsyncDownloader(Downloader downloader, Listener listener) {
41
        this.downloader = downloader;
42
        this.listener   = listener;
43
    }
44

  
45
    public void download() {
46
        downloadThread = new DownloadThread();
47
        downloadThread.start();
48
    }
49

  
50
    public void attemptCancel(boolean userRequested) {
51
        if (downloadThread != null) {
52
            downloadThread.interrupt();
53
        }
54
    }
55

  
56
    /**
57
     * Receives "messages" from the download thread, and passes them onto the
58
     * relevant {@link AsyncDownloader.Listener}
59
     * @param message
60
     */
61
    public void handleMessage(Message message) {
62
        switch (message.arg1) {
63
        case MSG_DOWNLOAD_COMPLETE:
64
            listener.onDownloadComplete();
65
            break;
66
        case MSG_DOWNLOAD_CANCELLED:
67
            listener.onDownloadCancelled();
68
            break;
69
        case MSG_ERROR:
70
            listener.onErrorDownloading(message.getData().getString(MSG_DATA));
71
            break;
72
        }
73
    }
74

  
75
    public int getBytesRead() {
76
        return downloader.getBytesRead();
77
    }
78

  
79
    public int getTotalBytes() {
80
        return downloader.getTotalBytes();
81
    }
82

  
83
    public interface Listener extends ProgressListener {
14
    interface Listener extends ProgressListener {
84 15
        void onErrorDownloading(String localisedExceptionDetails);
85 16
        void onDownloadComplete();
86 17
        void onDownloadCancelled();
87 18
    }
88 19

  
89
    private class DownloadThread extends Thread {
20
    int getBytesRead();
21
    int getTotalBytes();
22
    void download();
23
    void attemptCancel(boolean userRequested);
90 24

  
91
        public void run() {
92
            try {
93
                downloader.download();
94
                sendMessage(MSG_DOWNLOAD_COMPLETE);
95
            } catch (InterruptedException e) {
96
                sendMessage(MSG_DOWNLOAD_CANCELLED);
97
            } catch (IOException e) {
98
                Log.e(TAG, "I/O exception in download thread", e);
99
                Bundle data = new Bundle(1);
100
                data.putString(MSG_DATA, e.getLocalizedMessage());
101
                Message message = new Message();
102
                message.arg1 = MSG_ERROR;
103
                message.setData(data);
104
                AsyncDownloader.this.sendMessage(message);
105
            }
106
        }
107

  
108
        private void sendMessage(int messageType) {
109
            Message message = new Message();
110
            message.arg1 = messageType;
111
            AsyncDownloader.this.sendMessage(message);
112
        }
113
    }
114 25
}
F-Droid/src/org/fdroid/fdroid/net/AsyncDownloaderFromAndroid.java
23 23
 * A downloader that uses Android's DownloadManager to perform a download.
24 24
 */
25 25
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
26
public class AsyncDownloaderFromAndroid extends AsyncDownloader {
26
public class AsyncDownloaderFromAndroid implements AsyncDownloader {
27 27
    private final Context context;
28 28
    private final DownloadManager dm;
29 29
    private File localFile;
......
42 42
     * parameter to the constructor.
43 43
     */
44 44
    public AsyncDownloaderFromAndroid(Context context, Listener listener, String appName, String appId, String remoteAddress, File localFile) {
45
        super(null, listener);
46 45
        this.context = context;
47 46
        this.appName = appName;
48 47
        this.appId = appId;
F-Droid/src/org/fdroid/fdroid/net/DownloaderFactory.java
5 5

  
6 6
import java.io.File;
7 7
import java.io.IOException;
8
import java.net.MalformedURLException;
9 8
import java.net.URL;
10 9

  
11 10
public class DownloaderFactory {
......
62 61
        if (canUseDownloadManager(url)) {
63 62
            return new AsyncDownloaderFromAndroid(context, listener, title, id, url.toString(), destFile);
64 63
        } else {
65
            return new AsyncDownloader(create(context, url, destFile), listener);
64
            return new AsyncDownloadWrapper(create(context, url, destFile), listener);
66 65
        }
67 66
    }
68 67

  

Also available in: Unified diff