DownloadManager 全解析,包括结果广播和下载进度监听

祁刚毅
2023-12-01

首先我们要有以下权限,这个是要求能够上网:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

如何开始下载

现在开始进行下载,按照以下步骤

1.获得DownloadManager的实例,使用getSystemService就可以了,不用自己new,既可以放在UI线程,也可以放在新线程

2.配置DownloadManager.Request ,具体看下面的代码,就是一个简单的参数设置

我的DOWNLOAD_LINK就是下载的String地址;

setDestinationInExternalPublicDic这个就是在/mnt/sdcard 下建立文件夹“Konachan”,里面的文件叫做“image.getTags() + ".jpeg”

setMimeType为打开方式,上网搜索“MimeType表”即可

其余的自行查询API,基本用的不多

3.开始下载 downloadManager.enqueue(request),它的返回值是一个下载ID,下面的接受广播,查询下载都要需要它

所有代码如下:

DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
                    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DOWNLOAD_LINK))
                            .setDestinationInExternalPublicDir("Konachan", image.getTags() + ".jpeg")
                            .setTitle("title")
                            .setDescription("下载到SD卡啦")
                            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                            .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI)
                            .setMimeType("image/jpeg");
                    final long downloadid = downloadManager.enqueue(request);


如何查询下载进度

这个利用DownloadManager提供的Uri,用ContentObserver进行不断的查询监控,步骤如下:

1.获得ContentResolver,注册ContentObserver ,参数如下

Uri.prase("content://downloads/") 这个地方不用动了

true : 是否查询子元素,这个地方也不用动了,因为我们要查询“downloads”的子元素

ContentObserver: 这个是我构造的一个DownloadObserver,详见下面

getContentResolver().registerContentObserver(Uri.parse("content://downloads/"),true,new DownloadObserver(handler,MyActivity.this,downloadid));


2.我的DownloadObserver类,最后可以发送handler修改UI

public class DownloadObserver extends ContentObserver {
    private long downid;
    private Handler handler;
    private Context context;

    public DownloadObserver(Handler handler, Context context, long downid) {
        super(handler);
        this.handler = handler;
        this.downid = downid;
        this.context = context;
    }

    @Override
    public void onChange(boolean selfChange) {
        //每当/data/data/com.android.providers.download/database/database.db变化后,触发onCHANGE,开始具体查询
        Log.w("onChangeID", String.valueOf(downid));
        super.onChange(selfChange);
        //实例化查询类,这里需要一个刚刚的downid
        DownloadManager.Query query = new DownloadManager.Query().setFilterById(downid);
        DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        //这个就是数据库查询啦
        Cursor cursor = downloadManager.query(query);
        while (cursor.moveToNext()) {
            int mDownload_so_far = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
            int mDownload_all = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
            int mProgress = (mDownload_so_far * 99) / mDownload_all;
            Log.w(getClass().getSimpleName(), String.valueOf(mProgress));
            //TODO:handler.sendMessage(xxxx),这样就可以更新UI了
        }
    }
}


如何下载完成自动打开

自动打开的实质就接受“下载完成”的广播,所以要重写一个BroadcastReceiver,步骤如下:

1.重写onReceive,代码就是判断广播是否为当前ID,然后启动intent

public class DownloadReceiver extends BroadcastReceiver {
    final static String MINETYPE = "image/jpeg";

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        long downId = bundle.getLong(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
        Log.w(getClass().getSimpleName(),String.valueOf(downId));
        DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
        Uri filepath = downloadManager.getUriForDownloadedFile(downId);
        Log.w(getClass().getSimpleName(),filepath.toString());
        if (intent.getAction() == DownloadManager.ACTION_DOWNLOAD_COMPLETE){
            //start the activity in new task opening the picture
            Intent activityIntent = new Intent(Intent.ACTION_VIEW);
            activityIntent.setDataAndType(filepath, MINETYPE);
            activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            try {
                context.startActivity(activityIntent);
            } catch (ActivityNotFoundException ex) {
                Log.d(getClass().getName(), "no activity for " + MINETYPE, ex);
            }
        } else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)){
            try {
                Intent dm = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
                dm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(dm);
            } catch (ActivityNotFoundException ex){
                Log.d(getClass().getName(), "no activity for " + MINETYPE, ex);
            }
        }

    }

}

2.注册AndroidMainFest.xml ,name对应的是刚才的DownloadReceiver的位置

 <receiver android:name="com.github.miao1007.konakanwallpaper.receiver.DownloadReceiver" >
            <intent-filter>
                <!--监听下载完成的那一瞬间-->
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            </intent-filter>
        </receiver>

3.全部完成,广播接受不需要在Activity中加东西,只用静态注册即可,其生命由系统自动控制

------END



 类似资料: