转载请注明出处:https://blog.youkuaiyun.com/mythmayor/article/details/72842291
我们的App中常常会涉及到与下载相关的内容,这时候就不得不提及DownloadManager这个类
对DownloadManager又进行了一次封装,相比之前更加的完善。
public class MyDownloadUtil {
private Context mContext;
private String mDownloadUrl;//文件下载地址
private String fileSubPath;//文件下载二级路径
private DownloadListener mDownloadListener;//下载监听
private boolean isSavePathPrivate = false;
private DownloadManager mManager;
private long mRequestId;
private boolean isDownloading;//是否在下载中
public MyDownloadUtil(Context context, String url, String subPath, DownloadListener listener) {
this.mContext = context;
this.mDownloadUrl = url;
this.fileSubPath = subPath;
this.mDownloadListener = listener;
//获得DownloadManager对象
mManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
}
public MyDownloadUtil(Context context, String url, String subPath, boolean isSavePathPrivate, DownloadListener listener) {
this.mContext = context;
this.mDownloadUrl = url;
this.fileSubPath = subPath;
this.mDownloadListener = listener;
this.isSavePathPrivate = isSavePathPrivate;
//获得DownloadManager对象
mManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
}
/**
* 开始下载
*
* @return 下载请求ID
*/
public long startDownload() {
//获得下载id,这是下载任务生成时的唯一id,可通过此id获得下载信息
mRequestId = mManager.enqueue(createRequest(mDownloadUrl, fileSubPath));
BasicApplication.getInstance().getAppExecutors().diskIO().execute(new Runnable() {//使用线程池管理子线程
@Override
public void run() {
//查询下载信息方法
queryDownloadProgress(mRequestId, mManager);
}
});
return mRequestId;
}
/**
* 开始下载(调用需开启子线程)
*
* @return 下载请求ID
*/
public long startDownloadSync() {
//获得下载id,这是下载任务生成时的唯一id,可通过此id获得下载信息
mRequestId = mManager.enqueue(createRequest(mDownloadUrl, fileSubPath));
//查询下载信息方法
queryDownloadProgress(mRequestId, mManager);
return mRequestId;
}
/**
* 取消下载
*
* @return 实际删除的下载数量
*/
public int cancelDownload() {
isDownloading = false;
return mManager.remove(mRequestId);
}
/**
* 查询下载信息
*
* @param requestId 下载请求ID
* @param manager 下载管理器
*/
private void queryDownloadProgress(long requestId, DownloadManager manager) {
DownloadManager.Query query = new DownloadManager.Query();
//根据任务编号id查询下载任务信息
query.setFilterById(requestId);
try {
isDownloading = true;
while (isDownloading) {
Cursor cursor = manager.query(query);
if (cursor != null && cursor.moveToFirst()) {
//获得下载状态
int state = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (state) {
case DownloadManager.STATUS_SUCCESSFUL://下载成功
isDownloading = false;
mDownloadListener.onDownloadStatusListener(DownloadManager.STATUS_SUCCESSFUL, null);
break;
case DownloadManager.STATUS_FAILED://下载失败
isDownloading = false;
mDownloadListener.onDownloadStatusListener(DownloadManager.STATUS_FAILED, null);
break;
case DownloadManager.STATUS_RUNNING://下载中
int totalSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));//计算下载率
int currentSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int progress = (int) (((float) currentSize) / ((float) totalSize) * 100);
mDownloadListener.onDownloadStatusListener(DownloadManager.STATUS_RUNNING, progress);
break;
case DownloadManager.STATUS_PAUSED://下载暂停
isDownloading = false;
mDownloadListener.onDownloadStatusListener(DownloadManager.STATUS_PAUSED, null);
break;
case DownloadManager.STATUS_PENDING://准备下载
mDownloadListener.onDownloadStatusListener(DownloadManager.STATUS_PENDING, null);
break;
}
} else {
isDownloading = false;
}
if (cursor != null) {
cursor.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建下载请求对象
*
* @param url 下载地址
* @param subPath 保存目录子路径
* @return 下载请求对象
*/
private DownloadManager.Request createRequest(String url, String subPath) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
//request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);// 隐藏notification
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);//显示notification
request.setAllowedNetworkTypes(request.NETWORK_MOBILE | request.NETWORK_WIFI);//设置下载网络环境为手机数据流量、wifi
if (isSavePathPrivate) {
//保存至私有目录(/storage/Android/data/<package-name>/files/Download/<subPath>)
request.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, subPath);
} else {
//保存至公有目录(/storage/Download/<subPath>)
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, subPath);
}
return request;
}
/**
* 用于监听下载状态变化的接口
*/
public interface DownloadListener extends BaseListener {
void onDownloadStatusListener(int status, Object obj);
}
}
说明:工具类中涉及到我的两个类或者方法。第一个是BasicApplication.getInstance().getAppExecutors().diskIO().execute(Runnable command);这段代码是我项目中对线程池的管理。如果没有对线程池进行管理,可以直接使用new Thread等方式创建子线程。第二个是BaseListener类,这就是一个Listener的基类,里面就是一个空接口,如果有公共内容可以定义再BaseListener中。
闲话少说,直接上代码,这里封装成了一个工具类(已过时):
1.DownloadUtil.class
package com.mythmayor.download;
import android.app.DownloadManager;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
/**
* Created by mythmayor on 2017/4/26.
*/
public class DownloadUtil {
private String mUrl;
private String mName;
private Handler mHandler;
private Context mContext;
private DownloadManager mManager;
private long requestId;
public DownloadUtil(Context context, String url, Handler handler, String name) {
this.mContext = context;
this.mUrl = url;
this.mHandler = handler;
this.mName = name;
//获得DownloadManager对象
mManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
}
public long startDownload() {
//获得下载id,这是下载任务生成时的唯一id,可通过此id获得下载信息
requestId = mManager.enqueue(CreateRequest(mUrl, mName));
//查询下载信息方法
queryDownloadProgress(requestId, mManager);
return requestId;
}
public int cancelDownload() {
return mManager.remove(requestId);
}
private void queryDownloadProgress(long requestId, DownloadManager downloadManager) {
DownloadManager.Query query = new DownloadManager.Query();
//根据任务编号id查询下载任务信息
query.setFilterById(requestId);
try {
boolean isGoging = true;
while (isGoging) {
Cursor cursor = downloadManager.query(query);
if (cursor != null && cursor.moveToFirst()) {
//获得下载状态
int state = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (state) {
case DownloadManager.STATUS_SUCCESSFUL://下载成功
isGoging = false;
mHandler.obtainMessage(downloadManager.STATUS_SUCCESSFUL).sendToTarget();//发送到主线程,更新ui
break;
case DownloadManager.STATUS_FAILED://下载失败
isGoging = false;
mHandler.obtainMessage(downloadManager.STATUS_FAILED).sendToTarget();//发送到主线程,更新ui
break;
case DownloadManager.STATUS_RUNNING://下载中
/**
* 计算下载下载率;
*/
int totalSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
int currentSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int progress = (int) (((float) currentSize) / ((float) totalSize) * 100);
mHandler.obtainMessage(downloadManager.STATUS_RUNNING, progress).sendToTarget();//发送到主线程,更新ui
break;
case DownloadManager.STATUS_PAUSED://下载停止
mHandler.obtainMessage(DownloadManager.STATUS_PAUSED).sendToTarget();
break;
case DownloadManager.STATUS_PENDING://准备下载
mHandler.obtainMessage(DownloadManager.STATUS_PENDING).sendToTarget();
break;
}
}
if (cursor != null) {
cursor.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private DownloadManager.Request CreateRequest(String url, String name) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
//request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);// 隐藏notification
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);//显示notification
request.setAllowedNetworkTypes(request.NETWORK_WIFI);//设置下载网络环境为wifi
request.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, name);//指定apk缓存路径,默认是在SD卡中的Download文件夹
return request;
}
}
2.DownloadUtil的使用
//定义Handler处理下载状态
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DownloadManager.STATUS_SUCCESSFUL:
Toast.makeText(MainActivity.this, "下载任务已经完成!", Toast.LENGTH_SHORT).show();
break;
case DownloadManager.STATUS_RUNNING:
break;
case DownloadManager.STATUS_FAILED:
break;
case DownloadManager.STATUS_PENDING:
break;
}
}
};
private DownloadUtil mUtil;
mUtil = new DownloadUtil(MainActivity.this, url, handler, fileName);
//开始下载
new Thread() {
@Override
public void run() {
long l = mUtil.startDownload();
ToastUtil.showToast(MainActivity.this, "requestId = " + l);
}
}.start();
//取消下载
int i = mUtil.cancelDownload();
if (i == 1) {
ToastUtil.showToast(this, "下载已取消 ");
}