Android 版本更新安装apk

Android 版本更新安装apk

版本更新是每个安卓应用都会涉及的,当有新的版本更新下载后,调用系统安装程序安装新的apk,targetSdkVersion 在7.0以下时我们直接使用以下代码:

/**
    * 安装apk
    *
    * @param context
    * @param path    本地apk路径
    */
   public static void installApk(Context context, String path) {
       Intent install = new Intent(Intent.ACTION_VIEW);
       install.setDataAndType(Uri.fromFile(new File(path)),
               "application/vnd.android.package-archive");
       install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       context.startActivity(install);
   }

但是当targetSdkVersion 适配7.0以后当手机时,由于谷歌权限政策的变动,直接使用上面的方法将会报FileUriExposeException异常,8.0时,有的手机会报解析软件包时出现问题,查看google文档可以看见:
Android 版本更新安装apk_第1张图片

所以按照google提示,我们需要使用FileProvider,授权访问对应文件。那需要怎么做兼容呢?其实也很简单,步骤如下:
1.定义一个FileProvider

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
        ...
    </application>
</manifest>

2.指定可用目录文件
在工程的res目录下创建xml/file_paths.xml文件,并指定对应目录。

需要先说明下,paths中已经定义好代表各个常用目录的元素,

元素 目录
files-path getFilesDir()
cache-path getCacheDir()
external-path Environment.getExternalStorageDirectory()
external-files-path getExternalFilesDir(String) /getExternalFilesDir(null)
external-cache-path getExternalCacheDir()

所以比如我们要指定
Environment.getExternalStorageDirectory()+"/App/download/"目录,则代码如下

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--<files-path name="my_images" path="images/"/>-->
    <!--Context.getFilesDir()-->
    <!--<files-path name="name" path="path" />-->
    <!--getCacheDir()-->
    <!--<cache-path name="name" path="path" />-->
    <!--Environment.getExternalStorageDirectory()-->
    <!--<external-path name="name" path="path" />-->
    <!--Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)-->
    <!--<external-files-path name="name" path="path" />-->
    <!--Context.getExternalCacheDir()-->
    <!--<external-cache-path name="name" path="path" />-->

    <external-path
        name="download"
        path="/App/download/" />
</paths>

3.生成uri调用系统程序安装apk

/**
     * 安装apk
     *
     * @param context
     * @param filePath 本地apk路径
     */
    public static void installApk(Context context, String filePath) {
        try {
            File file = new File(filePath);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
            Uri contentUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                contentUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", file);
            } else {
                contentUri = Uri.fromFile(file);
            }
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
            List<ResolveInfo> resolveLists = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
            if (resolveLists != null) {
                for (ResolveInfo resolveInfo : resolveLists) {
                    if (resolveInfo != null && resolveInfo.activityInfo != null) {
                        String packageName = resolveInfo.activityInfo.packageName;
                        context.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
                                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
                    }
                }
            }
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4.签名权限授予

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

参考链接:
https://developer.android.com/about/versions/nougat/android-7.0-changes?hl=zh-cn
https://developer.android.com/reference/android/support/v4/content/FileProvider.html?hl=zh-cn

你可能感兴趣的:(android,Android更新,Android安装,安装apk,FileProvider)