ASP源码.NET源码PHP源码JSP源码JAVA源码DELPHI源码PB源码VC源码VB源码Android源码
当前位置:首页 >> 低调看直播体育app软件下载 >> Android开发 >> AsyncTask实现多任务多线程断点续传下载

AsyncTask实现多任务多线程断点续传下载(1/2)

来源:网络整理     时间:2015-10-16     关键词:文件下载,线程池,博客,Exception,断点续传

本篇文章主要介绍了"AsyncTask实现多任务多线程断点续传下载",主要涉及到文件下载,线程池,博客,Exception,断点续传方面的内容,对于Android开发感兴趣的同学可以参考一下: 这篇博客是AsyncTask下载系列的最后一篇文章,前面写了关于断点续传的和多线程下载的博客,这篇是在前两篇的基础上面实现的,有兴趣的可以去看下。  一、Asy...

这篇博客是AsyncTask下载系列的最后一篇文章,前面写了关于断点续传的和多线程下载的博客,这篇是在前两篇的基础上面实现的,有兴趣的可以去看下。

  一、AsyncTask实现断点续传

  二、AsyncTask实现多线程断点续传

  这里模拟应用市场app下载实现了一个Demo,因为只有一个界面,所以没有将下载放到Service中,而是直接在Activity中创建。在正式的项目中,下载都是放到Service中,然后通过BroadCast通知界面更新进度。

  上代码之前,先看下demo的运行效果图吧。

AsyncTask实现多任务多线程<strong>断点续传</strong>下载

下面我们看代码,这里每一个文件的下载定义一个Downloador来管理下载该文件的所有线程(暂停、下载等)。Downloador创建3个DownloadTask(这里定义每个文件分配3个线程下载)来下载该文件特定的起止位置。这里要通过文件的大小来计算每个线程所下载的起止位置,详细可以参考《AsyncTask实现多线程断点续传》。

  1、Downloador类

  1package com.bbk.lling.multitaskdownload.downloador;
  2  3import android.content.Context;
  4import android.content.Intent;
  5import android.os.AsyncTask;
  6import android.os.Bundle;
  7import android.os.Handler;
  8import android.os.Message;
  9import android.text.TextUtils;
 10import android.util.Log;
 11import android.widget.Toast;
 12 13import com.bbk.lling.multitaskdownload.beans.AppContent;
 14import com.bbk.lling.multitaskdownload.beans.DownloadInfo;
 15import com.bbk.lling.multitaskdownload.db.DownloadFileDAO;
 16import com.bbk.lling.multitaskdownload.db.DownloadInfoDAO;
 17import com.bbk.lling.multitaskdownload.utils.DownloadUtils;
 18 19import org.apache.http.HttpResponse;
 20import org.apache.http.client.HttpClient;
 21import org.apache.http.client.methods.HttpGet;
 22import org.apache.http.impl.client.DefaultHttpClient;
 23 24import java.util.ArrayList;
 25import java.util.List;
 26import java.util.concurrent.Executor;
 27import java.util.concurrent.Executors;
 28 29/** 30 * @Class: Downloador
 31 * @Description: 任务下载器
 32 * @author: lling(www.cnblogs.com/liuling)
 33 * @Date: 2015/10/13
 34*/ 35publicclass Downloador {
 36publicstaticfinal String TAG = "Downloador";
 37privatestaticfinalint THREAD_POOL_SIZE = 9;  //线程池大小为9 38privatestaticfinalint THREAD_NUM = 3;  //每个文件3个线程下载 39privatestaticfinalint GET_LENGTH_SUCCESS = 1;
 40publicstaticfinal Executor THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
 41 42private List tasks;
 43private InnerHandler handler = new InnerHandler();
 44 45private AppContent appContent; //待下载的应用 46privatelong downloadLength; //下载过程中记录已下载大小 47privatelong fileLength;
 48private Context context;
 49private String downloadPath;
 50 51public Downloador(Context context, AppContent appContent) {
 52this.context = context;
 53this.appContent = appContent;
 54this.downloadPath = DownloadUtils.getDownloadPath();
 55    }
 56 57/** 58     * 开始下载
 59*/ 60publicvoid download() {
 61if(TextUtils.isEmpty(downloadPath)) {
 62             Toast.makeText(context, "未找到SD卡", Toast.LENGTH_SHORT).show();
 63return;
 64        }
 65if(appContent == null) {
 66thrownew IllegalArgumentException("download content can not be null");
 67        }
 68new Thread() {
 69            @Override
 70publicvoid run() {
 71//获取文件大小 72                 HttpClient client = new DefaultHttpClient();
 73                 HttpGet request = new HttpGet(appContent.getUrl());
 74                 HttpResponse response = null;
 75try {
 76                     response = client.execute(request);
 77                     fileLength = response.getEntity().getContentLength();
 78                 } catch (Exception e) {
 79                    Log.e(TAG, e.getMessage());
 80                 } finally {
 81if (request != null) {
 82                        request.abort();
 83                    }
 84                }
 85//计算出该文件已经下载的总长度 86                 List lists = DownloadInfoDAO.getInstance(context.getApplicationContext())
 87                        .getDownloadInfosByUrl(appContent.getUrl());
 88for (DownloadInfo info : lists) {
 89                     downloadLength += info.getDownloadLength();
 90                }
 91 92//插入文件下载记录到数据库 93                DownloadFileDAO.getInstance(context.getApplicationContext()).insertDownloadFile(appContent);
 94                Message.obtain(handler, GET_LENGTH_SUCCESS).sendToTarget();
 95            }
 96        }.start();
 97    }
 98 99/**100     * 开始创建AsyncTask下载
101*/102privatevoid beginDownload() {
103         Log.e(TAG, "beginDownload" + appContent.getUrl());
104        appContent.setStatus(AppContent.Status.WAITING);
105long blockLength = fileLength / THREAD_NUM;
106for (int i = 0; i < THREAD_NUM; i++) {
107long beginPosition = i * blockLength;//每条线程下载的开始位置108long endPosition = (i + 1) * blockLength;//每条线程下载的结束位置109if (i == (THREAD_NUM - 1)) {
110                 endPosition = fileLength;//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度111            }
112             DownloadTask task = new DownloadTask(i, beginPosition, endPosition, this, context);
113            task.executeOnExecutor(THREAD_POOL_EXECUTOR, appContent.getUrl());
114if(tasks == null) {
115                 tasks = new ArrayList();
116            }
117            tasks.add(task);
118        }
119    }
120121/**122     * 暂停下载
123*/124publicvoid pause() {
125for (DownloadTask task : tasks) {
126if (task != null && (task.getStatus() == AsyncTask.Status.RUNNING || !task.isCancelled())) {
127                 task.cancel(true);
128            }
129        }
130        tasks.clear();
131        appContent.setStatus(AppContent.Status.PAUSED);
132        DownloadFileDAO.getInstance(context.getApplicationContext()).updateDownloadFile(appContent);
133    }
134135/**136     * 将已下载大小归零
137*/138protectedsynchronizedvoid resetDownloadLength() {
139this.downloadLength = 0;
140    }
141142/**143     * 添加已下载大小
144     * 多线程访问需加锁
145     * @param size
146*/147protectedsynchronizedvoid updateDownloadLength(long size){
148this.downloadLength += size;
149//通知更新界面150int percent = (int)((float)downloadLength * 100 / (float)fileLength);
151        appContent.setDownloadPercent(percent);
152if(percent == 100 || downloadLength == fileLength) {
153             appContent.setDownloadPercent(100); //上面计算有时候会有点误差,算到percent=99154            appContent.setStatus(AppContent.Status.FINISHED);
155            DownloadFileDAO.getInstance(context.getApplicationContext()).updateDownloadFile(appContent);
156        }
157         Intent intent = new Intent(Constants.DOWNLOAD_MSG);
158if(appContent.getStatus() == AppContent.Status.WAITING) {
159            appContent.setStatus(AppContent.Status.DOWNLOADING);
160        }
161         Bundle bundle = new Bundle();
162         bundle.putParcelable("appContent", appContent);
163        intent.putExtras(bundle);
164        context.sendBroadcast(intent);
165    }
166167protected String getDownloadPath() {
168return downloadPath;
169    }
170171privateclass InnerHandler extends Handler {
172        @Override
173publicvoid handleMessage(Message msg) {
174switch (msg.what) {
175case GET_LENGTH_SUCCESS :
176                    beginDownload();
177break;
178            }
179super.handleMessage(msg);
180        }
181    }
182 }

  2、DownloadTask类

  1package com.bbk.lling.multitaskdownload.downloador;
  2  3import android.content.Context;
  4import android.os.AsyncTask;
  5import android.util.Log;
  6  7import com.bbk.lling.multitaskdownload.beans.DownloadInfo;
  8import com.bbk.lling.multitaskdownload.db.DownloadInfoDAO;
  9 10import org.apache.http.Header;
 11import org.apache.http.HttpResponse;
 12import org.apache.http.client.HttpClient;
 13import org.apache.http.client.methods.HttpGet;
 14import org.apache.http.impl.client.DefaultHttpClient;
 15import org.apache.http.message.BasicHeader;
 16 17import java.io.File;
 18import java.io.IOException;
 19import java.io.InputStream;
 20import java.io.OutputStream;
 21import java.io.RandomAccessFile;
 22import java.net.MalformedURLException;
 23 24/** 25 * @Class: DownloadTask
 26 * @Description: 文件下载AsyncTask
 27 * @author: lling(www.cnblogs.com/liuling)
 28 * @Date: 2015/10/13
 29*/ 30publicclass DownloadTask extends AsyncTask {
 31privatestaticfinal String TAG = "DownloadTask";
 32 33privateint taskId;
 34privatelong beginPosition;
 35privatelong endPosition;
 36privatelong downloadLength;
 37private String url;
 38private Downloador downloador;
 39private DownloadInfoDAO downloadInfoDAO;
 40 41 42public DownloadTask(int taskId, long beginPosition, long endPosition, Downloador downloador,
 43                        Context context) {
 44this.taskId = taskId;
 45this.beginPosition = beginPosition;
 46this.endPosition = endPosition;
 47this.downloador = downloador;
 48         downloadInfoDAO = DownloadInfoDAO.getInstance(context.getApplicationContext());
 49    }
 50 51    @Override
 52protectedvoid onPreExecute() {
 53         Log.e(TAG, "onPreExecute");
 54    }
 55 56    @Override
 57protectedvoid onPostExecute(Long aLong) {
 58         Log.e(TAG, url + "taskId:" + taskId + "executed");
 59//        downloador.updateDownloadInfo(null); 60    }
 61 62    @Override
 63protectedvoid onProgressUpdate(Integer... values) {
 64//通知downloador增加已下载大小
 65//        downloador.updateDownloadLength(values[0]); 66    }
 67 68    @Override
 69protectedvoid onCancelled() {
 70         Log.e(TAG, "onCancelled");
 71//        downloador.updateDownloadInfo(null); 72    }
 73 74    @Override
 75protected Long doInBackground(String... params) {
 76//这里加判断的作用是:如果还处于等待就暂停了,运行到这里已经cancel了,就直接退出 77if(isCancelled()) {
 78returnnull;
 79        }
 80         url = params[0];
 81if(url == null) {
 82returnnull;
 83        }
 84         HttpClient client = new DefaultHttpClient();
 85         HttpGet request = new HttpGet(url);
 86        HttpResponse response;
 87        InputStream is;
 88         RandomAccessFile fos = null;
 89         OutputStream output = null;
 90 91         DownloadInfo downloadInfo = null;
 92try {
 93//本地文件 94             File file = new File(downloador.getDownloadPath() + File.separator + url.substring(url.lastIndexOf("/") + 1));
 95 96//获取之前下载保存的信息 97             downloadInfo = downloadInfoDAO.getDownloadInfoByTaskIdAndUrl(taskId, url);
 98//从之前结束的位置继续下载
 99//这里加了判断file.exists(),判断是否被用户删除了,如果文件没有下载完,但是已经被用户删除了,则重新下载100if(file.exists() && downloadInfo != null) {
101if(downloadInfo.isDownloadSuccess() == 1) {
102//下载完成直接结束103returnnull;
104                }
105                 beginPosition = beginPosition + downloadInfo.getDownloadLength();
106                 downloadLength = downloadInfo.getDownloadLength();
107            }
108if(!file.exists()) {
109//如果此task已经下载完,但是文件被用户删除,则需要重新设置已下载长度,重新下载110                downloador.resetDownloadLength();
111            }
112113//设置下载的数据位置beginPosition字节到endPosition字节114             Header header_size = new BasicHeader("Range", "bytes=" + beginPosition + "-" + endPosition);
115            request.addHeader(header_size);
116//执行请求获取下载输入流117             response = client.execute(request);
118             is = response.getEntity().getContent();
119120//创建文件输出流121             fos = new RandomAccessFile(file, "rw");
122//从文件的size以后的位置开始写入123            fos.seek(beginPosition);
124125byte buffer [] = newbyte[1024];
126int inputSize = -1;
127while((inputSize = is.read(buffer)) != -1) {
128                 fos.write(buffer, 0, inputSize);
129                 downloadLength += inputSize;
130                downloador.updateDownloadLength(inputSize);
131132//如果暂停了,需要将下载信息存入数据库133if (isCancelled()) {
134if(downloadInfo == null) {
135                         downloadInfo = new DownloadInfo();
136                    }
137                    downloadInfo.setUrl(url);
138                    downloadInfo.setDownloadLength(downloadLength);
139                    downloadInfo.setTaskId(taskId);
140                     downloadInfo.setDownloadSuccess(0);
141//保存下载信息到数据库142                    downloadInfoDAO.insertDownloadInfo(downloadInfo);
143returnnull;
144                }
145            }
146         } catch (MalformedURLException e) {
147            Log.e(TAG, e.getMessage());
148         } catch (IOException e) {
149            Log.e(TAG, e.getMessage());
150         } finally{
151try{
152if (request != null) {
153                    request.abort();
154                }
155if(output != null) {
156                    output.close();
157                }
158if(fos != null) {
159                    fos.close();
160                }
161             } catch(Exception e) {
162                e.printStackTrace();
163            }
164        }
165//执行到这里,说明该task已经下载完了166if(downloadInfo == null) {
167             downloadInfo = new DownloadInfo();
168        }
169        downloadInfo.setUrl(url);
170        downloadInfo.setDownloadLength(downloadLength);
171        downloadInfo.setTaskId(taskId);
172         downloadInfo.setDownloadSuccess(1);
173//保存下载信息到数据库174        downloadInfoDAO.insertDownloadInfo(downloadInfo);
175returnnull;
176    }
177 }

相关图片

相关文章