首页 > 代码库 > F-droid 源码片段(二)下载模块整理

F-droid 源码片段(二)下载模块整理

 这篇文章把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 one rror(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 = http://www.mamicode.com/new DownloadListener.Data(bytesRead,>

 

三、写了一个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 = http://www.mamicode.com/(Data) msg.obj;>


五、页面如何使用

<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 one rror(Exception e) {
		System.out.println("======");
		e.printStackTrace();
		
	}

	@Override
	public void onCompleted() {
		System.out.println("======下载完成");
		
	}

}


尚未完成的功能:

1、断点下载(需要数据库)

2、如果下载完成了,下次下载应该是不需要下载了。

 

F-droid 源码片段(二)下载模块整理