美文网首页Android进阶+实战Android知识程序员
Android开发之DownloadManager的使用

Android开发之DownloadManager的使用

作者: YungFan | 来源:发表于2017-03-03 09:48 被阅读9367次

    Android 开发中,经常有从服务器下载数据的需求出现,尤其是在线更新App的情形。其基本思路是根据本地的App版本号和服务器的版本号进行比较,如果服务器版本较新,再进行提示然后下载Apk最后进行安装。这种需求解决方案有很多,第三方的网络框架基本都有这个功能。

    Android自带的DownloadManager是一个很好的下载文件的工具。该类在API level 9之后出现,它已经帮我们处理了下载失败、重新下载等功能,整个下载过程全部交给系统负责,不需要我们过多的处理,非常的nice。关键的是用起来也很简单,很爽,稍微封装一下就可以几句话搞定下载。

    下面以一个简单案例来实现从服务器下载一个Apk文件并进行安装。

    1、打开本地Tomcat服务器,放入一个Apk文件

    Tomcat.png

    2、开启Tomcat,然后确保能从浏览器下载

    浏览器下载.png

    3、编写DownloadManager工具类,代码注释很详细

    public class DownloadUtils {
        //下载器
        private DownloadManager downloadManager;
        //上下文
        private Context mContext;
        //下载的ID
        private long downloadId;
        public  DownloadUtils(Context context){
            this.mContext = context;
        }
    
        //下载apk
        public void downloadAPK(String url, String name) {
    
            //创建下载任务
            Request request = new Request(Uri.parse(url));
            //移动网络情况下是否允许漫游
            request.setAllowedOverRoaming(false);
    
            //在通知栏中显示,默认就是显示的
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
            request.setTitle("新版本Apk");
            request.setDescription("Apk Downloading");
            request.setVisibleInDownloadsUi(true);
    
            //设置下载的路径
            request.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory().getAbsolutePath() , name);
    
           //获取DownloadManager
            downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
            //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
            downloadId = downloadManager.enqueue(request);
    
            //注册广播接收者,监听下载状态
            mContext.registerReceiver(receiver,
                    new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
        }
    
        //广播监听下载的各个状态
        private BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                checkStatus();
            }
        };
    
    
        //检查下载状态
        private void checkStatus() {
            Query query = new Query();
            //通过下载的id查找
            query.setFilterById(downloadId);
            Cursor c = downloadManager.query(query);
            if (c.moveToFirst()) {
                int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                switch (status) {
                     //下载暂停
                    case DownloadManager.STATUS_PAUSED:
                        break;
                    //下载延迟
                    case DownloadManager.STATUS_PENDING:
                        break;
                    //正在下载
                    case DownloadManager.STATUS_RUNNING:
                        break;
                    //下载完成
                    case DownloadManager.STATUS_SUCCESSFUL:
                        //下载完成安装APK
                        installAPK();
                        break;
                    //下载失败
                    case DownloadManager.STATUS_FAILED:
                        Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT).show();
                        break;
                }
            }
            c.close();
        }
    
        //下载到本地后执行安装
        private void installAPK() {
            //获取下载文件的Uri
            Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId);
            if (downloadFileUri != null) {
                Intent intent= new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mContext.startActivity(intent);
                mContext.unregisterReceiver(receiver);
            }
        }
    
    }
    
    

    4、编写Activity代码初始化工具类,然后下载

    public class MainActivity extends AppCompatActivity {
        private DownloadUtils downloadUtils;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            downloadUtils =   new DownloadUtils(MainActivity.this); 
            downloadUtils.downloadAPK("http://192.168.1.104:8080/XXX.apk", "XXX.apk");
    
        }
    }
    

    5、配置权限

    <!--在SDCard中创建与删除文件权限  -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- 往SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!--  从SDCard读取数据权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <!--  访问网络权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    

    6、运行结果

    运行以后会去下载服务器的Apk,通知栏也会有相应的通知。当下载完毕以后,会弹出安装界面。

    • 通知栏
    通知栏提醒.png
    • 主界面
    主界面.gif

    相关文章

      网友评论

      • 鱼我所欲:这个在下载的过程中怎么暂停或者取消呀??
      • 骚年_金闪闪:为什么我下载中,通知栏会自己消失呢,华为三星都这样,一个19版本,一个22版本
        YungFan:@骚年_金闪闪 底层改了肯定就没办法了 这个是原生的
        骚年_金闪闪:@YungFan 发现一个巨坑(No Activity found to handle Intent)。。。不知道为什么,三星的会出,华为小米都没出,然后搜了下,有些品牌无法识别content,有解决方法么
        YungFan:@骚年_金闪闪 下载结束了 点击后会消失
      • 大大大大大大的大大:跳转时忘了取消注册 mContext.unregisterReceiver(receiver)
        大大大大大大的大大:@YungFan 代码结尾忘了加“ ; ”号:kissing_heart:
        YungFan:@大大大大大大的大大 看得真仔细 谢谢指正
      • 88383ea191db:下载失败有几种原因呢?我用的真机测试 7.1的系统
      • 阿甘_0be0:Cursor c 用完应该需要close下吧
        YungFan:@阿甘_0be0 应该应该
      • YY_简书:downloadManager.Request = new DownloadManager.Request(Uri.parse(url))就不会有,没有构造函数的错误
      • YY_简书:Request构建对象的时候显示没有合适的构建函数
      • 97c30afb1412:默认是支持移动和wifi网络的,但是我没设置,却只能wifi下载很奇怪。我下载代码也没有判断网络状态
        YungFan:@谢谢谢皇上 暂时没有
        fencex:request.setAllowedNetworkTypes?

        后来发现有什么坑吗?
      • 669aeb7b559e:几乎全copy代码用了,最后不能自动安装,提示不够权限
        后来google说必须加上这个Flag,7.0以上才能调起
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        YungFan:@wellingone 最新的系统需要适配一下
      • Ariel__10df:请问我能用这个方法来实现在webview 中下载文件吗?
        YungFan:@Ariel__10df 7.0多了很多权限申请
        Ariel__10df:@YungFan 喔,我就是想图个方便,用这个传入了servlet路径之后能下载了。😄
        YungFan:@Ariel__10df 那和安卓的API没关系 你要用网页的东西
      • 暮雨沉沦:楼上说部分厂商把这个功能删了???卧槽,这么凶残
        YungFan:@醉生梦死_风花雪月 :+1:
        e786f2d9d0e5:@YungFan 是的 需要手动判断com.android.providers.downloads设置
        YungFan:网上据说三星的部分手机有 我没用过
      • 搞Android的文艺青年:7.0系统会有问题,还有就是部分厂商将系统的downloadmanager删除了
        YungFan:@醉生梦死_风花雪月 原来如此 受教了
        e786f2d9d0e5:@YungFan 7.0系统读取apk的时候需通过FileProvider
        YungFan:@搞Android的文艺青年 好像三星的部分机器有问题 7.0没试过
      • MisterT:还没有用过呢,以后会用到,收藏一下
        YungFan:@RamMin 挺好用的,封装一下几句话搞定。
      • 582c6f536166:老师厉害了

      本文标题:Android开发之DownloadManager的使用

      本文链接:https://www.haomeiwen.com/subject/zkrkgttx.html