zoukankan      html  css  js  c++  java
  • Android 开发学习进程0.32 dwonloadmanager使用

    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" );
            }
    
    吾生也有涯,而知也無涯。以有涯隨無涯,殆已
  • 相关阅读:
    Python—格式化输出
    拨开Python迷雾
    彻底搞懂Python切片操作
    CodeMirror教程,CodeMirrorAPI中文信息
    PHP header() session_start() 函数前为什么不能有输出?
    PHP time() date() strtotime()日期函数总结
    LAMP专业术语的规范书写格式
    经验之谈
    PHP接口对方(C#)接收不到数据?ContentLength=1
    jQuery判断checkbox是否选中?操作checkbox(不)选中?
  • 原文地址:https://www.cnblogs.com/baimiyishu/p/15013627.html
Copyright © 2011-2022 走看看