Android 多线程下载源码实现详细注释

来源:互联网 发布:sql的添加语句序列 编辑:程序博客网 时间:2024/05/17 07:53

贴出代码供参考:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    ><TextView      android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="下载地址"    /><TextViewandroid:id="@+id/downloadurl"android:layout_width="fill_parent"     android:layout_height="wrap_content" android:lines="5"/><TextView      android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="线程数"    /><EditTextandroid:id="@+id/downloadnum"android:layout_width="fill_parent"     android:layout_height="wrap_content" /><ProgressBarandroid:id="@+id/downloadProgressBar"android:layout_width="fill_parent" style="?android:attr/progressBarStyleHorizontal"    android:layout_height="wrap_content" /><TextViewandroid:id="@+id/downloadinfo"android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="下载进度 0"/><Buttonandroid:id="@+id/downloadbutton"android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="开始下载"/></LinearLayout>


配置文件设置:

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

主函数:
package com.sada.src;import java.io.File;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android.content.DialogInterface;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.os.SystemClock;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.TextView;public class DemoDownloadThreadActivity extends Activity { private String TAG = "Sada.DemoDownloadThreadActivity";private TextView downloadurl;   // 显示下载的地址private EditText downloadnum;   // 现在线程数 private Button downloadbutton;  // 下载按钮 private ProgressBar downloadProgressBar;   // 进度显示器 private TextView downloadinfo;      // 信息提示private int downloadedSize = 0;     // 当前下载文件的总大小private int fileSize = 0;           // 文件的大小private long downloadtime;   // 耗时// 网络文件的 下载地址//String mtempUrl = "http://219.138.125.22/myweb/mp3/CMP3/JH19.MP3";String mtempUrl = "http://file16.top100.cn/201105110911/AA5CC27CBE34DEB50A194581D1300881/Special_323149/%E8%8D%B7%E5%A1%98%E6%9C%88%E8%89%B2.mp3";    String filename = "";@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main); downloadurl = (TextView) findViewById(R.id.downloadurl);downloadurl.setText(mtempUrl);downloadnum = (EditText) findViewById(R.id.downloadnum);downloadinfo = (TextView) findViewById(R.id.downloadinfo);downloadbutton = (Button) findViewById(R.id.downloadbutton);downloadProgressBar = (ProgressBar) findViewById(R.id.downloadProgressBar);downloadProgressBar.setVisibility(View.VISIBLE);downloadProgressBar.setMax(100);downloadProgressBar.setProgress(0);downloadbutton.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {download();downloadtime = SystemClock.currentThreadTimeMillis();}});} private void download() {// 获取SD卡目录String dowloadDir = Environment.getExternalStorageDirectory() + "/threaddemodownload/";File file = new File(dowloadDir);//创建下载目录if (!file.exists()) {file.mkdirs();}//读取下载线程数,如果为空,则单线程下载int downloadTN = Integer.valueOf("".equals(downloadnum.getText().toString()) ? "1" : downloadnum.getText().toString());String fileName = "hetang.mp3";//开始下载前把下载按钮设置为不可用downloadbutton.setClickable(false);//进度条设为0downloadProgressBar.setProgress(0);//启动文件下载线程new downloadTask(mtempUrl, Integer.valueOf(downloadTN), dowloadDir + fileName).start();} Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {//当收到更新视图消息时,计算已完成下载百分比,同时更新进度条信息int progress = (Double.valueOf((downloadedSize * 1.0 / fileSize * 100))).intValue();if (progress == 100) {downloadbutton.setClickable(true);downloadinfo.setText("下载完成!");Dialog mdialog = new AlertDialog.Builder(DemoDownloadThreadActivity.this).setTitle("提示信息").setMessage("下载完成,总用时为:"+(SystemClock.currentThreadTimeMillis()-downloadtime)+"毫秒").setNegativeButton("确定", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}}).create();mdialog.show();} else {downloadinfo.setText("当前进度:" + progress + "%");}downloadProgressBar.setProgress(progress);} }; /** * 这边文件分块是按照线程数来分的 * 还有一个是按照一次最大的文件块来分的这也是实现多线程下载的一个方式 * @author WH1107022 * */public class downloadTask extends Thread {private int blockSize, downloadSizeMore;  // 每一个线程应该下载的数据大小,   整除后还剩下的数据大小private int threadNum = 5; // 默认是5条String urlStr, threadNo, fileName;  // 下载的地址    线程的序号   下载文件的命名 public downloadTask(String urlStr, int threadNum, String fileName) {this.urlStr = urlStr;this.threadNum = threadNum;this.fileName = fileName;} @Overridepublic void run() {FileDownloadThread[] fds = null;try {URL url = new URL(urlStr);HttpURLConnection conn = (HttpURLConnection) url.openConnection();//防止返回-1InputStream in = conn.getInputStream();//获取下载文件的总大小fileSize = conn.getContentLength();Log.i(TAG, "======================fileSize: " + fileSize);//计算每个线程要下载的数据量(一次下载大小)blockSize = fileSize / threadNum;// 解决整除后百分比计算误差downloadSizeMore = (fileSize % threadNum);if(downloadSizeMore > 0){ // 有剩余时Log.i(TAG, "---------downloadSizeMore = " + downloadSizeMore);fds = new FileDownloadThread[threadNum + 1];}else {Log.i(TAG, "---------downloadSizeMore = " + 0);fds = new FileDownloadThread[threadNum];}File file = new File(fileName);int i = 0;for (i = 0; i < threadNum; i ++) {Log.i(TAG, "======================i: " + i);//启动线程,分别下载自己需要下载的部分FileDownloadThread fdt = new FileDownloadThread(url, file, i * blockSize, (i + 1) * blockSize - 1);fdt.setName("Thread" + i);fdt.start();fds[i] = fdt;}// 剩余部分的下载if(downloadSizeMore > 0){Log.i(TAG, "======================i: " + i);//启动线程,分别下载自己需要下载的部分FileDownloadThread fdt = new FileDownloadThread(url, file, i * blockSize, (i * blockSize + downloadSizeMore) - 1);fdt.setName("Thread" + i);fdt.start();fds[i] = fdt;}boolean finished = false;while (!finished) {// 先把整除的余数搞定downloadedSize = 0;  // downloadSizeMorefinished = true;for (i = 0; i < fds.length; i++) {downloadedSize += fds[i].getDownloadSize();if (!fds[i].isFinished()) {finished = false;}}handler.sendEmptyMessage(0);//线程暂停一秒sleep(1000);}} catch (Exception e) {e.printStackTrace();} }}}

连接类:

package com.sada.src;import java.io.BufferedInputStream;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import android.util.Log;public class FileDownloadThread extends Thread {private final String TAG = "Sada.FileDownloadThread";private static final int BUFFER_SIZE = 1024;private URL url;private File file;private int startPosition;private int endPosition;private int curPosition;// 标识当前线程是否下载完成private boolean finished = false;private int downloadSize = 0;  // 本线程已经下载的文件的大小public FileDownloadThread(URL url, File file, int startPosition,int endPosition) {this.url = url;this.file = file;this.startPosition = startPosition;this.curPosition = startPosition;this.endPosition = endPosition;}@Overridepublic void run() {BufferedInputStream bis = null;RandomAccessFile fos = null;byte[] buf = new byte[BUFFER_SIZE];HttpURLConnection conn = null;try {conn = (HttpURLConnection) url.openConnection();conn.setAllowUserInteraction(true);// 设置当前线程下载的起止点conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);Log.i(TAG, Thread.currentThread().getName() + "  bytes=" + startPosition + "-" + endPosition);// 使用java中的RandomAccessFile 对文件进行随机读写操作fos = new RandomAccessFile(file, "rw");// 设置写文件的起始位置fos.seek(startPosition);bis = new BufferedInputStream(conn.getInputStream());// 开始循环以流的形式读写文件while (curPosition < endPosition) {int len = bis.read(buf, 0, BUFFER_SIZE);if (len == -1) {break;}fos.write(buf, 0, len);curPosition = curPosition + len;if (curPosition > endPosition) {downloadSize += len - (curPosition - endPosition) + 1;} else {downloadSize += len;}}// 下载完成设为truethis.finished = true;bis.close();fos.close();conn.disconnect();conn = null;bis = null;fos = null;buf = null;} catch (IOException e) {e.printStackTrace();}}public boolean isFinished() {return finished;}public int getDownloadSize() {return downloadSize;}}





原创粉丝点击