Android - DownloadManager: 下载管理, 艺术般的体验

本文介绍了一个封装了Android DownloadManager的工具类MyDownloadUtil,通过该工具类可以方便地管理下载任务,包括开始、取消下载及监听下载进度。

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

转载请注明出处: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, "下载已取消 ");
}

最后附上源码下载地址

点击此处进入源码下载界面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值