目录(?)[-]

  1. 小例子
  2. 保存在哪里下载文件信息设置和读取
  3. 查看下载状态和取消下载

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件,转载须注明出处: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的更多相关文章

  1. 【转】 Pro Android学习笔记(五六):配置变化

    目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...

  2. 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式

    可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...

  3. 【转】 Pro Android学习笔记(五七):Preferences(1):ListPreference

    目录(?)[-] 例子1ListPreference小例子 定义一个preferences XML文件 继承PreferenceActivity 用户定制偏好的读取 第一次运行时设置缺省值 设置Cat ...

  4. 【转】Pro Android学习笔记(五):了解Content Provider(上)

    Content Provider是抽象数据封装和数据访问机制,例如SQLite是Android设备带有的数据源,可以封装到一个content provider中.要通过content provider ...

  5. 【转】 Pro Android学习笔记(五九):Preferences(3):EditText和Ringtone Preference

    目录(?)[-] EditText Preferences xml文件 设备的存贮文件 Ringtone Preferences EditText Preferences xml文件 在res/xml ...

  6. 【转】 Pro Android学习笔记(五八):Preferences(2):CheckBoxPreference

    目录(?)[-] CheckBox Preference xml文件 设备的存贮文件 复合preference 在ListPreference的例子中显示的是单选,如果是多选,可采用CheckBoxP ...

  7. 【转】 Pro Android学习笔记(五十):ActionBar(3):搜索条

    目录(?)[-] ActionBar中的搜索条 通过Menu item上定义search view 进行Searchable的配置 在activity中将search view关联searchable ...

  8. 【转】Pro Android学习笔记(五三):调试和分析(1):Debug视图和DDMS视图

    目录(?)[-] Debug视图 DDMS视图 查看应用运行状态 进入debug状态 HPROF Thread信息 Method信息 Stop 截图 UI层次架构信息 其它的 Tab中提供的功能 我们 ...

  9. 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode

    目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...

  10. 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件

    目录(?)[-] 在AIDL中定义服务接口 根据AIDL文件自动生成接口代码 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.n ...

随机推荐

  1. html/css背景图片自适应分辨率大小

    <style type='text/css'> .bgbox { position: absolute; left: 0; top: 0; width: 100%; overflow: h ...

  2. 【python】-- pymsql 外键

    pymsql 外键 本片是以上一篇pymsql操作MySQL的补充,主要演示pymysql的外键操作使用 一.一对一外键关联 1.示意图 2.一对一外键关联示例 2.1.创建表结构,插入数据 from ...

  3. 获取exe文件窗口抓图,将memo转化为JPG输出

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  4. 我的Android进阶之旅------>android:drawableLeft的用法

    有时候想在EditText左边放一个图片,如图所示: 就可以在xml布局文件中的EditText定义代码中,添加入下面的代码,即可实现: android:drawableLeft="@dra ...

  5. 关于Ninja中上传下载文件

    上传得时候 根据类型来判断一下: 然后下载的时候需要:在url的最后一个/ 后面加上你要下载的类型如/download/app.apk; 下载成功就是app.apk了;

  6. matlab常用的一些程序和功能

    ~ 去除误匹配算法(matlab) 1.ransac算法 [tform,matchedPoints1,matchedPoints2] = ...    estimateGeometricTransfo ...

  7. IOS UI Frame 相对位置调整 与优化方法 Height Width X Y 调整

    不使用xib ,纯代码开发的过程中,动态UI  需要改对象的大小位置 反复使用CGRectMake 去 setFrame  非常低效耗时,而且 牵一发动全身. 以下整理出几个方法,方便动态布局 1.s ...

  8. nodejs模块之fs&&stream

    nodejs的文件系统fs模块,可以实现对文件.目录等的操作,stream模块实现对文件数据的断续读写操作 一.文件操作 fs.readFile(file[,options],callback) 异步 ...

  9. thinkphp 的 Action 控制器中的系统常量总结

    THINK_PATH // ThinkPHP系统目录 APP_PATH // 当前项目目录 APP_NAME // 当前项目名称 CONTROLLER_NAME // 当前控制器名称 MODULE_N ...

  10. 常量池、perm(持久代)、方法区、栈

      常量池.perm(持久代).方法区.栈 常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据. 除了包含代码中所定义的各种基本类型(如:int.long等等)和对象型(如St ...