android 自带了下载管理器,我们可以获取到下载的进度大小以及下载完成等等的状态,但是android自带的DownLoadManager却没有实现比如暂停,继续等功能也就是不能断点续传,这几天在总下载管理器,写了以后总是 感觉还是不是太好,因为下载要考虑的情况是比较多的
1、我们要考虑下载的时候要有下载情况的回调,
2、下载的文件是否已经下载
3、是否已经下载完成
4、下载速度
5、下载的进度
6、下载的过程中暂停,继续,取消等操作
7、可能有些人还要把下载的列表分为a 已经下载完成 b 正在下载
8、还有要加下载完成的通知,或是提示
9、还有listView经常遇到的进度条显示错乱
等等。。。。上网查找了很多的资料,网上有现成的第三方DownloadProvider这个,功能相当的齐全,但是我还是希望自己能写一个
下边是我自己的实现思路
首先 1 、要有一个service 来进行后台下载
2、需要有一个存放下载信息的一个实体类downLoadInfo 包含下载的文件大小,每次下载的大小,下载的速度等
private long id;
@Transient
private HttpHandler<File> handler;
private HttpHandler.State state
private String downloadUrl;
private String fileName;
private String fileSavePath;
private long progress;
private long fileLength;
private boolean autoResume;
private boolean autoRename;
private float speed;
3、一个下载管理器;进行下载的管理,已经下载进度的回调
下载我使用的是第三方的xutils
4 、一个DownLoadAdapter用来给listView填充数据
整体来讲就是这么多。
下载管理器代码如下
package cn.com.huahuawifi.android.guest.download; import android.content.Context; import android.database.Cursor; import android.util.Log; import cn.com.huahuawifi.android.guest.util.Utils; import cn.com.huahuawifi.android.guest.util.XUtilsHttpUtil; import com.lidroid.xutils.DbUtils; import com.lidroid.xutils.HttpUtils; import com.lidroid.xutils.db.converter.ColumnConverter; import com.lidroid.xutils.db.converter.ColumnConverterFactory; import com.lidroid.xutils.db.sqlite.ColumnDbType; import com.lidroid.xutils.db.sqlite.Selector; import com.lidroid.xutils.exception.DbException; import com.lidroid.xutils.exception.HttpException; import com.lidroid.xutils.http.HttpHandler; import com.lidroid.xutils.http.HttpHandler.State; import com.lidroid.xutils.http.ResponseInfo; import com.lidroid.xutils.http.callback.RequestCallBack; import com.lidroid.xutils.util.LogUtils; import java.io.File; import java.util.ArrayList; import java.util.List; /** * 下载管理器 */ public class DownloadManager { private List<DownloadInfo> downloadInfoList; // 下载列表 private List<DownloadInfo> alreadyDownLoadList; // 已经下载完成的 private List<DownloadInfo> downLoadingList; // 正在下载 private int maxDownloadThread = 3; // 最大下载线程数 private Context mContext; private DbUtils db; private long mLastTime; private long mLastFileSize; /* package */DownloadManager(Context appContext) { ColumnConverterFactory.registerColumnConverter(HttpHandler.State.class, new HttpHandlerStateConverter()); mContext = appContext; db = DbUtils.create(mContext); alreadyDownLoadList = new ArrayList<DownloadInfo>(); downLoadingList = new ArrayList<DownloadInfo>(); try { downloadInfoList = db.findAll(Selector.from(DownloadInfo.class)); // 查询所有的下载 } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (downloadInfoList == null) { downloadInfoList = new ArrayList<DownloadInfo>(); } else { for (int i = 0; i < downloadInfoList.size(); i++) { if (downloadInfoList .get(i) .getState() .equals(com.lidroid.xutils.http.HttpHandler.State.SUCCESS)) { alreadyDownLoadList.add(downloadInfoList.get(i)); } else { downLoadingList.add(downloadInfoList.get(i)); } } } } public int getDownloadInfoListCount() { return downloadInfoList.size(); } public DownloadInfo getDownloadInfo(int index) { return downloadInfoList.get(index); } public int getDownloadInfoLoadingCount() { return downLoadingList.size(); } public List<DownloadInfo> getDownLoadingList() { return downLoadingList; } public DownloadInfo getDownLoadinginfo(int index) { downLoadingList.get(index); return downLoadingList.get(index); } public int getAlreadyDownLoadCount() { return alreadyDownLoadList.size(); } public List<DownloadInfo> getAlreadyDownLoadList() { return alreadyDownLoadList; } public DownloadInfo getAlreadyDownLoadInfo(int index) { alreadyDownLoadList.get(index); return alreadyDownLoadList.get(index); } /** * 获取当前url的文件是否在下载列表里,或去的时候想确保把改下载添加到了下载列表中 * @param downloadUrl * @return */ public DownloadInfo getDownLoadInfo(String downloadUrl){ DownloadInfo downloadInfo =null; for (DownloadInfo doInfo : downloadInfoList) { if (doInfo.getDownloadUrl().equals(downloadUrl)) { downloadInfo =doInfo; return downloadInfo; } } return downloadInfo; } /** * 添加下载任务 * * @param url * 下载链接 * @param fileName * 文件名 * @param target * 文件存放路径 * @param autoResume * @param autoRename * @param callback * 回调 * @throws DbException */ public void addNewDownload(String url, String fileName, String target, boolean autoResume, boolean autoRename, final RequestCallBack<File> callback) throws DbException { if (Utils.fileIsExists(target)) {// 下载文件已经存在不在添加下载任务 } else { final DownloadInfo downloadInfo = new DownloadInfo(); downloadInfo.setDownloadUrl(url); downloadInfo.setAutoRename(autoRename); downloadInfo.setAutoResume(autoResume); downloadInfo.setFileName(fileName); downloadInfo.setFileSavePath(target); HttpUtils http = new HttpUtils(); http.configRequestThreadPoolSize(maxDownloadThread); HttpHandler<File> handler = http.download(url, target, autoResume, autoRename, new ManagerCallBack(downloadInfo, callback)); downloadInfo.setHandler(handler); downloadInfo.setState(handler.getState()); downloadInfoList.add(downloadInfo); db.saveBindingId(downloadInfo); } } public void resumeDownload(int index, final RequestCallBack<File> callback) throws DbException { final DownloadInfo downloadInfo = downloadInfoList.get(index); resumeDownload(downloadInfo, callback); } /** * 重新下载 * * @param downloadInfo * downLoadinfo信息 * @param callback * 回调 * @throws DbException */ public void resumeDownload(DownloadInfo downloadInfo, final RequestCallBack<File> callback) throws DbException { HttpUtils http = new HttpUtils(); http.configRequestThreadPoolSize(maxDownloadThread); HttpHandler<File> handler = http.download( downloadInfo.getDownloadUrl(), downloadInfo.getFileSavePath(), downloadInfo.isAutoResume(), downloadInfo.isAutoRename(), new ManagerCallBack(downloadInfo, callback)); downloadInfo.setHandler(handler); downloadInfo.setState(handler.getState()); db.saveOrUpdate(downloadInfo); } /** * 移除下载任务 * * @param index * 要移除的下表 * @throws DbException */ public void removeDownload(int index) throws DbException { DownloadInfo downloadInfo = downloadInfoList.get(index); removeDownload(downloadInfo); } /** * 移除下载任务 * * @param downloadInfo * 下载的downloadInfo对象 * @throws DbException */ public void removeDownload(DownloadInfo downloadInfo) throws DbException { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } downloadInfoList.remove(downloadInfo); downLoadingList.remove(downloadInfo); alreadyDownLoadList.remove(downloadInfo); db.delete(downloadInfo); } public void removeAlreadyDownLoad(DownloadInfo downloadInfo) throws DbException{ HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } alreadyDownLoadList.remove(downloadInfo); Utils.deleteFile(downloadInfo.getFileSavePath()); db.delete(downloadInfo); } /** * 停止下载 * * @param index * 下载的下表 * @throws DbException */ public void stopDownload(int index) throws DbException { DownloadInfo downloadInfo = downloadInfoList.get(index); stopDownload(downloadInfo); } /** * 停止下载 * * @param downloadInfo * 下载的downloadInfo对象 * @throws DbException */ public void stopDownload(DownloadInfo downloadInfo) throws DbException { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } else { downloadInfo.setState(HttpHandler.State.CANCELLED); } db.saveOrUpdate(downloadInfo); } /** * 停止所有的下载任务 * * @throws DbException */ public void stopAllDownload() throws DbException { for (DownloadInfo downloadInfo : downloadInfoList) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null && !handler.isCancelled()) { handler.cancel(); } else { downloadInfo.setState(HttpHandler.State.CANCELLED); } } db.saveOrUpdateAll(downloadInfoList); } /** * 改变数据库中下载状态 * * @throws DbException */ public void backupDownloadInfoList() throws DbException { for (DownloadInfo downloadInfo : downloadInfoList) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { switch (handler.getState()) { case WAITING: downloadInfo.setState(State.CANCELLED); break; case SUCCESS: break; case FAILURE: break; case LOADING: downloadInfo.setState(State.CANCELLED); break; case CANCELLED: downloadInfo.setState(State.CANCELLED); break; case STARTED: downloadInfo.setState(State.CANCELLED); break; default: break; } } } db.saveOrUpdateAll(downloadInfoList); } public int getMaxDownloadThread() { return maxDownloadThread; } /** * 设置最大下载线程 * * @param maxDownloadThread */ public void setMaxDownloadThread(int maxDownloadThread) { this.maxDownloadThread = maxDownloadThread; } public class ManagerCallBack extends RequestCallBack<File> { private DownloadInfo downloadInfo; private RequestCallBack<File> baseCallBack; public RequestCallBack<File> getBaseCallBack() { return baseCallBack; } public void setBaseCallBack(RequestCallBack<File> baseCallBack) { this.baseCallBack = baseCallBack; } private ManagerCallBack(DownloadInfo downloadInfo, RequestCallBack<File> baseCallBack) { this.baseCallBack = baseCallBack; this.downloadInfo = downloadInfo; } @Override public Object getUserTag() { if (baseCallBack == null) return null; return baseCallBack.getUserTag(); } @Override public void setUserTag(Object userTag) { if (baseCallBack == null) return; baseCallBack.setUserTag(userTag); } @Override public void onStart() { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); if (downLoadingList.size() == 0) { downLoadingList.add(downloadInfo); } } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onStart(); } } @Override public void onCancelled() { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onCancelled(); } } @Override public void onLoading(long total, long current, boolean isUploading) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } long nowTime = System.currentTimeMillis(); Log.e("SPEED1", nowTime + ""); Log.e("SPEED2", mLastTime + ""); Log.e("SPEED1_file", current + ""); Log.e("SPEED2_file", mLastFileSize + ""); float speed = 0; float speedContent = current - mLastFileSize; float speedTimer = nowTime - mLastTime; if (mLastTime > 0 && current != 0) { if (speedContent >= 1024) { speedContent = (float) ((speedContent) / (1024 + 0.0)); speedContent = (float) (((int) (speedContent * 10) % 10 + 0.0) / 10 + (int) speedContent); speedTimer = (float) ((speedTimer) / (1000 + 0.0)); speed = speedContent / speedTimer; } Log.e("SPEED", speed + ""); } mLastTime = nowTime; mLastFileSize = current; downloadInfo.setSpeed(speed); downloadInfo.setFileLength(total); downloadInfo.setFileAllSize(((float) total) / ((float) 1048576)); ; downloadInfo.setProgress(current); try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onLoading(total, current, isUploading); } } @Override public void onSuccess(ResponseInfo<File> responseInfo) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); downLoadingList.remove(downloadInfo); alreadyDownLoadList.add(downloadInfo); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onSuccess(responseInfo); } } @Override public void onFailure(HttpException error, String msg) { HttpHandler<File> handler = downloadInfo.getHandler(); if (handler != null) { downloadInfo.setState(handler.getState()); } try { db.saveOrUpdate(downloadInfo); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } if (baseCallBack != null) { baseCallBack.onFailure(error, msg); } } } private class HttpHandlerStateConverter implements ColumnConverter<HttpHandler.State> { @Override public HttpHandler.State getFieldValue(Cursor cursor, int index) { return HttpHandler.State.valueOf(cursor.getInt(index)); } @Override public HttpHandler.State getFieldValue(String fieldStringValue) { if (fieldStringValue == null) return null; return HttpHandler.State.valueOf(fieldStringValue); } @Override public Object fieldValue2ColumnValue(HttpHandler.State fieldValue) { return fieldValue.value(); } @Override public ColumnDbType getColumnDbType() { return ColumnDbType.INTEGER; } } }
DownLoadInfo
<span style="font-size:10px;">package cn.com.huahuawifi.android.guest.download; import com.lidroid.xutils.db.annotation.Transient; import com.lidroid.xutils.http.HttpHandler; import java.io.File; public class DownloadInfo { public DownloadInfo() { } private long id; @Transient private HttpHandler<File> handler; private HttpHandler.State state; private String downloadUrl; private String fileName; private String fileSavePath; private long progress; //下载的长度 private long fileLength; //文件的总长度 private boolean autoResume; private boolean autoRename; private float speed; private float fileAllSize; public float getFileAllSize() { return fileAllSize; } public void setFileAllSize(float fileAllSize) { this.fileAllSize = fileAllSize; } public float getSpeed() { return speed; } public void setSpeed(float speed) { this.speed = speed; } public long getId() { return id; } public void setId(long id) { this.id = id; } public HttpHandler<File> getHandler() { return handler; } public void setHandler(HttpHandler<File> handler) { this.handler = handler; } public HttpHandler.State getState() { return state; } public void setState(HttpHandler.State state) { this.state = state; } public String getDownloadUrl() { return downloadUrl; } public void setDownloadUrl(String downloadUrl) { this.downloadUrl = downloadUrl; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileSavePath() { return fileSavePath; } public void setFileSavePath(String fileSavePath) { this.fileSavePath = fileSavePath; } public long getProgress() { return progress; } public void setProgress(long progress) { this.progress = progress; } public long getFileLength() { return fileLength; } public void setFileLength(long fileLength) { this.fileLength = fileLength; } public boolean isAutoResume() { return autoResume; } public void setAutoResume(boolean autoResume) { this.autoResume = autoResume; } public boolean isAutoRename() { return autoRename; } public void setAutoRename(boolean autoRename) { this.autoRename = autoRename; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof DownloadInfo)) return false; DownloadInfo that = (DownloadInfo) o; if (id != that.id) return false; return true; } @Override public int hashCode() { return (int) (id ^ (id >>> 32)); } }</span><span style="font-size:18px;font-weight: bold;"> </span>
下载的service
<span style="font-size:10px;">package cn.com.huahuawifi.android.guest.download; import android.app.ActivityManager; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import com.lidroid.xutils.exception.DbException; import com.lidroid.xutils.util.LogUtils; import java.util.List; public class DownloadService extends Service { private static DownloadManager DOWNLOAD_MANAGER; public static DownloadManager getDownloadManager(Context appContext) { if (!DownloadService.isServiceRunning(appContext)) { Intent downloadSvr = new Intent("download.service.action"); appContext.startService(downloadSvr); } if (DownloadService.DOWNLOAD_MANAGER == null) { DownloadService.DOWNLOAD_MANAGER = new DownloadManager(appContext); } return DOWNLOAD_MANAGER; } public DownloadService() { super(); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public void onDestroy() { if (DOWNLOAD_MANAGER != null) { try { DOWNLOAD_MANAGER.stopAllDownload(); DOWNLOAD_MANAGER.backupDownloadInfoList(); } catch (DbException e) { LogUtils.e(e.getMessage(), e); } } super.onDestroy(); } public static boolean isServiceRunning(Context context) { boolean isRunning = false; ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(Integer.MAX_VALUE); if (serviceList == null || serviceList.size() == 0) { return false; } for (int i = 0; i < serviceList.size(); i++) { if (serviceList.get(i).service.getClassName().equals(DownloadService.class.getName())) { isRunning = true; break; } } return isRunning; } }</span><span style="font-size:18px;font-weight: bold;"> </span>