Statistics
| Branch: | Tag: | Revision:

fdroidclient / F-Droid / src / org / fdroid / fdroid / net / AsyncDownloader.java @ 69ecaf02

History | View | Annotate | Download (3.76 KB)

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 org.fdroid.fdroid.ProgressListener;
9

    
10
import java.io.IOException;
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 {
21

    
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 {
84
        void onErrorDownloading(String localisedExceptionDetails);
85
        void onDownloadComplete();
86
        void onDownloadCancelled();
87
    }
88

    
89
    private class DownloadThread extends Thread {
90

    
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
}