楼主三年磨剑(当然不是磨着一把剑),倾血奉献Android多线程下载Demo。有的人就问了“怎么写来写去还是Demo?”,因为老哥我实在太忙了, 每天写一点,写到现在也才写了个下载器,也就差下载管理类就是个完整的模块了。对于新手学习这已经足够了,不对,是完全足够了。
这不仅仅只是一个简单的Demo,这绝对是你前所未见的商业级别的范例,集支持多线程下载,断点续传,只使用wifi网络下载,显示下载速度,人性化提示 及超强的容错机制多功能于一体,绝对的实用,绝对的专业。
当然我写这个是为了下载apk的,大家稍微改一改就可以写成更通用的下载器。唯一有点不足的地方就是在Android上使用RandomAccessFile在创建大文件的时候 速度有些慢,导致前几秒的进度都为0。不知道有没有人可以帮我解决这个问题。
下面给出关键代码。
- package com.h3c.DownloadEngine;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.ArrayList;
- import android.content.Context;
- import android.os.Environment;
- import android.util.Log;
- import com.h3c.DownloadEngine.common.DownloaderErrorException;
- import com.h3c.DownloadEngine.common.EngineConstants;
- import com.h3c.DownloadEngine.common.EngineUtil;
- import com.h3c.DownloadEngine.common.EngineVariable;
- import com.h3c.DownloadEngine.db.EngineDBOperator;
- import com.h3c.DownloadEngine.entity.DownloadBean;
- public class Downloader {
- private final static String TAG = "Downloader";
- private final static byte[] lock_getFileSize = new byte[1];
- private final static byte[] lock_refresh_progress = new byte[1];
- private int mThreadCount = 4;// 默认子线程数为4个
- private int bufferSize = 1024 * 16; // 16K 一个块
- private DownloadBean mBean;// 注意,这里是dwonloader的bean不是其subBean
- private Context mContext;
- private DownloadEngineCallback mCallback;
- private EngineDBOperator mDBOper;
- private int mDoneThreadCount = 0;// 完成的线程数
- private int mState = EngineConstants.DOWNLOAD_STATE_INIT;// 下载器状态
- private ArrayList mBeans = new ArrayList(
- mThreadCount);
- public Downloader(DownloadBean bean, Context context,
- DownloadEngineCallback callback) throws DownloaderErrorException {
- this.mBean = bean;
- this.mContext = context;
- this.mCallback = callback;
- this.mDBOper = EngineDBOperator.getInstance(context);
- if (this.mDBOper != null) {
- if (this.mDBOper.isHasDownloadTaskByUrl(bean.url)) {// 如果此任务已经存放进数据库
- getDownloaderInfoFromDB(bean);
- } else {// 插入信息至数据库
- addDownloaderInfoToDB(bean);
- }
- } else {
- callBackError("Downloader错误,可能是EngineDBOperator为Null.");
- throw new DownloaderErrorException(
- "Downloader错误,可能是EngineDBOperator为Null.");
- }
- }
- public DownloadBean getDownloaderInfo() {
- return mBean;
- }
- public int getDownloaderState() {
- return mState;
- }
- /**
- * 请求初始化
- *
- * @param state
- */
- protected void setDownloaderState(int state) {
- mState = state;
- if (state == EngineConstants.DOWNLOAD_STATE_INIT) {
- mBean.currentPosition = 0;
- }
- }
- /**
- * 加入下载信息进入数据库,此方法用于刚刚初始化Downloader,且数据库中没有该任务的时候
- *
- * @param bean
- * @throws DownloaderErrorException
- */
- private void addDownloaderInfoToDB(DownloadBean bean)
- throws DownloaderErrorException {
- if (mState != EngineConstants.DOWNLOAD_STATE_INIT
- && mState != EngineConstants.DOWNLOAD_STATE_STOP
- && mState != EngineConstants.DOWNLOAD_STATE_ERROR) {
- callBackError("这个任务已经加入到数据库中了");
- throw new DownloaderErrorException("这个任务已经加入到数据库中了");
- }
- if (mDBOper != null) {
- long fileSize = bean.fileSize;
- if (mBeans.size() > 0) {
- mBeans.clear();
- }
- try {
- if (fileSize > 0) {// 判断传入的fileSize大小,如果大于0,就不用从网络中获取,直接初始化N个子下载器
- if (!hasSpaceInSDCard()) {
- return;
- }
- long range = fileSize / mThreadCount;// 文件分段值
- for (int i = 0; i mBean.fileSize) {
- mBean.fileSize = subBean.fileSize;
- }
- }
- if (mBean.fileSize
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?
立即登录/注册


微信扫码登录