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; | import java.io.IOException; | ||||||
| 
 | 
 | ||||||
| /** | public interface AsyncDownloader { | ||||||
|  * 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 { |  | ||||||
| 
 | 
 | ||||||
|     private static final String TAG = "AsyncDownloadWrapper"; |     interface Listener extends ProgressListener { | ||||||
| 
 |  | ||||||
|     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 { |  | ||||||
|         void onErrorDownloading(String localisedExceptionDetails); |         void onErrorDownloading(String localisedExceptionDetails); | ||||||
|         void onDownloadComplete(); |         void onDownloadComplete(); | ||||||
|         void onDownloadCancelled(); |         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. |  * A downloader that uses Android's DownloadManager to perform a download. | ||||||
|  */ |  */ | ||||||
| @TargetApi(Build.VERSION_CODES.GINGERBREAD) | @TargetApi(Build.VERSION_CODES.GINGERBREAD) | ||||||
| public class AsyncDownloaderFromAndroid extends AsyncDownloader { | public class AsyncDownloaderFromAndroid implements AsyncDownloader { | ||||||
|     private final Context context; |     private final Context context; | ||||||
|     private final DownloadManager dm; |     private final DownloadManager dm; | ||||||
|     private File localFile; |     private File localFile; | ||||||
| @ -42,7 +42,6 @@ public class AsyncDownloaderFromAndroid extends AsyncDownloader { | |||||||
|      * parameter to the constructor. |      * parameter to the constructor. | ||||||
|      */ |      */ | ||||||
|     public AsyncDownloaderFromAndroid(Context context, Listener listener, String appName, String appId, String remoteAddress, File localFile) { |     public AsyncDownloaderFromAndroid(Context context, Listener listener, String appName, String appId, String remoteAddress, File localFile) { | ||||||
|         super(null, listener); |  | ||||||
|         this.context = context; |         this.context = context; | ||||||
|         this.appName = appName; |         this.appName = appName; | ||||||
|         this.appId = appId; |         this.appId = appId; | ||||||
|  | |||||||
| @ -5,7 +5,6 @@ import android.os.Build; | |||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.net.MalformedURLException; |  | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
| 
 | 
 | ||||||
| public class DownloaderFactory { | public class DownloaderFactory { | ||||||
| @ -62,7 +61,7 @@ public class DownloaderFactory { | |||||||
|         if (canUseDownloadManager(url)) { |         if (canUseDownloadManager(url)) { | ||||||
|             return new AsyncDownloaderFromAndroid(context, listener, title, id, url.toString(), destFile); |             return new AsyncDownloaderFromAndroid(context, listener, title, id, url.toString(), destFile); | ||||||
|         } else { |         } 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
	 Peter Serwylo
						Peter Serwylo