这篇文章把F-droid的下载功能经过修改单独拿出来,而且做了一个demo。
希望能对自己后续起到借鉴作用。各位童鞋也可以去进行下载。
其实主要的思想有2个
1、使用接口进行回调
2、线程直接调用回调,由于无法知道主线程是否进行UI操作,所以把线程的回调进行了包装,使用Handler来发消息。保证不会崩溃。
项目下载地址:
http://download.csdn.net/download/leehu1987/7979253
一、定义一个接口,用于页面下载状态的监听;
<pre class="java" name="code">import java.io.Serializable; public interface DownloadListener { public static class Data implements Serializable { private static final long serialVersionUID = 8954447444334039739L; private long currentSize; private long totalSize; public Data() { } public Data(int currentSize, int totalSize) { this.currentSize = currentSize; this.totalSize = totalSize; } public long getCurrentSize() { return currentSize; } public void setCurrentSize(long currentSize) { this.currentSize = currentSize; } public long getTotalSize() { return totalSize; } public void setTotalSize(long totalSize) { this.totalSize = totalSize; } @Override public String toString() { return "Data [currentSize=" + currentSize + ", totalSize=" + totalSize + "]"; } } /** * * @param data * : transfer downloaded data */ public void onProgress(Data data); /** * * @param e * : exception */ public void onError(Exception e); public void onCompleted(); }
二、定义了一个Downloader父类,为了适应不同的下载,比如使用Http进行下载;使用代理进行下载等。
所以这个类是一个接口类,定义了一些基本的操作方法。
package com.example.downloader;
package com.example.downloader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import android.util.Log; public abstract class Downloader { private static final String TAG = "Downloader"; protected URL sourceUrl; private OutputStream outputStream; private DownloadListener downloadListener = null; private File outputFile; private final int BUFFER_SIZE = 1240000;//1M // /////////////////////////// public abstract InputStream getInputStream() throws IOException; public abstract int totalDownloadSize(); public abstract void download() throws IOException, InterruptedException; // /////////////////////////// Downloader(File destFile) throws FileNotFoundException, MalformedURLException { outputFile = destFile; outputStream = new FileOutputStream(outputFile); } public void setProgressListener(DownloadListener downloadListener) { this.downloadListener = downloadListener; } public File getFile() { return outputFile; } protected void downloadFromStream() throws IOException, InterruptedException { Log.d(TAG, "Downloading from stream"); InputStream input = null; try { input = getInputStream(); throwExceptionIfInterrupted(); copyInputToOutputStream(getInputStream()); } finally { try { if (outputStream != null) { outputStream.close(); } if (input != null) { input.close(); } } catch (IOException ioe) { // ignore } } // Even if we have completely downloaded the file, we should probably // respect // the wishes of the user who wanted to cancel us. throwExceptionIfInterrupted(); } /** * stop thread * * @throws InterruptedException */ private void throwExceptionIfInterrupted() throws InterruptedException { if (Thread.interrupted()) { Log.d(TAG, "Received interrupt, cancelling download"); throw new InterruptedException(); } } protected void copyInputToOutputStream(InputStream input) throws IOException, InterruptedException { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = 0; int totalBytes = totalDownloadSize(); throwExceptionIfInterrupted(); sendProgress(bytesRead, totalBytes); while (true) { int count = input.read(buffer); throwExceptionIfInterrupted(); bytesRead += count; sendProgress(bytesRead, totalBytes); if (count == -1) { Log.d(TAG, "Finished downloading from stream"); break; } outputStream.write(buffer, 0, count); } outputStream.flush(); } protected void sendProgress(int bytesRead, int totalBytes) { if (downloadListener != null) { DownloadListener.Data data = new DownloadListener.Data(bytesRead, totalBytes); downloadListener.onProgress(data); } } }
三、写了一个HttpDownloader。继承自Downloader
package com.example.downloader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpDownloader extends Downloader { protected HttpURLConnection connection; HttpDownloader(String source, File destFile) throws FileNotFoundException, MalformedURLException { super(destFile); sourceUrl = new URL(source); } @Override public void download() throws IOException, InterruptedException { setupConnection(); downloadFromStream(); } protected void setupConnection() throws IOException { if (connection != null) { return; } connection = (HttpURLConnection) sourceUrl.openConnection(); } @Override public InputStream getInputStream() throws IOException { setupConnection(); return connection.getInputStream(); } @Override public int totalDownloadSize() { return connection.getContentLength(); } }
四、需要一个控制方法
package com.example.downloader; import java.io.IOException; import com.example.downloader.DownloadListener.Data; import android.os.Handler; import android.os.Message; import android.util.Log; public class DownloadManager extends Handler { private DownloadThread downloadThread; private Downloader downloader; private DownloadListener listener; private static final int MSG_PROGRESS = 1; private static final int MSG_DOWNLOAD_COMPLETE = 2; private static final int MSG_DOWNLOAD_CANCELLED = 3; private static final int MSG_ERROR = 4; public DownloadManager(Downloader downloader, DownloadListener listener) { this.downloader = downloader; this.listener = listener; } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case MSG_PROGRESS: { DownloadListener.Data data = (Data) msg.obj; if (listener != null) { listener.onProgress(data); } break; } case MSG_DOWNLOAD_COMPLETE: { if (listener != null) { listener.onCompleted(); } break; } case MSG_DOWNLOAD_CANCELLED: { break; } case MSG_ERROR: { Exception e = (Exception) msg.obj; if (listener != null) { listener.onError(e); } break; } default: return; } } public void download() { downloadThread = new DownloadThread(); downloadThread.start(); } private class DownloadThread extends Thread implements<strong><span style="color:#ff6666;"> DownloadListener </span></strong>{ private static final String TAG = "DownloadThread"; public void run() { try { downloader.setProgressListener(this); downloader.download(); sendMessage(MSG_DOWNLOAD_COMPLETE); } catch (InterruptedException e) { sendMessage(MSG_DOWNLOAD_CANCELLED); } catch (IOException e) { Log.e(TAG, e.getMessage() + ": " + Log.getStackTraceString(e)); Message message = new Message(); message.what = MSG_ERROR; message.obj = e; sendMessage(message); } } private void sendMessage(int messageType) { Message message = new Message(); message.what = messageType; DownloadManager.this.sendMessage(message); } private void sendMessage(Message msg){ DownloadManager.this.sendMessage(msg); } @Override public void onProgress(Data data) { // TODO Message message = new Message(); message.what = MSG_PROGRESS; message.obj =data; DownloadManager.this.sendMessage(message); } @Override public void onError(Exception e) { // 在这里没有任何用,异常被捕获了 // do nothing } @Override public void onCompleted() { // do nothing } } }
五、页面如何使用
<pre class="html" name="code">package com.example.downloader; import java.io.File; import java.io.FileNotFoundException; import java.net.MalformedURLException; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity implements DownloadListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String dir = Environment.getExternalStorageDirectory() .getAbsolutePath() + File.separator + "test.apk"; File f = new File(dir); try { Downloader downloader = new HttpDownloader( "http://192.168.131.63/fengxing2.2.0.6.apk", f); DownloadManager m = new DownloadManager(downloader, this); m.download(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onProgress(Data data) { System.out.println("======"+data); } @Override public void onError(Exception e) { System.out.println("======"); e.printStackTrace(); } @Override public void onCompleted() { System.out.println("======下载完成"); } }
尚未完成的功能:
1、断点下载(需要数据库)
2、如果下载完成了,下次下载应该是不需要下载了。
原文地址:http://blog.csdn.net/leehu1987/article/details/39583497