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

来源:互联网 发布:数据库学哪个 编辑:程序博客网 时间:2024/06/05 19:52

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");
阅读全文
0 0
原创粉丝点击