1、下载apk文件

下载的方式有很多种,常用的有:

(1)调用系统下载器下载,需要设置通知来接受下载完成的操作,然后进入安装流程

(2)最简单的,直接调起系统浏览器访问apk下载链接,后续的事情都不管,等下载完了用户自行安装

(3)自己写下载代码,缺点是不如前两者稳定,优点是下载进度和状态可控

我这里使用的是第三种,然后下载代码并不自己写,而是直接调用OkHttpUtils框架,OkHttpUtils框架的配置跟导入这里不再赘述,具体自己查一下用法,直接上下载代码(不要忘了网络权限跟存储权限):

isDownloading = true;//是否正在下载,同一时间不给同时进行多个下载任务
        final TextLoadingPopupWindow textLoadingPopupWindow = new TextLoadingPopupWindow(getActivity());//进度提示弹窗,具体替换自己的弹窗,这里不提供
        textLoadingPopupWindow.setText("00.0%");
        textLoadingPopupWindow.show();
        OkHttpUtils.get(url)
                .execute(new FileCallback(new PathUtil().getMusicEditorPath(), UUID.randomUUID().toString() + ".apk") {//这里指定下载保存文件的路径
                    @Override
                    public void onSuccess(File file, Call call, Response response) {
                        isDownloading = false;
                        textLoadingPopupWindow.dismiss();
                        installApp(file);//下载完成,调起安装
                    }

                    public void onError(Call call, Response response, Exception e) {
                        isDownloading = false;
                        textLoadingPopupWindow.dismiss();
                        ToastUtils.showToast(getContext(), "下载出错");
                    }

                    public void downloadProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
                        textLoadingPopupWindow.setText((int) (progress * 100) + "." + (int) (progress * 1000) % 10 + "%");//进度显示,处于UI线程
                    }
                });

2、安装apk

文件准备好了之后就是安装了,安装主要需要注意7.0和8.0两个系统的兼容.

(1)7.0适配

需要用到fileprovider,需要在res文件夹下创建一个xml文件,我这里叫xxxxxx.xml,主要就是配置几个路径,你需要安装的apk文件在调用安装之前,需要先移到这几个路径之下才可以。

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="xxxxx" path="xxxxx" />
</paths>

xml准备好了之后,需要去AndroidManifest.xml里面配置一下

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="这里替换成你的包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/xxxxx" />
        </provider>

(2)8.0适配

适配了7.0之后,8.0基本上没啥问题了,唯一的区别就是8.0需要加上一个权限


    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

如果觉得有必要的话,8.0可以在调起安装之前校验一下本应用是否已经有了可以安装其他应用的权限,如果没有则直接跳转到手机设置的相关页面,这里需要说一下,在我亲测的几台手机中,如果使用了这个逻辑,基本上是会跳转到一个设置页面,页面是一箩筐的应用列表,很难找到自己的app并进去设置“允许安装未知应用”这个东西,个人觉得这个体验很不好,而如果是直接调用安装代码,则系统会自发的提示是否需要开启这个应用“允许安装未知应用”的这个东西,所以这里的代码就是执行直接调起安装操作,是否具备权限就不验证了。

 /**
     * 调起安装
     *
     * @param file
     */
    private void installApp(File file) {
        if (file == null || !file.getPath().endsWith(".apk")) {
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);

        //判读版本是否在7.0以上
        if (Build.VERSION.SDK_INT >= 24) {
            Uri apkUri = FileProvider.getUriForFile(getActivity(), "你的包名.fileprovider", file);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        }
        getActivity().startActivity(intent);
    }

本代码在7.0的vivo手机和8.0的小米手机上亲测有效。

12-22 11:41