移动架构33_网络访问框架与数据库框架实现断点下载

本文详细介绍了一种基于Android的断点续传下载方案。该方案涵盖了网络框架、数据库存储及下载逻辑的设计与实现,包括自定义网络访问框架、面向对象数据库架构、下载状态管理和下载任务调度等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android移动架构汇总​​​​​​​
Demo地址:https://gitee.com/YuBaoZi/AndroidWenJianDuanDianXiaZai/blob/master/Download.rar
断点下载;
下载任务有优先级;
下载有回调;
网络自封装(fastjson和HttpClient)
数据库存储下载信息;
拓展性好,可以针对不同用户;

要点
掌握网络框架的搭建
掌握数据库框架的封装
掌握数据的下载
网络框架和数据库框架的联合封装使用
数据库作用:记录文件下载记录、文件总长度、文件是否已经下载,可以不用实时更改当前文件的下载进度,利用File的长度,作为下载文件的起始值
##一、实现数据库底层框架
具体详解:移动架构29_面向对象式手写数据库架构设计一

###1、定义注解
实现业务类属性与数据库表中列名的兼容(翻译以及防止出现关键字)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbTable {
    String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbFiled {
    String value();
}

###2、定义操作数据的接口和抽象类
封装表创建、增删改查的行为;业务生成sql语句、查询结果生成业务结果的逻辑是一致的,将其封装。

public interface IBaseDao<T> {
    /**
     * 插入数据
     * @param entity
     * @return
     */
    Long insert(T entity);

    /**
     *
     * @param entity
     * @param where
     * @return
     */
    int  update(T entity, T where);

    /**
     * 删除数据
     * @param where
     * @return
     */
    int  delete(T where);

    /**
     * 查询数据
     */
    List<T> query(T where);

    List<T> query(T where, String orderBy, Integer startIndex, Integer limit);

    List<T> query(String sql);
}
public abstract class BaseDao<T> implements IBaseDao<T> {
    private boolean isInit = false;
    protected SQLiteDatabase sqLiteDatabase;
    private Class<T> entityClass;
    private String tableName;
    private Map<String, Field> cacheMap;

    public String getTableName() {
        return tableName;
    }

    @Override
    public Long insert(T entity) {
        ContentValues contentValues = getContentValues(entity);
        long result = sqLiteDatabase.insert(tableName, null, contentValues);
        return result;
    }

    private ContentValues getContentValues(T entity) {
        ContentValues contentValues = new ContentValues();
        try {
            for (Map.Entry<String,Field> me:cacheMap.entrySet()){
                if(me.getValue().get(entity)==null){
                    continue;
                }
                contentValues.put(me.getKey(),me.getValue().get(entity).toString());
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return contentValues;
    }

    @Override
    public int update(T entity, T where) {
        ContentValues contentValues = getContentValues(entity);
        Condition condition = new Condition(getContentValues(where));
        int update = sqLiteDatabase.update(tableName, contentValues, condition.whereClause, condition.whereArgs);
        return update;
    }

    @Override
    public int delete(T where) {
        Condition condition = new Condition(getContentValues(where));
        int delete = sqLiteDatabase.delete(tableName, condition.whereClause, condition.whereArgs);
        return delete;
    }

    @Override
    public List<T> query(T where) {
        return query(where,null,null,null);
    }

    @Override
    public List<T> query(T where, String orderBy, Integer startIndex, Integer limit) {
        String limitString = null;
        if(startIndex!=null && limit!=null){
            limitString = startIndex+","+limit;
        }
        Condition condition = new Condition(getContentValues(where));
        Cursor cursor = null;
        List<T> result =new ArrayList<>();
        try
        {
            cursor = sqLiteDatabase.query(tableName, null,condition.getWhereClause(),condition.whereArgs,null,null,orderBy,limitString);
            result=getResult(cursor,where);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(cursor!=null){
                cursor.close();
            }
        }
        return result;
    }

    protected List<T> getResult(Cursor cursor, T where) {
        ArrayList list = new ArrayList();
        Object item;
        while(cursor.moveToNext()){
            try {
                item = where.getClass().newInstance();
                Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
                while(iterator.hasNext()){
                    Map.Entry<String, Field> entry = iterator.next();
                    String colmunName = entry.getKey();
                    Field field = entry.getValue();
                    int columnIndex = cursor.getColumnIndex(colmunName);
                    Class type = field.getType();
                    if(columnIndex!=-1){
                        if(type==String.class){
                            field.set(item,cursor.getString(columnIndex));
                        }else if(type==Double.class){
                            field.set(item,cursor.getDouble(columnIndex));
                        }else if(type== Integer.class){
                            field.set(item,cursor.getInt(columnIndex));
                        }else if(type == Long.class){
                            field.set(item,cursor.getLong(columnIndex));
                        }else if(type == byte[].class){
                            field.set(item,cursor.getBlob(columnIndex));
                        }else{
                            /**
                             * 不支持的类型
                             */
                            continue;
                        }
                    }
                }
                list.add(item);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    protected synchronized boolean init(Class<T> entity, SQLiteDatabase sqLiteDatabase) {
        if (!isInit) {
            this.sqLiteDatabase = sqLiteDatabase;
            this.entityClass = entity;
            if (entity.getAnnotation(DbTable.class) == null) {
                tableName = entity.getClass().getSimpleName();
            } else {
                tableName = entity.getAnnotation(DbTable.class).value();
            }
            if (!sqLiteDatabase.isOpen()) {
                return false;
            }

            if (!TextUtils.isEmpty(createTable())) {
                sqLiteDatabase.execSQL(createTable());
            }
            cacheMap = new HashMap<>();
            initCatchMap();
            isInit = true;
        }
        return isInit;
    }

    /**
     * 维护映射关系
     */
    private void initCatchMap() {
        String sql = "select * from " + this.tableName + " limit 1,0";
        Cursor cursor = null;
        try {
            cursor = sqLiteDatabase.rawQuery(sql, null);
            /**
             * 表的列名数组
             */
            String[] columnNames = cursor.getColumnNames();
            /**
             * 拿到Filed数组
             */
            Field[] columnFields = entityClass.getFields();
            for (Field filed : columnFields) {
                filed.setAccessible(true);

                Field columnFiled = null;
                String colmunName = null;
                /**
                 * 开始找对应关系
                 */
                for (String cn : columnNames) {
                    String filedName = null;
                    if(filed.getAnnotation(DbFiled.class)!=null){
                        filedName = filed.getAnnotation(DbFiled.class).value();
                    }else {
                        filedName = filed.getName();
                    }
                    if(cn.equals(filedName)){
                        columnFiled = filed;
                        colmunName = cn;
                        break;
                    }
                }
                //找到了对应关系
                if(columnFiled!=null){
                    cacheMap.put(colmunName,columnFiled);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cursor.close();
        }
    }

    public abstract String createTable();


    class Condition{
        /**
         * 查询条件
         * name=? && password =?
         */
        private String whereClause;

        private  String[] whereArgs;
        public Condition(ContentValues whereClause) {
            ArrayList list=new ArrayList();
            StringBuilder stringBuilder=new StringBuilder();

            stringBuilder.append(" 1=1 ");

            Set keys=whereClause.keySet();
            Iterator iterator=keys.iterator();
            while (iterator.hasNext())
            {
                String key= (String) iterator.next();
                String value= (String) whereClause.get(key);

                if (value!=null)
                {
                    /*
                    拼接条件查询语句
                    1=1 and name =? and password=?
                     */
                    stringBuilder.append(" and "+key+" =?");
                    /**
                     * ?----》value
                     */
                    list.add(value);
                }
            }
            this.whereClause=stringBuilder.toString();
            this.whereArgs= (String[]) list.toArray(new String[list.size()]);

        }

        public String[] getWhereArgs() {
            return whereArgs;
        }

        public String getWhereClause() {
            return whereClause;
        }
    }
}

###3、定义提供操作数据库类的工厂类
校验数据库创建、根据类型提供操作表的操作类

public class BaseDaoFactory {

    private String sqlitDatabasePath;

    private SQLiteDatabase sqLiteDatabase;

    private static BaseDaoFactory instance = new BaseDaoFactory();

    private BaseDaoFactory() {
        sqlitDatabasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/teacher.db";
        openDatabase();
    }

    public synchronized <T extends BaseDao<M>, M> T getDataHelper(Class<T> clazz, Class<M> entityClass) {
        T baseDao = null;
        try {
            baseDao = clazz.newInstance();
            baseDao.init(entityClass, sqLiteDatabase);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return baseDao;
    }


    private void openDatabase() {
        sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqlitDatabasePath, null);

    }

    public static BaseDaoFactory getInstance() {
        return instance;
    }

}

##二、定义网络框架
具体详解:移动架构32_自定义网络访问框架开发
###1、定义网络请求的接口

public interface IHttpListener {
    /**
     * 网络访问
     * 处理结果  回调
     * @param httpEntity
     */
    void onSuccess(HttpEntity httpEntity);

    void onFail();

    void addHttpHeader(Map<String,String> headerMap);
}
public interface IHttpService {
    /**
     * 设置url
     * @param url
     */
    void setUrl(String url);

    /**
     * 执行获取网络
     */
    void excute();

    /**
     * 设置处理接口
     * @param httpListener
     */
    void setHttpListener(IHttpListener httpListener);

    /**
     * 设置请求参数
     * String  1
     * byte[]  2
     *
     */
    void setRequestData(byte[] requestData);

    void pause();

    /**
     *
     * 以下的方法是 额外添加的
     * 获取请求头的map
     * @return
     */
     Map<String,String> getHttpHeadMap();

     boolean cancle();

     boolean isCancle();

     boolean isPause();


}

###2、请求与回调封装到一个类中

public class RequestHodler<T> {
    /**
     * 执行下载类
     */
    private IHttpService httpService;
    /**
     * 获取数据  回调结果的类
     */
    private IHttpListener httpListener;
    /**
     * 请求参数对应的实体
     */
    private T requestInfo;

    private String url;

    public IHttpService getHttpService() {
        return httpService;
    }

    public void setHttpService(IHttpService httpService) {
        this.httpService = httpService;
    }

    public IHttpListener getHttpListener() {
        return httpListener;
    }

    public void setHttpListener(IHttpListener httpListener) {
        this.httpListener = httpListener;
    }

    public T getRequestInfo() {
        return requestInfo;
    }

    public void setRequestInfo(T requestInfo) {
        this.requestInfo = requestInfo;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

###3、定义管理网络请求的线程池

public class ThreadPoolManager {
    private static final String TAG ="ThreadPoolManager" ;
    private static  ThreadPoolManager instance=new ThreadPoolManager();

    private LinkedBlockingQueue<Future<?>> taskQuene=new LinkedBlockingQueue<>();

    private ThreadPoolExecutor threadPoolExecutor;
    public static ThreadPoolManager getInstance() {
        return instance;
    }
    private ThreadPoolManager()
    {
        threadPoolExecutor=new ThreadPoolExecutor(4,10,10, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(4), handler);
        threadPoolExecutor.execute(runable);
    }

    public <T> boolean removeTask(FutureTask futureTask)
    {
        boolean result=false;
        /**
         * 阻塞式队列是否含有线程
         */
        if(taskQuene.contains(futureTask))
        {
            taskQuene.remove(futureTask);
        }else
        {
            result=threadPoolExecutor.remove(futureTask);
        }
        return  result;
    }


    private Runnable runable =new Runnable() {
        @Override
        public void run() {
            while (true)
            {
                FutureTask futrueTask=null;

                try {
                    /**
                     * 阻塞式函数
                     */
                    Log.i(TAG,"等待队列     "+taskQuene.size());
                    futrueTask= (FutureTask) taskQuene.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(futrueTask!=null)
                {
                    threadPoolExecutor.execute(futrueTask);
                }
                Log.i(TAG,"线程池大小      "+threadPoolExecutor.getPoolSize());
            }
        }
    };
    public <T> void execte(FutureTask<T> futureTask) throws InterruptedException {
        taskQuene.put(futureTask);
    }

    private RejectedExecutionHandler handler=new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                taskQuene.put(new FutureTask<Object>(r,null) {
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
}

###4、定义异步操作作为网络请求实现的平台

public class HttpTask<T> implements Runnable {
    private IHttpService httpService;
    private FutureTask futureTask;
    public HttpTask(RequestHodler<T> requestHodler)
    {
        httpService=requestHodler.getHttpService();
        httpService.setHttpListener(requestHodler.getHttpListener());
        httpService.setUrl(requestHodler.getUrl());
        //增加方法
        IHttpListener httpListener=requestHodler.getHttpListener();
        httpListener.addHttpHeader(httpService.getHttpHeadMap());
        try {
            T request=requestHodler.getRequestInfo();
            if(request!=null)
            {
                String requestInfo= JSON.toJSONString(request);
                httpService.setRequestData(requestInfo.getBytes("UTF-8"));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        httpService.excute();
    }
    /**
     * 新增方法
     */
    public void start()
    {
        futureTask=new FutureTask(this,null);
        try {
            ThreadPoolManager.getInstance().execte(futureTask);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    /**
     * 新增方法
     */
    public  void pause()
    {
        httpService.pause();
        if(futureTask!=null)
        {
            ThreadPoolManager.getInstance().removeTask(futureTask);
        }

    }
}

##三、在网络与数据库框架的基础上再次封装
###1、定义下载状态、优先级、停止模式

public enum  DownloadStatus {
    waitting(0),

    starting(1),

    downloading(2),

    pause(3),

    finish(4),

    failed(5)
    ;

    private int value;
    private   DownloadStatus(int value)
    {
        this.value=value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}
public enum Priority
{
    /**
     * 手动下载的优先级
     */
    low(0),

    /**
     * 主动推送资源的手动恢复的优先级
     */
    middle(1),

    /**
     * 主动推送资源的优先级
     */
    high(2);
    Priority(int value)
    {
        this.value = value;
    }

    private int value;

    public int getValue()
    {
        return value;
    }

    public void setValue(int value)
    {
        this.value = value;
    }

    public static Priority getInstance(int value)
    {
        for (Priority priority : Priority.values())
        {
            if (priority.getValue() == value)
            {
                return priority;
            }
        }
        return Priority.middle;
    }
}
public enum DownloadStopMode
{
    /**
     * 后台根据下载优先级调度自动停止下载任务
     */
    auto(0),

    /**
     * 手动停止下载任务
     */
    hand(1);
    DownloadStopMode(Integer value)
    {
        this.value = value;
    }

    /**
     * 值
     */
    private Integer value;

    public Integer getValue()
    {
        return value;
    }

    public void setValue(Integer value)
    {
        this.value = value;
    }

    public static DownloadStopMode getInstance(int value)
    {
        for (DownloadStopMode mode : DownloadStopMode.values())
        {
            if (mode.getValue() == value)
            {
                return mode;
            }
        }
        return DownloadStopMode.auto;
    }
}

###2、定义业务Bean及其基类

public class BaseEntity<T> implements Serializable{
	    private static final long serialVersionUID = 1L;
    public BaseEntity() {
    }

    public T copy() {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;

        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);

            ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            Object result = objectInputStream.readObject();
            return (T) result;
        } catch (IOException io) {
            io.printStackTrace();
        } catch (ClassNotFoundException classNot) {
            classNot.printStackTrace();
        } finally {
            if(byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException io) {
                    io.printStackTrace();
                }
            }

            if(objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException io) {
                    io.printStackTrace();
                }
            }

        }

        return null;
    }


}
@DbTable("t_downloadInfo")
public class DownloadItemInfo extends  BaseEntity<DownloadItemInfo>  {

    public long currentLength;

    public long totalLength;

    public  transient  HttpTask httpTask;
    /**
     * 下载id
     */
    public Integer id;

    /**
     * 下载url
     */
    public String url;

    /**
     * 下载存储的文件路径
     */
    public String filePath;

    /**
     * 下载文件显示名
     */
    public String displayName;
    /**
     * 下载文件总大小
     */
    public Long totalLen;

    /**
     * 下载文件当前大小
     */
    public Long currentLen;

    /**
     * 下载开始时间
     */
    public String startTime;

    /**
     * 下载结束时间
     */
    public String finishTime;

    /**
     * 用户id
     */
    public String userId;

    /**
     * 下载任务类型
     */
    public String httpTaskType;

    /**
     * 下载优先级
     */
    public Integer priority;

    /**
     * 下载停止模式
     */
    public Integer stopMode;


    //下载的状态
    public Integer status;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }


    public Long getTotalLen() {
        return totalLen;
    }

    public void setTotalLen(Long totalLen) {
        this.totalLen = totalLen;
    }

    public Long getCurrentLen() {
        return currentLen;
    }

    public void setCurrentLen(Long currentLen) {
        this.currentLen = currentLen;
    }


    public void setFinishTime(String finishTime) {
        this.finishTime = finishTime;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getHttpTaskType() {
        return httpTaskType;
    }

    public void setHttpTaskType(String httpTaskType) {
        this.httpTaskType = httpTaskType;
    }

    public Integer getPriority() {
        return priority;
    }

    public void setPriority(Integer priority) {
        this.priority = priority;
    }

    public Integer getStopMode() {
        return stopMode;
    }

    public void setStopMode(Integer stopMode) {
        this.stopMode = stopMode;
    }

    public DownloadItemInfo(String url, String filePath) {
        this.url = url;
        this.filePath = filePath;
    }

    public DownloadItemInfo( ) {
    }




    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public long getCurrentLength() {
        return currentLength;
    }

    public void setCurrentLength(long currentLength) {
        this.currentLength = currentLength;
    }

    public long getTotalLength() {
        return totalLength;
    }

    public void setTotalLength(long totalLength) {
        this.totalLength = totalLength;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public HttpTask getHttpTask() {
        return httpTask;
    }

    public void setHttpTask(HttpTask httpTask) {
        this.httpTask = httpTask;
    }

    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
}

###3、定义下载的接口

public interface IDownLitener  extends IHttpListener{

    void setHttpServive(IHttpService  httpServive);


    void  setCancleCalle();


    void  setPuaseCallble();

}
/**
 * 断点续传监听接口
 */
public interface IDownloadCallable
{

    /**
     * 新增下载任务的监听
     *
     * @param downloadId
     *            下载id
     */
    void onDownloadInfoAdd(int downloadId);

    /**
     * 删除下载任务的监听
     *
     * @param downloadId
     *            下载id
     */
    void onDownloadInfoRemove(int downloadId);

    /**
     * 下载状态变化
     *
     * @param downloadId
     *            下载id
     * @param status
     *            下载状态
     */

    void onDownloadStatusChanged(int downloadId, DownloadStatus status);

    /**
     * 获取了下载文件总的长度
     *
     * @param downloadId
     *            下载id
     * @param totalLength
     *            下载文件总的长度
     */
    void onTotalLengthReceived(int downloadId, long totalLength);

    /**
     * 下载进度
     *
     * @param downloadId
     *            下载id
     * @param downloadpercent
     *            下载的百分比
     * @param speed
     *            下载速度
     */
    void onCurrentSizeChanged(int downloadId, double downloadpercent, long speed);

    /**
     * 下载成功
     *
     * @param downloadId
     *            下载id
     */
    void onDownloadSuccess(int downloadId);

    /**
     * 下载失败监听
     *
     * @param downloadId
     *            下载id
     * @param errorCode
     *            下载错误码
     * @param errorMsg
     *            下载错误信息
     */
    void onDownloadError(int downloadId, int errorCode, String errorMsg);
}
public interface IDownloadServiceCallable {
    void onDownloadStatusChanged(DownloadItemInfo downloadItemInfo);

    void onTotalLengthReceived(DownloadItemInfo downloadItemInfo);

    void onCurrentSizeChanged(DownloadItemInfo downloadItemInfo, double downLenth, long speed);

    void onDownloadSuccess(DownloadItemInfo downloadItemInfo);

    void onDownloadPause(DownloadItemInfo downloadItemInfo);

    void onDownloadError(DownloadItemInfo downloadItemInfo, int var2, String var3);
}

###4、实现数据具体操作

public class DownLoadDao extends BaseDao<DownloadItemInfo> {
    /**
     * 保存应该下载的集合
     * 不包括已经下载成功的
     */
    private List<DownloadItemInfo> downloadItemInfoList=
            Collections.synchronizedList(new ArrayList<DownloadItemInfo>());

    private DownloadInfoComparator downloadInfoComparator=new DownloadInfoComparator();

    @Override
    public String createTable() {
        return "create table if not exists  t_downloadInfo(" + "id Integer primary key, " + "url TEXT not null," + "filePath TEXT not null, " + "displayName TEXT, " + "status Integer, " + "totalLen Long, " + "currentLen Long," + "startTime TEXT," + "finishTime TEXT," + "userId TEXT, " + "httpTaskType TEXT," + "priority  Integer," + "stopMode Integer," + "downloadMaxSizeKey TEXT," + "unique(filePath))";
    }

    @Override
    public List<DownloadItemInfo> query(String sql) {
        return null;
    }
    /**
     * id
     */
    /**
     * 生成下载id
     *
     * @return 返回下载id
     */
    private Integer generateRecordId()
    {
        int maxId = 0;
        String sql = "select max(id)  from " +getTableName() ;
        synchronized (DownLoadDao.class)
        {
            Cursor cursor = this.sqLiteDatabase.rawQuery(sql,null);
            if(cursor.moveToNext())
            {
                String[] colmName=cursor.getColumnNames();

                int index=cursor.getColumnIndex("max(id)");
                if(index!=-1)
                {
                    Object value =cursor.getInt(index);
                    if (value != null)
                    {
                        maxId = Integer.parseInt(String.valueOf(value));
                    }
                }
            }

        }
        return maxId + 1;
    }

    /**
     * 根据下载地址和下载文件路径查找下载记录
     *
     * @param url
     *            下载地址
     * @param filePath
     *            下载文件路径
     * @return
     */
    public DownloadItemInfo findRecord(String url, String filePath)
    {
        synchronized (DownLoadDao.class)
        {
            for (DownloadItemInfo record : downloadItemInfoList)
            {
                if (record.getUrl().equals(url) && record.getFilePath().equals(filePath))
                {
                    return record;
                }
            }
            /**
             * 内存集合找不到
             * 就从数据库中查找
             */
            DownloadItemInfo where = new DownloadItemInfo();
            where.setUrl(url);
            where.setFilePath(filePath);
            List<DownloadItemInfo> resultList = super.query(where);
            if (resultList.size() > 0)
            {
                return resultList.get(0);
            }
            return null;
        }

    }

    /**
     * 根据 下载文件路径查找下载记录
     *
     *            下载地址
     * @param filePath
     *            下载文件路径
     * @return
     */
    public List<DownloadItemInfo> findRecord(String filePath)
    {
        synchronized (DownLoadDao.class)
        {
            DownloadItemInfo where = new DownloadItemInfo();
            where.setFilePath(filePath);
            List<DownloadItemInfo> resultList = super.query(where);
            return resultList;
        }

    }

    /**
     * 添加下载记录
     *
     * @param url
     *            下载地址
     * @param filePath
     *            下载文件路径
     * @param displayName
     *            文件显示名
     * @param priority
     *            小组优先级
     *            TODO
     * @return 下载id
     */
    public int addRecrod(String url, String filePath, String displayName , int priority)
    {
        synchronized (DownLoadDao.class)
        {
            DownloadItemInfo existDownloadInfo = findRecord(url, filePath);
            if (existDownloadInfo == null)
            {
                DownloadItemInfo record = new DownloadItemInfo();
                record.setId(generateRecordId());
                record.setUrl(url);
                record.setFilePath(filePath);
                record.setDisplayName(displayName);
                record.setStatus(DownloadStatus.waitting.getValue());
                record.setTotalLen(0L);
                record.setCurrentLen(0L);
                java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
                record.setStartTime(dateFormat.format(new Date()));
                record.setFinishTime("0");
                record.setPriority(priority);
                super.insert(record);
                downloadItemInfoList.add(record);
                return record.getId();
            }
            return -1;
        }
    }

    /**
     * 更新下载记录
     *
     * @param record
     *            下载记录
     * @return
     */
    public int updateRecord(DownloadItemInfo record)
    {
        DownloadItemInfo where = new DownloadItemInfo();
        where.setId(record.getId());
        int result = 0;
        synchronized (DownLoadDao.class)
        {
            try
            {
                result = super.update(record, where);
            }
            catch (Throwable e)
            {
            }
            if (result > 0)
            {
                for (int i = 0; i < downloadItemInfoList.size(); i++)
                {
                    if (downloadItemInfoList.get(i).getId().intValue() == record.getId())
                    {
                        downloadItemInfoList.set(i, record);
                        break;
                    }
                }
            }
        }
        return result;
    }
    /**
     * 根据下载地址和下载文件路径查找下载记录
     *
     *            下载地址
     * @param filePath
     *            下载文件路径
     * @return
     */
    public DownloadItemInfo findSigleRecord(String filePath)
    {
        List<DownloadItemInfo> downloadInfoList = findRecord(filePath);
        if(downloadInfoList.isEmpty())
        {
            return null;
        }
        return downloadInfoList.get(0);
    }
    /**
     * 根据id查找下载记录对象
     *
     * @param recordId
     * @return
     */
    public DownloadItemInfo findRecordById(int recordId)
    {
        synchronized (DownLoadDao.class)
        {
            for (DownloadItemInfo record :downloadItemInfoList)
            {
                if (record.getId() == recordId)
                {
                    return record;
                }
            }

            DownloadItemInfo where = new DownloadItemInfo();
            where.setId(recordId);
            List<DownloadItemInfo> resultList = super.query(where);
            if (resultList.size() > 0)
            {
                return resultList.get(0);
            }
            return null;
        }

    }
    /**
     * 根据id从内存中移除下载记录
     *
     * @param id
     *            下载id
     * @return true标示删除成功,否则false
     */
    public boolean removeRecordFromMemery(int id)
    {
        synchronized (DownloadItemInfo.class)
        {
            for (int i = 0; i < downloadItemInfoList.size(); i++)
            {
                if (downloadItemInfoList.get(i).getId() == id)
                {
                    downloadItemInfoList.remove(i);
                    break;
                }
            }
            return true;
        }
    }

    /**
     * 比较器
     */
    class DownloadInfoComparator implements Comparator<DownloadItemInfo>
    {
        @Override
        public int compare(DownloadItemInfo lhs, DownloadItemInfo rhs)
        {
            return rhs.getId() - lhs.getId();
        }
    }
}

###5、实现下载和回调的接口

public class DownLoadLitener  implements IDownLitener{

    private  DownloadItemInfo downloadItemInfo;

    private File file;
    protected  String url;
    private long breakPoint;
    private IDownloadServiceCallable downloadServiceCallable;

    private IHttpService httpService;
    /**
     * 得到主线程
     */
    private Handler handler=new Handler(Looper.getMainLooper());
    public DownLoadLitener(DownloadItemInfo downloadItemInfo,
                           IDownloadServiceCallable downloadServiceCallable,
                           IHttpService httpService) {
        this.downloadItemInfo = downloadItemInfo;
        this.downloadServiceCallable = downloadServiceCallable;
        this.httpService = httpService;
        this.file=new File(downloadItemInfo.getFilePath());
        /**
         * 得到已经下载的长度
         */
        this.breakPoint=file.length();
    }

    /**
     * 2
     * @param headerMap
     */
    public void addHttpHeader(Map<String,String> headerMap)
    {
        long length=getFile().length();
        if(length>0L)
        {
            headerMap.put("RANGE","bytes="+length+"-");
        }

    }
    public DownLoadLitener(DownloadItemInfo downloadItemInfo) {
        this.downloadItemInfo = downloadItemInfo;
    }

    @Override
    public void setHttpServive(IHttpService httpServive) {
        this.httpService=httpServive;
    }

    /**
     * 设置取消接口
     */
    @Override
    public void setCancleCalle() {

    }

    @Override
    public void setPuaseCallble() {

    }

    @Override
    public void onSuccess(HttpEntity httpEntity) {
        InputStream inputStream = null;
        try {
            inputStream = httpEntity.getContent();
        } catch (IOException e) {
            e.printStackTrace();
        }

        long startTime = System.currentTimeMillis();
        //用于计算每秒多少k
        long speed = 0L;
        //花费时间
        long useTime = 0L;
        //下载的长度
        long getLen = 0L;
        //接受的长度
        long receiveLen = 0L;
        boolean bufferLen = false;
        //得到下载的长度
        long dataLength = httpEntity.getContentLength();
        //单位时间下载的字节数
        long calcSpeedLen = 0L;
        //总数
        long totalLength = this.breakPoint + dataLength;
        //更新数量
        this.receviceTotalLength(totalLength);
        //更新状态
        this.downloadStatusChange(DownloadStatus.downloading);
        byte[] buffer = new byte[512];
        int count = 0;
        long currentTime = System.currentTimeMillis();
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;

        try {
            if (!makeDir(this.getFile().getParentFile())) {
                downloadServiceCallable.onDownloadError(downloadItemInfo,1,"创建文件夹失败");
            } else {
                fos = new FileOutputStream(this.getFile(), true);
                bos = new BufferedOutputStream(fos);
                int length = 1;
                while ((length = inputStream.read(buffer)) != -1) {
                    if (this.getHttpService().isCancle()) {
                        downloadServiceCallable.onDownloadError(downloadItemInfo, 1, "用户取消了");
                        return;
                    }

                    if (this.getHttpService().isPause()) {
                        downloadServiceCallable.onDownloadError(downloadItemInfo, 2, "用户暂停了");
                        return;
                    }
                    bos.write(buffer, 0, length);
                    getLen += (long) length;
                    receiveLen += (long) length;
                    calcSpeedLen += (long) length;
                    ++count;
                    if (receiveLen * 10L / totalLength >= 1L || count >= 5000) {
                        currentTime = System.currentTimeMillis();
                        useTime = currentTime - startTime;
                        startTime = currentTime;
                        speed = 1000L * calcSpeedLen / useTime;
                        count = 0;
                        calcSpeedLen = 0L;
                        receiveLen = 0L;
                        //应该保存数据库
                        this.downloadLengthChange(this.breakPoint + getLen, totalLength, speed);
                    }
                }
                bos.close();
                inputStream.close();
                if (dataLength != getLen) {
                    downloadServiceCallable.onDownloadError(downloadItemInfo, 3, "下载长度不相等");
                } else {
                    this.downloadLengthChange(this.breakPoint + getLen, totalLength, speed);
                    this.downloadServiceCallable.onDownloadSuccess(downloadItemInfo.copy());
                }
            }
        } catch (IOException ioException) {
            if (this.getHttpService() != null) {
//                this.getHttpService().abortRequest();
            }
            return;
        } catch (Exception e) {
            if (this.getHttpService() != null) {
//                this.getHttpService().abortRequest();
            }
        } finally {
            try {
                if (bos != null) {
                    bos.close();
                }

                if (httpEntity != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

    /**
     * 创建文件夹的操作
     * @param parentFile
     * @return
     */
    private boolean makeDir(File parentFile) {
        return parentFile.exists()&&!parentFile.isFile()
                ?parentFile.exists()&&parentFile.isDirectory():
                parentFile.mkdirs();
    }


    private void downloadLengthChange(final long downlength, final long totalLength, final long speed) {
        downloadItemInfo.setCurrentLength(downlength);
        if(downloadServiceCallable!=null)
        {
            DownloadItemInfo copyDownItenIfo=downloadItemInfo.copy();
            synchronized (this.downloadServiceCallable)
            {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        downloadServiceCallable.onCurrentSizeChanged(downloadItemInfo,(double) downlength/(double)totalLength,speed);
                    }
                });
            }

        }

    }

    /**
     * 更改下载时的状态
     * @param downloading
     */
    private void downloadStatusChange(DownloadStatus downloading) {
        downloadItemInfo.setStatus(downloading.getValue());
        final DownloadItemInfo copyDownloadItemInfo=downloadItemInfo.copy();
        if(downloadServiceCallable!=null)
        {
            synchronized (this.downloadServiceCallable)
            {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        downloadServiceCallable.onDownloadStatusChanged(copyDownloadItemInfo);
                    }
                });
            }
        }
    }

    /**
     * 回调  长度的变化
     * @param totalLength
     */
    private void receviceTotalLength(long totalLength) {
        downloadItemInfo.setCurrentLength(totalLength);
        final DownloadItemInfo copyDownloadItemInfo=downloadItemInfo.copy();
        if(downloadServiceCallable!=null)
        {
            synchronized (this.downloadServiceCallable)
            {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        downloadServiceCallable.onTotalLengthReceived(copyDownloadItemInfo);
                    }
                });
            }
        }

    }

    @Override
    public void onFail() {

    }

    public IHttpService getHttpService() {
        return httpService;
    }

    public File getFile() {
        return file;
    }
}
public class FileDownHttpService implements IHttpService {
    private static final String TAG = "FileDownHttpService";
    /**
     * 即将添加到请求头的信息
     */
    private Map<String ,String> headerMap= Collections.synchronizedMap(new HashMap<String ,String>());
    /**
     * 含有请求处理的 接口
     */
    private IHttpListener httpListener;

    private HttpClient httpClient=new DefaultHttpClient();
    private HttpGet httpPost;
    private String url;

    private byte[] requestDate;
    /**
     * httpClient获取网络的回调
     */
    private  HttpRespnceHandler httpRespnceHandler=new HttpRespnceHandler();
    /**
     * 增加方法
     */
    private AtomicBoolean pause=new AtomicBoolean(false);

    @Override
    public void setUrl(String url) {
        this.url=url;
    }

    @Override
    public void excute() {
        httpPost=new HttpGet(url);
        constrcutHeader();
//        ByteArrayEntity byteArrayEntity=new ByteArrayEntity(requestDate);
//        httpPost.setEntity(byteArrayEntity);
        try {
            httpClient.execute(httpPost,httpRespnceHandler);
        } catch (IOException e) {
            httpListener.onFail();
        }
    }

    /**
     * 1
     */
    private void constrcutHeader() {
        Iterator iterator=headerMap.keySet().iterator();
        while (iterator.hasNext())
        {
            String key= (String) iterator.next();
            String value=headerMap.get(key);
            Log.i(TAG," 请求头信息  "+key+"  value "+value);
            httpPost.addHeader(key,value);
        }
    }

    public Map<String, String> getHeaderMap() {
        return headerMap;
    }

    @Override
    public void setHttpListener(IHttpListener httpListener) {
        this.httpListener=httpListener;
    }

    @Override
    public void setRequestData(byte[] requestData) {
        this.requestDate=requestData;
    }

    @Override
    public void pause() {
        pause.compareAndSet(false,true);
    }

    @Override
    public Map<String, String> getHttpHeadMap() {
        return headerMap;
    }

    @Override
    public boolean cancle() {
        return false;
    }

    @Override
    public boolean isCancle() {
        return false;
    }
    @Override
    public boolean isPause() {
        return pause.get();
    }

    private class HttpRespnceHandler extends BasicResponseHandler
    {
        @Override
        public String handleResponse(HttpResponse response) throws ClientProtocolException {
            //响应吗
            int code=response.getStatusLine().getStatusCode();
            if(code==200||206==code)
            {
                httpListener.onSuccess(response.getEntity());
            }else
            {
                ListView list;
                httpListener.onFail();
            }


            return null;
        }
    }
}

###6、将整个逻辑进行封装、链接、启动,形成调用工具类

public class DownFileManager implements IDownloadServiceCallable {
    private static final String TAG ="DownFileManager " ;
    //    private  static
    private byte[] lock=new byte[0];
    DownLoadDao downLoadDao= BaseDaoFactory.getInstance().
            getDataHelper(DownLoadDao.class,DownloadItemInfo.class);
    java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    /**
     * 观察者模式
     */
    private final List<IDownloadCallable> applisteners = new CopyOnWriteArrayList<IDownloadCallable>();

    /**
     * 正在下载的所有任务
     */
    private static List<DownloadItemInfo> downloadFileTaskList = new CopyOnWriteArrayList();

    Handler handler=new Handler(Looper.getMainLooper());


    public int download(String url)
    {
        String[] preFix=url.split("/");
        return this.download(url,Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+preFix[preFix.length-1]);
    }
    public int download(String url, String filePath )
    {
        String[] preFix=url.split("/");
        String displayName=preFix[preFix.length-1];
        return this.download(url,filePath,displayName);
    }
    public int download(String url, String filePath, String displayName)
    {
        return this.download(url,filePath,displayName,Priority.middle);
    }

    public int download(String url, String filePath,
                        String displayName , Priority priority ) {

        if(priority==null)
        {
            priority=Priority.low;
        }
        File file=new File(filePath);
        DownloadItemInfo downloadItemInfo=null;

        downloadItemInfo=downLoadDao.findRecord(url,filePath);
        //没下载
        if(downloadItemInfo==null)
        {
            /**
             * 根据文件路径查找
             */
            List<DownloadItemInfo> samesFile=downLoadDao.findRecord(filePath);
            /**
             * 大于0  表示下载
             */
            if(samesFile.size()>0)
            {
                DownloadItemInfo sameDown=samesFile.get(0);
                if(sameDown.getCurrentLen()==sameDown.getTotalLen())
                {
                    synchronized (applisteners)
                    {
                        for (IDownloadCallable downloadCallable:applisteners)
                        {
                            downloadCallable.onDownloadError(sameDown.getId(),2,"文件已经下载了");
                        }
                    }

                }
            }
            /**---------------------------------------------
             * 插入数据库
             * 可能插入失败
             * 因为filePath  和id是独一无二的  在数据库建表时已经确定了
             */
           int recrodId=downLoadDao.addRecrod(url,filePath,displayName,priority.getValue());
            if(recrodId!=-1)
            {
                synchronized (applisteners)
                {
                    for (IDownloadCallable downloadCallable:applisteners)
                    {
                        //通知应用层  数据库被添加了
                        downloadCallable.onDownloadInfoAdd(downloadItemInfo.getId());
                    }
                }
            }
            //插入失败时,再次进行查找,确保能查得到
            else
            {
                //插入
                downloadItemInfo=downLoadDao.findRecord(url,filePath);
            }
        }
        /**-----------------------------------------------
         * 括号写错了  放在外面
         *
         * 是否正在下载`
         */
        if(isDowning(file.getAbsolutePath()))
        {
            synchronized (applisteners)
            {
                for (IDownloadCallable downloadCallable:applisteners)
                {
                    downloadCallable.onDownloadError(downloadItemInfo.getId(),4,"正在下载,请不要重复添加");
                }
            }
            return downloadItemInfo.getId();
        }

        if(downloadItemInfo!=null)
        {
            downloadItemInfo.setPriority(priority.getValue());
            //添加----------------------------------------------------
            downloadItemInfo.setStopMode(DownloadStopMode.auto.getValue());

            //判断数据库存的 状态是否是完成
            if(downloadItemInfo.getStatus()!= DownloadStatus.finish.getValue())
            {
                if(downloadItemInfo.getTotalLen()==0L||file.length()==0L)
                {
                    Log.i(TAG,"还未开始下载");
                    //----------------------删除--------------------
                    downloadItemInfo.setStatus(DownloadStatus.failed.getValue());
                }
                //判断数据库中 总长度是否等于文件长度
                if(downloadItemInfo.getTotalLen()==file.length()&&downloadItemInfo.getTotalLen()!=0)
                {
                    downloadItemInfo.setStatus(DownloadStatus.finish.getValue());
                    synchronized (applisteners)
                    {
                        for (IDownloadCallable downloadCallable:applisteners)
                        {
                            try {
                                downloadCallable.onDownloadError(downloadItemInfo.getId(),4,"已经下载了");
                            }catch (Exception e)
                            {
                            }
                        }
                    }
                }
            }
            //------------------添加--------
            else
            {
                if(!file.exists()||(downloadItemInfo.getTotalLen()!=downloadItemInfo.getCurrentLen()))
                {
                    downloadItemInfo.setStatus(DownloadStatus.failed.getValue());
                }
            }
            /**
             *
             * 更新
             */
            downLoadDao.updateRecord(downloadItemInfo);
            //移到括号里面来----------------------------------------------------
            /**
             * 判断是否已经下载完成
             */
            if(downloadItemInfo.getStatus()==DownloadStatus.finish.getValue())
            {
                Log.i(TAG,"已经下载完成  回调应用层");
                final int downId=downloadItemInfo.getId();
                synchronized (applisteners)
                {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            for (IDownloadCallable downloadCallable:applisteners)
                            {
                                downloadCallable.onDownloadStatusChanged(downId,DownloadStatus.finish);
                            }
                        }
                    });
                }
                downLoadDao.removeRecordFromMemery(downId);
                return downloadItemInfo.getId();
            }//之前的下载 状态为暂停状态
            List<DownloadItemInfo> allDowning=downloadFileTaskList;
            //当前下载不是最高级  则先退出下载
            if(priority!=Priority.high)
            {
                for(DownloadItemInfo downling:allDowning)
                {
                    //从下载表中  获取到全部正在下载的任务
                    downling=downLoadDao.findSigleRecord(downling.getFilePath());

                    if(downling!=null&&downling.getPriority()==Priority.high.getValue())
                    {

                        /**
                         *     更改---------
                         *     当前下载级别不是最高级 传进来的是middle    但是在数据库中查到路径一模一样 的记录   所以他也是最高级------------------------------
                         *     比如 第一次下载是用最高级下载,app闪退后,没有下载完成,第二次传的是默认级别,这样就应该是最高级别下载

                         */
                        if (downling.getFilePath().equals(downloadItemInfo.getFilePath()))
                        {
                            break;
                        }
                        else
                        {
                            return downloadItemInfo.getId();
                        }
//                        if(downloadItemInfo.getFilePath().equals(downling.getFilePath()))
//                        {
//                            return downloadItemInfo.getId();
//                        }
                    }
                }
            }
            //
            reallyDown(downloadItemInfo);
            if(priority==Priority.high||priority== Priority.middle)
            {
                synchronized (allDowning)
                {
                    for (DownloadItemInfo downloadItemInfo1:allDowning)
                    {
                        if(!downloadItemInfo.getFilePath().equals(downloadItemInfo1.getFilePath()))
                        {
                            DownloadItemInfo downingInfo=downLoadDao.findSigleRecord(downloadItemInfo1.getFilePath());
                            if(downingInfo!=null)
                            {
                                pause(downloadItemInfo.getId(),DownloadStopMode.auto);
                            }
                        }
                    }
                }
                return downloadItemInfo.getId();
            }
        }

      return  -1;
    }


    /**
     * 停止
     * @param downloadId
     * @param mode
     */
    public void pause(int downloadId, DownloadStopMode mode)
    {
        if (mode == null)
        {
            mode = DownloadStopMode.auto;
        }
        final DownloadItemInfo downloadInfo =downLoadDao.findRecordById(downloadId);
        if (downloadInfo != null)
        {
            // 更新停止状态
            if (downloadInfo != null)
            {
                downloadInfo.setStopMode(mode.getValue());
                downloadInfo.setStatus(DownloadStatus.pause.getValue());
                downLoadDao.updateRecord(downloadInfo);
            }
            for (DownloadItemInfo downing:downloadFileTaskList)
            {
                if(downloadId==downing.getId())
                {
                    downing.getHttpTask().pause();
                }
            }
        }
    }

    /**
     * 判断当前是否正在下载
     *
     * @param absolutePath
     * @return
     */
    private boolean isDowning(String absolutePath) {
        for (DownloadItemInfo downloadItemInfo:downloadFileTaskList)
        {
            if(downloadItemInfo.getFilePath().equals(absolutePath))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 添加观察者
     * @param downloadCallable
     */
    public void setDownCallable(IDownloadCallable downloadCallable)
    {
        synchronized (applisteners)
        {
             applisteners.add(downloadCallable);
        }

    }


    /**
     * 下载
     */
    public DownloadItemInfo reallyDown(DownloadItemInfo downloadItemInfo)
    {
        synchronized (lock)
        {
            //实例化DownloadItem
            RequestHodler requestHodler=new RequestHodler();
            //设置请求下载的策略
            IHttpService httpService=new FileDownHttpService();
            //得到请求头的参数 map
            Map<String,String> map=httpService.getHttpHeadMap();
            /**
             * 处理结果的策略
             */
            IHttpListener httpListener=new DownLoadLitener(downloadItemInfo,this,httpService);

            requestHodler.setHttpListener(httpListener);
            requestHodler.setHttpService(httpService);
            /**
             *  bug  url
             */
            requestHodler.setUrl(downloadItemInfo.getUrl());

            HttpTask httpTask=new HttpTask(requestHodler);
            downloadItemInfo.setHttpTask(httpTask);

            /**
             * 添加
             */
            downloadFileTaskList.add(downloadItemInfo);
            httpTask.start();
        }
        return downloadItemInfo;

    }

    @Override
    public void onDownloadStatusChanged(DownloadItemInfo downloadItemInfo) {

    }

    @Override
    public void onTotalLengthReceived(DownloadItemInfo downloadItemInfo) {

    }

    @Override
    public void onCurrentSizeChanged(DownloadItemInfo downloadItemInfo, double downLenth, long speed) {
        Log.i(TAG,"下载速度:"+ speed/1000 +"k/s");
        Log.i(TAG,"-----路径  "+ downloadItemInfo.getFilePath()+"  下载长度  "+downLenth+"   速度  "+speed);
    }

    @Override
    public void onDownloadSuccess(DownloadItemInfo downloadItemInfo) {
        Log.i(TAG,"下载成功    路劲  "+ downloadItemInfo.getFilePath()+"  url "+ downloadItemInfo.getUrl());

    }

    @Override
    public void onDownloadPause(DownloadItemInfo downloadItemInfo) {
  }

    @Override
    public void onDownloadError(DownloadItemInfo downloadItemInfo, int var2, String var3) {

    }
}

###四、调用

DownFileManager downFileService=new DownFileManager();     downFileService.download("http://gdown.baidu.com/data/wisegame/8be18d2c0dc8a9c9/WPSOffice_177.apk");
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值