使用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 \n";
            }

            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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,835评论 25 709
  • APK安装流程系列文章整体内容如下: APK安装流程详解0——前言APK安装流程详解1——有关"安装ing"的实体...
    隔壁老李头阅读 12,807评论 3 27
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 11,844评论 0 17
  • 尝有越女,名旦,其人净而丽,其音婉而鸣,其舞美而烈,其心逊而敏。时城厢之西有女名夷光者,人唤西施,嘈切自怜,恐为丑...
    杨宫大人阅读 3,690评论 0 1
  • 文/Meetingtian 我也不知道这篇文章该用什么题目,想来想去,这个词语应该是再合适不过的了,正好是我现在得...
    MeetingTian阅读 3,240评论 4 4