• 使用DownloadManager 下载完 apk 自动提示安装


    前言

    每个Android App都会有版本更新的功能,而下载功能Google官方推荐使用 DownloadManager
    服务, 一起来看看如何使用DownloadManager实现版本更新的功能。


    recoder.gif

    使用DownloadManager

        /**
         * 下载Apk, 并设置Apk地址,
         * 默认位置: /storage/sdcard0/Download
         *
         * @param context    上下文
         * @param downLoadUrl 下载地址
         * @param infoName   通知名称
         * @param description  通知描述
         */
        @SuppressWarnings("unused")
        public static void downloadApk(
                Context context,
                String downLoadUrl,
                String description,
                String infoName) {
    
            DownloadManager.Request request;
            try {
                request = new DownloadManager.Request(Uri.parse(appUrl));
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
    
            request.setTitle(infoName);
            request.setDescription(description);
    
            //在通知栏显示下载进度
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                request.allowScanningByMediaScanner();
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            }
    
            //设置保存下载apk保存路径
            request.setDestinationInExternalPublicDir(CommonCons.SAVE_APP_LOCATION, CommonCons.SAVE_APP_NAME);
    
            Context appContext = context.getApplicationContext();
            DownloadManager manager = (DownloadManager)
                    appContext.getSystemService(Context.DOWNLOAD_SERVICE);
          //进入下载队列
            manager.enqueue(request);
    
        }

    当DownloadManager下载完成后会发出一个广播 android.intent.action.DOWNLOAD_COMPLETE,创建一个广播接收者,处理自动提示安装:

    /**
     * 安装下载接收器
     * Created by maimingliang on 2016/8/11.
     */
    
    public class InstallReceiver extends BroadcastReceiver {
    
        private static final String TAG = "InstallReceiver";
    
    
        // 安装下载接收器
        @Override public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
                installApk(context);
            }
        }
    
        // 安装Apk
        private void installApk(Context context) {
    
            try {
                Intent i = new Intent(Intent.ACTION_VIEW);
                String filePath = CommonCons.APP_FILE_NAME;
                i.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(i);
            }catch (Exception e){
                Log.e(TAG,"安装失败");
                e.printStackTrace();
            }
    
    }

    可以看出,实现起来其实是很容易的。不过要注意下面的几个坑:

    坑一


    QQ截图20161008112555.png

    图上报错的原因是 targetSdkVersion >=23 导致的,在API23以后引入了动态权限的概念。

    如何解决?有两种方式:

    方法一:

    把build.gradle 文件中的targetSdkVersion < 23。这种方式也是最简单的。

    方法二:

    动态的获取权限:

     @TargetApi(23)
        private void getPersimmions() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                ArrayList<String> permissions = new ArrayList<String>();
                /*
                 * 读写权限和电话状态权限非必要权限(建议授予)只会申请一次,用户同意或者禁止,只会弹一次
                 */
                // 读写权限
                if (addPermission(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny 
    ";
                }
    
                if (permissions.size() > 0) {
                    requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
                }
            }
        }
    
        @TargetApi(23)
        private boolean addPermission(ArrayList<String> permissionsList, String permission) {
            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { // 如果应用没有获得对应权限,则添加到列表中,准备批量申请
                if (shouldShowRequestPermissionRationale(permission)){
                    return true;
                }else{
                    permissionsList.add(permission);
                    return false;
                }
    
            }else{
                return true;
            }
        }
    
        @TargetApi(23)
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            // TODO Auto-generated method stub
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
        }

    坑二


    QQ截图20161008113535.png

    有两种原因:

    原因一:
    没有权限读取这个文件或者文件路径错误。

    解决方案:
    把apk的路径固定死

    String filePath = CommonCons.APP_FILE_NAME;

    原因二:
    单独设置data和type,如下:

    i.setData(Uri.parse("file://" + filePath));
    i.setType( "application/vnd.android.package-archive");

    坑三


    QQ截图20161008113834.png


    没有设置FLAG_ACTIVITY_NEW_TASK

    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    坑四


    QQ截图20161008112839.png

    APK签名不一致, 比如之前是debug版 现在你更新安装release版 .

    DownloadManager 下载完 apk 自动提示安装Demo

    END.



    文/maimingliang(简书作者)
    原文链接:http://www.jianshu.com/p/33ec70b08bd2
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 相关阅读:
    bzoj 3709: [PA2014]Bohater【贪心】
    bzoj 3714: [PA2014]Kuglarz【最小生成树】
    bzoj 2216: [Poi2011]Lightning Conductor【决策单调性dp+分治】
    bzoj 2087: [Poi2010]Sheep【凸包+极角排序+dp】
    bzoj 3830: [Poi2014]Freight【dp】
    bzoj 3930: [CQOI2015]选数【快速幂+容斥】
    bzoj 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式【后缀自动机】
    bzoj 1614: [Usaco2007 Jan]Telephone Lines架设电话线【二分+spfa】
    bzoj 1640||1692: [Usaco2007 Dec]队列变换【后缀数组】
    bzoj 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛【Floyd】
  • 原文地址:https://www.cnblogs.com/alone-01/p/5941155.html
Copyright © 2020-2023  润新知