downloadmanager时Android系统下载器,使用系统下载器可以避免用stream流读入内存可能导致的内存溢出问题。以下为downloadmanager初始化部分。apkurl为下载网络路径。Environment.DIRECTORY_DOWNLOADS 为系统的下载路径。即下载至外部存储。

   mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
String apkUrl = "https://qd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk";
Uri resource = Uri.parse(apkUrl);
DownloadManager.Request request = new DownloadManager.Request(resource);
//下载的本地路径,表示设置下载地址为SD卡的Download文件夹,文件名为mobileqq_android.apk。
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "mobileqq_android.apk");
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setVisibleInDownloadsUi(true);
request.setDescription("xiazaizhong");
//end 一些非必要的设置
id = mDownloadManager.enqueue(request);
//下载后的本地uri
uri = mDownloadManager.getUriForDownloadedFile(id);

enqueue方法为添加到下载队列,同时返回的id用于contentobserver监听下载进度.下载进度监听代码如下:

private DownloadContentObserver observer = new DownloadContentObserver();
class DownloadContentObserver extends ContentObserver {
public DownloadContentObserver() {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
// updateView();
if (scheduledExecutorService != null) {
scheduledExecutorService.scheduleWithFixedDelay(runnable, 0, 3, TimeUnit.SECONDS);
}
}
}
public static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
public void updateView() {
int[] bytesAndStatus = getBytesAndStatus(id);
int currentSize = bytesAndStatus[0];//当前大小
int totalSize = bytesAndStatus[1];//总大小
int status = bytesAndStatus[2];//下载状态 1开始 2下载中 8下载完成
Message.obtain(handler, 0, currentSize, totalSize, status).sendToTarget();
}
public int[] getBytesAndStatus(long downloadId) {
int[] bytesAndStatus = new int[]{-1, -1, 0};
DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
Cursor c = null;
try {
c = mDownloadManager.query(query);
if (c != null && c.moveToFirst()) {
bytesAndStatus[0] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
bytesAndStatus[1] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
bytesAndStatus[2] = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
}
} finally {
if (c != null) {
c.close();
}
}
return bytesAndStatus;
}

设置 DownloadContentObserver类监听下载进度,可在其重写的 onchange方法中更新UI,即updataView方法,但此会返回大量数据,在下载量大时可使用ScheduledExecutorService 设定定时任务,注册定时任务设定间隔时间查询进度,downloadcontentobserver需要在onresume 和 ondestroy方法中注册和注销代码在下,getBytesAndStatus方法获取队列中数组当前下载的进度 包括当前大小总大小,下载状态等。

注销和注册downloadcontentobserver的代码

private static final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
getContentResolver().registerContentObserver(CONTENT_URI, true, observer);
getContentResolver().unregisterContentObserver(observer);

定时任务中执行的runable 为更新UI的 updateView方法

    Runnable runnable = new Runnable() {
@Override
public void run() {
try {
updateView();
} catch (Exception e) {
e.printStackTrace();
}
}
};

最后即是updateView方法中发送message的handeler代码,message可传入两个bundle参数和一个object对象。从handler中取出可以更新UI 或逻辑操作了,注意声明handler时传入了 mainlooper,这样不用再特地主线程中更新UI,测试中下载完成时状态码为8,具体使用时可再次测试。下载结束后可将定时任务关闭置空。

    private Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(@NonNull @NotNull Message msg) {
super.handleMessage(msg);
if (scheduledExecutorService != null) {
int currentSize = msg.arg1;
int totalSize = msg.arg2;
Object object = msg.obj;
tvDownload.setText(String.valueOf(((float) (currentSize / totalSize)) * 100));
if ((Integer) object == 8) {
scheduledExecutorService.shutdownNow();
scheduledExecutorService = null;
Toast.makeText(ControlerActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
Log.e(TAG, "handleMessage:" + currentSize + " " + totalSize + " " + object.toString());
}
}
};

最后测试下载的本地的uri是否正确,文件下载是否成功 Environment.getExternalStoragePublicDirectory获取外部存储的下载路径。还有下载完成点击通知跳转和下载完成监听功能不再详述。

  File file=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"/mobileqq_android.apk");
if (file.exists()) {
Log.e(TAG, "exists yes"+file.length());
}else {
Log.e(TAG, "exists no" );
}

Android 开发学习进程0.32 dwonloadmanager使用的更多相关文章

  1. Android 开发学习进程0.16 layout_weight属性 R文件关联XML Module

    layout_weight属性 layout_weight属性我们常常用到,但有时候会发现它还有一些奇怪的属性,比如大多数使用时会把宽度设置成0,但要是宽度不设置成0会有什么效果? layout_we ...

  2. Android 开发学习进程0.19 webview 的使用

    Android 中的webview android 中的webview是可以在app内部打开HTML等的网页,不必再打开浏览器,有两种实现方法,即webviewclient webChromeclie ...

  3. Android开发学习进程0.18 SharePreference的使用 AIDL

    SharePreference SharePreference是一种持久化存储手段,使用场景很多,如第一次打开时加载的用户协议等.适合小数据单进程的应用.将数据以键值对的形式存储在XML中. 使用方式 ...

  4. Android 开发学习进程0.17 Android资源文件selector textview显示两种不同字体

    selector 是安卓资源文件的一种,它可以使按钮等实现不同状态下的不同UI,不用在代码中实现,而使用方式有两种,一种在color文件下 创建.xml可以使按钮等字体在不同状态下的变化,其二是在dr ...

  5. Android 开发学习进程0.15 adb cardview framelayout 控件设置状态获取焦点

    Android设备调试桥 即adb 使用adb进行无线调试的一些常用命令 adb tcpip 5555 设置调试端口为5555 防止冲突 adb shell ifconfig wlan0 查询局域网中 ...

  6. Android 开发学习进程0.27 kotlin使用 和viewbinding的使用

    kotlin-android-extensions 插件被废弃 笔者曾经尝试写过一部分的kotlin代码 主要是项目中一些代码是kotlin完成的,其中我认为 kotlin的kotlin-androi ...

  7. Android 开发学习进程0.28 腾讯TBS接入和相关问题

    TBS 的接入和使用 TBS 的接入 腾讯TBS是X5内核的升级版,可以当作webview 来打开 网页,可以以用来打开docx doc pdf 等文件,这里主要使用的是文件功能. 依赖接入 api ...

  8. Android 开发学习进程0.14 Bindview recyclerview popwindow使用 window类属性使用

    BindView ButterKnife 优势 绑定组件方便,使用简单 处理点击事件方便,如adapter中的viewholder 同时父组件绑定后子组件无需绑定 注意 在setcontentview ...

  9. Android 开发学习进程0.13 Androidstudio快捷键 xmlns

    xmlns XML namespace xml命名空间 其中主要是定义xml文件定义位置 前缀有三种,android app tools 后面为唯一标识符URI android 表示为引用自安卓系统 ...

随机推荐

  1. 重新整理 .net core 实践篇—————服务的配置更新[十三]

    前言 前文讲述了,服务和配置直接的配合,这一节写一下,当配置文件修改了,每个服务如何感知自己的配置. 正文 服务感知到自己的配置发生变化,这就牵扯出两个东西: IoptionsMonitor<o ...

  2. Step By Step(Lua函数)

    Step By Step(Lua函数) 一.函数:    在Lua中函数的调用方式和C语言基本相同,如:print("Hello World")和a = add(x, y).唯一的 ...

  3. THINKPHP_(2)_TP模型的多表关联查询和多表字段的关键字搜索。

    问题: 上述内容中,标题和学年属于一个数据表.分类则属于另外一个数据表,并且是利用id关联后,另外一个数据表中的title字段. 需要设置关键字搜索,实现多表关联查询和多表字段的关键字搜索. 解决方法 ...

  4. gst-crypto GStreamer插件

    gst-crypto GStreamer插件 内容 1. gst-crypto概述 1.1gst-crypto GStreamer插件功能 1.2用例范例 2. GStreamer插件支持 3. 在本 ...

  5. CodeGen融合核心关系循环扩展

    CodeGen融合核心关系循环扩展 Expansion Tokens <HARMONYCORE_RELATION_NAME> 插入当前关系的名称.关系名称将自动生成,但可以由Harmony ...

  6. java 全端开源 电商系统 springboot uniapp 小程序 前后端分离 高可用

    Lilishop B2B2C商城系统 官方公众号 & 开源不易,如有帮助请点Star 所有jar包均可从maven中央仓库下载,无二次封装jar包,全端开源,无后门,无监控. 介绍 官网:ht ...

  7. java并发编程工具类JUC第七篇:BlockingDeque双端阻塞队列

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  8. LeetCode 每日一题「判定字符是否唯一」

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 题目 ...

  9. 【C++】vector容器的用法

    检测vector容器是否为空: 1 #include <iostream> 2 #include <string> 3 #include <vector> 4 us ...

  10. java处理方法的多个返回值

    我第一次接触到元组是在java编程思想这本书中,当时我正为方法的多个返回值苦恼.因为我之前处理多个返回值方法的时候,要不建一个新的实体类,要不在接收的方法中建立一个对象,返回值之前给其赋值,要不通过异 ...