【转】 Pro Android学习笔记(七五):HTTP服务(9):DownloadManager
文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件,转载须注明出处:http://blog.csdn.net/flowingflying/
应用有时需要从web中下载一个大文件,并保存在本地,这个操作过程是标准的,因此在Android2.3引入了DownloadManager类。相关的学习也可以参考Android学习笔记(四六):互联网通信-文件下载。
小例子
先看一个小例子,如下图所示。layout由一个button和一个textview组成,textview用于显示信息。用户按Start按键后,通过Download在后台下载文件,在通知栏中有提示,可以查看下载进度。当下载结束,通知栏的相关信息也将被清除。Android系统有一个下载管理器Downloads,可以查看通过DownloadManager下载的文件情况。

源程序如下:
public class DownloadMrgActivity extends Activity{
private TextView tv = null;
private DownloadManager manager = null;
private long downloadId = -1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download_mrg);
tv = (TextView)findViewById(R.id.tv);
}
//【1】通过获取Download_Service的reference来获得DownloadManager实例
protected void onResume() {
super.onResume();
manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
showInfo("get DownloadManager instance : " + manager);
}
//【2】向DownloadManager请求下载某图片
public void doDownload(View v){ //按Button触发 android:onClick="doDoownload"
showInfo("doDownload() is called");
/*【2.1】设置请求 */
DownloadManager.Request dmReq = new DownloadManager.Request(
Uri.parse("http://ww1.sinaimg.cn/large/5cf79a90jw1ecy18vfwlrj20xc18gtgd.jpg"));
dmReq.setTitle(getResources().getString(R.string.download_manager));//下来通知栏,显示信息的title
dmReq.setDescription("食指大动"); //下来通知栏,显示信息的描述
dmReq.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);//缺省不作限制,本例在此设置只允许WIFI连接时下载,也可以设置为NETWORK_MOBILE
/* 【2.2】DownloadManager在后台下载完成后,会进行广播通知,设置通知接收器:先设置过滤条件,再register接收器*/
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(myReceiver, filter);
/* 【2.3】 向DownloadManager提交请求,并获得id,该id用于对应该请求的处理 */
downloadId = manager.enqueue(dmReq);
showInfo("downloadId = " + downloadId);
}
/*【2.2.1】设置DownloadManager的广播接收器*/
public BroadcastReceiver myReceiver = new BroadcastReceiver(){
// 获取id号,可据此判断是哪个请求的完成。intent在之前已经学习过,可以用来唤起component,并传递信息,component包括activity、service、broadcast receiver以及content provider。此处正式broadcast receiver。
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
long doneDownloadId = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
if(doneDownloadId != downloadId)
return;
showInfo("Download with id " + doneDownloadId + " is finished.");
showInfo("Download file uri is " + manager.getUriForDownloadedFile(doneDownloadId));
}
};
//【3】与onResume()对应,进行一些清空处理,如unregister接收器,不再监听DownloadManager的广播
protected void onPause() {
super.onPause();
unregisterReceiver(myReceiver);
manager = null;
downloadId = -1;
}
private void showInfo(String s){
Log.d("PRO-wei",s);
tv.setText(s + "\n" + tv.getText());
}
}
保存在哪里?(下载文件信息设置和读取)
在Android 4.2开始,manager.getUriForDownloadedFile(id)将返回的scheme是content,小例子返回uri是content://downloads/my_downloads/<id>,没有给出路径,我找了很久都没有找到缺省存放在哪里。当然,有了uri,就可以进行读取,例如:
InputStream input = getContentResolver().openInputStream(uri);
但是,我们还是想知道具体存放在那里,可以通过下面的方式查看下载文件信息,还可以查询很多信息,具体可翻阅API的reference。
Cursor c = manager.query(new DownloadManager.Query().setFilterById(doneDownloadId));
if(c != null){
c.moveToFirst();
showInfo(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)));
c.close();
}
应该查询,文件放在一个隐秘的地方,难怪没能翻出来,LogCat截图如下:

如果希望文件能否放在一个用户容易查找的地方,可以在请求中指定路径,如下:
dmReq.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "fish.jpg");
在指定路径后,uri给出的是文件的路径file:///mnt/sdcard/Download/fish.jpg。当然要正确运行,我们必须申请WRITE_EXTERNAL_STORAGE权限。
实际上,我们并不需要知道文件路径或者content uri,也可读取文件,我们在layout中增加一个imageview控件,用于显示下载的图片,相关代码如下:
try{
ParcelFileDescriptor pfd = manager.openDownloadedFile(doneDownloadId);
FileDescriptor fileDescriptor = pfd.getFileDescriptor();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
pfd.close();
ImageView image = (ImageView)findViewById(R.id.download_image);
image.setImageBitmap(bitmap);
}catch(Exception e){
e.printStackTrace();
}

查看下载状态和取消下载
在layout中增加一个Cancel按钮,触发cancelDownload()函数,用于取消下载。我们首先查询下载的状态,如果已经完成,不作处理,否则取消下载。
public void cancelDownload(View v){
if(downloadId > 0){
Cursor c = manager.query(new DownloadManager.Query().setFilterById(downloadId));
if(c == null)
return;
c.moveToFirst();
int state = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if(state != DownloadManager.STATUS_FAILED && state != DownloadManager.STATUS_SUCCESSFUL){
showInfo("Download is not finished, CANCEL it.");
manager.remove(downloadId); //如果文件已经下载完成,remove命令并不会删除文件
downloadId = -1;
}
c.close();
}
}
本博文涉及的例子代码,可以在Pro Android学习:Http service小例子中下载。
相关链接: 我的Android开发相关文章
【转】 Pro Android学习笔记(七五):HTTP服务(9):DownloadManager的更多相关文章
- 【转】 Pro Android学习笔记(五六):配置变化
目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...
- 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式
可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...
- 【转】 Pro Android学习笔记(五七):Preferences(1):ListPreference
目录(?)[-] 例子1ListPreference小例子 定义一个preferences XML文件 继承PreferenceActivity 用户定制偏好的读取 第一次运行时设置缺省值 设置Cat ...
- 【转】Pro Android学习笔记(五):了解Content Provider(上)
Content Provider是抽象数据封装和数据访问机制,例如SQLite是Android设备带有的数据源,可以封装到一个content provider中.要通过content provider ...
- 【转】 Pro Android学习笔记(五九):Preferences(3):EditText和Ringtone Preference
目录(?)[-] EditText Preferences xml文件 设备的存贮文件 Ringtone Preferences EditText Preferences xml文件 在res/xml ...
- 【转】 Pro Android学习笔记(五八):Preferences(2):CheckBoxPreference
目录(?)[-] CheckBox Preference xml文件 设备的存贮文件 复合preference 在ListPreference的例子中显示的是单选,如果是多选,可采用CheckBoxP ...
- 【转】 Pro Android学习笔记(五十):ActionBar(3):搜索条
目录(?)[-] ActionBar中的搜索条 通过Menu item上定义search view 进行Searchable的配置 在activity中将search view关联searchable ...
- 【转】Pro Android学习笔记(五三):调试和分析(1):Debug视图和DDMS视图
目录(?)[-] Debug视图 DDMS视图 查看应用运行状态 进入debug状态 HPROF Thread信息 Method信息 Stop 截图 UI层次架构信息 其它的 Tab中提供的功能 我们 ...
- 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode
目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...
- 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件
目录(?)[-] 在AIDL中定义服务接口 根据AIDL文件自动生成接口代码 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.n ...
随机推荐
- springboot错误页面处理
springboot作为微服务的便捷框架,在错误页面处理上也有了一些新的处理,不同于之前的pringmvc500的页面处理是比较简单的,用java config或者xml的形式,定义如下的Bean即可 ...
- 【题解】国家集训队礼物(Lucas定理)
[国家集训队]礼物(扩展Lucas定理) 传送门可以直接戳标题 172.40.23.20 24 .1 答案就是一个式子: \[ {n\choose \Sigma_{i=1}^m w}\times\pr ...
- 我的设计模式学习笔记------>单例模式(Singleton)
一.前言 有些时候,允许自由创建某个类的实例是没有意义,还可能造成系统性能下降(因为创建对象所带来的系统开销问题).例如整个Windows系统只有一个窗口管理器,只有一个回收站等.在Java EE应用 ...
- PHP中ob系列函数讲解(浏览器缓存技术) (转)
Output Control 函数可以让你自由控制脚本中数据的输出.它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况. 输出控制函数不对使用 header() 或 setcooki ...
- 使用curl / wget命令上传下载FTP
curl可以在shell下轻松上传下载ftp上的文件,相比ftp命令更具有优势,因为它能在单命令条件下,下载或者上传一个ftp文件,甚至可以删除文件. 下面看实例: 1.列出ftp服务器上的目录列表: ...
- LeetCode:移动零【283】
LeetCode:移动零[283] 题目描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3 ...
- 小程序真机GET请求出现406错误
问题:微信开发模拟器请求成功,获得数据,但是在真机上出现406请求错误,无法获得请求结果 原因:真机微信小程序的请求头与模拟器不同 怎么发现的:在请求头强制添加Accept即可解决 修复:在请求Hea ...
- UVA - 10870 Recurrences 【矩阵快速幂】
题目链接 https://odzkskevi.qnssl.com/d474b5dd1cebae1d617e6c48f5aca598?v=1524578553 题意 给出一个表达式 算法 f(n) 思路 ...
- 【LeetCode】数组排列问题(permutations)(附加next_permutation解析)
描述 Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3 ...
- vi使用方法详细介绍
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...