Android7.0以上的App更新下载及进度显示

最近在编写app的升级功能,第一反应就是看看公司的旧项目里有没有相关代码,看看能不能抄过来直接用,结果当然是不行,一是由于需求跟以前有些不同,二是之前的项目可能比较老,没有对7.0进行适配,于是在看完了老的升级代码的基础上,再加上我充分的发挥了码农的搬运精神,东拼西凑终于大致上的满足了需求,于是决定写篇博客,一是做一个记录以后再写这个不用那么费劲,二是希望有相似需求的同学可以少走弯路,废话不多说,先把完整代码贴上来

package com.example.administrator.updateapkdemo;

import android.annotation.TargetApi;
import android.app.Dialog;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.RequiresApi;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private DownloadManager mDownloadManager;
    private long mId;
    private Dialog mDialog1;
    private ProgressBar mProgressBar;
    private TextView mPrecent;
    private TextView mComplete;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //1、网络获取版本号,跟本地apk版本号比对,如果发现服务器版本号高于本地版本号即弹出对话框,提醒用户更新
        new AlertDialog.Builder(MainActivity.this)
                .setTitle("版本更新")
                .setMessage("发现新的app版本,请及时更新")
                .setNegativeButton("暂不更新", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("立即更新", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //此处使用DownLoadManager开启下载任务
                        mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

                        DownloadManager.Request request = new DownloadManager.Request(Uri.parse("http://www.wandoujia.com/apps/com.tencent.mm/binding?source=web_inner_referral_binded"));
                        // 下载过程和下载完成后通知栏有通知消息。
                        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE | DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                        request.setTitle("下载");
                        request.setDescription("apk正在下载");
                        //设置保存目录  /storage/emulated/0/Android/包名/files/Download
                        request.setDestinationInExternalFilesDir(MainActivity.this,Environment.DIRECTORY_DOWNLOADS,"jiaogeyi.apk");
                        mId = mDownloadManager.enqueue(request);

                        //注册内容观察者,实时显示进度
                        MyContentObserver downloadChangeObserver = new MyContentObserver(null);
                        getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, downloadChangeObserver);

                        //广播监听下载完成
                        listener(mId);
                        //弹出进度条,先隐藏前一个dialog
                        dialog.dismiss();
                        //显示进度的对话框
                        mDialog1 = new Dialog(MainActivity.this, R.style.Theme_AppCompat_Dialog_Alert);
                        View view = MainActivity.this.getLayoutInflater().inflate(R.layout.progress_dialog, null);
                        mProgressBar = view.findViewById(R.id.pb);
                        mPrecent = view.findViewById(R.id.tv_precent);
                        mDialog1.setContentView(view);
                        mDialog1.show();

                    }
                })
                .create().show();

    }

    private void listener(final long id) {
        //Toast.makeText(MainActivity.this,"XXXX",Toast.LENGTH_SHORT).show();
        IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);

        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                long longExtra = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
                if (id == longExtra){
//                    Uri downloadUri = mDownloadManager.getUriForDownloadedFile(id);
                    Intent install = new Intent(Intent.ACTION_VIEW);
                    File apkFile = getExternalFilesDir("DownLoad/jiaogeyi.apk");
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                        install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        Uri uriForFile = FileProvider.getUriForFile(context, "com.example.administrator.updateapkdemo.fileprovider", apkFile);
                        install.setDataAndType(uriForFile,"application/vnd.android.package-archive");
                    }else {
                        install.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive");
                    }

                    install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(install);
                    Toast.makeText(MainActivity.this,"ZZZZ",Toast.LENGTH_SHORT).show();
                }
            }

        };

        registerReceiver(broadcastReceiver,intentFilter);
    }

    class MyContentObserver extends ContentObserver {

        public MyContentObserver(Handler handler) {
            super(handler);
        }


        @TargetApi(Build.VERSION_CODES.N)
        @Override
        public void onChange(boolean selfChange) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(mId);
            DownloadManager dManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
            final Cursor cursor = dManager.query(query);
            if (cursor != null && cursor.moveToFirst()) {
                final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
                final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
                int totalSize = cursor.getInt(totalColumn);
                int currentSize = cursor.getInt(currentColumn);
                float percent = (float) currentSize / (float) totalSize;
                float progress = (float) Math.floor(percent * 100);
                mPrecent.setText(progress+"%");
                mProgressBar.setProgress((int) progress,true);
                if (progress == 100)
                    mDialog1.dismiss();
            }
        }

    }
}

这里需要注意的是7.0之后对文件的权限进行了更严格的限制,需要使用FileProvider来间接的获取文件,所以操作起来自然是要麻烦一些,首先需要做的是在manifests中声明FileProvider

《Android7.0以上的App更新下载及进度显示》

其中authorities是需要注意的地方,这个属性的值最好让他独一无二,所以我这里采用包名加fileprovider来设置,你如果非要设置成xxx.ooo也不是不可以,但是必须和以下这行代码中的第二个参数一致

 Uri uriForFile = FileProvider.getUriForFile(context, "com.example.administrator.updateapkdemo.fileprovider", apkFile);

其次就是需要按照下图的方式创建xml文件《Android7.0以上的App更新下载及进度显示》

这里path报红不用管它,path值为空表示此是映射的是外挂SD卡的根目录(百度说的《Android7.0以上的App更新下载及进度显示》),java代码中没有的需要注意的地方就这么点,其他的完整代码中都有,当然还有在清单中声明一些权限

《Android7.0以上的App更新下载及进度显示》

最后将运行效果截图贴出来就算完事儿了

《Android7.0以上的App更新下载及进度显示》《Android7.0以上的App更新下载及进度显示》《Android7.0以上的App更新下载及进度显示》

    原文作者:jiang2717
    原文地址: https://blog.csdn.net/jiang2717/article/details/79362021
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞