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
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 downloadInfoList; // 下载列表
private List alreadyDownLoadList; // 已经下载完成的
private List 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();
downLoadingList = new ArrayList();
try {
downloadInfoList = db.findAll(Selector.from(DownloadInfo.class)); // 查询所有的下载
} catch (DbException e) {
LogUtils.e(e.getMessage(), e);
}
if (downloadInfoList == null) {
downloadInfoList = new ArrayList();
} 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 getDownLoadingList() {
return downLoadingList;
}
public DownloadInfo getDownLoadinginfo(int index) {
downLoadingList.get(index);
return downLoadingList.get(index);
}
public int getAlreadyDownLoadCount() {
return alreadyDownLoadList.size();
}
public List 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 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 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 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 callback) throws DbException {
HttpUtils http = new HttpUtils();
http.configRequestThreadPoolSize(maxDownloadThread);
HttpHandler 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 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 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 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 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 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 {
private DownloadInfo downloadInfo;
private RequestCallBack baseCallBack;
public RequestCallBack getBaseCallBack() {
return baseCallBack;
}
public void setBaseCallBack(RequestCallBack baseCallBack) {
this.baseCallBack = baseCallBack;
}
private ManagerCallBack(DownloadInfo downloadInfo,
RequestCallBack 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 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 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 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 responseInfo) {
HttpHandler 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 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 {
@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
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 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 getHandler() {
return handler;
}
public void setHandler(HttpHandler 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));
}
}
下载的service
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 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;
}
}