Android 7.0安装apk

在做应用版本更新的时候使用Android 7.0的手机测试发现一个问题:下载完成安装包之后,不能跳转到安装界面,使用7.0以下的手机没遇到这种情况。

对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。
如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。

要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。
既然Android 7.0对文件访问做了限制,下面介绍如何利用FileProvider类进行授权:

1 . 在清单文件中定义一个FileProvider

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
        ...>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.myapp.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
        ...
    </application>
</manifest>
2 . 指定共享目录
在上面代码中android:resource="@xml/filepaths" ,说明在我们的项目中有一个filepaths.xml文件,它记录了我们共享文件的位置,这个文件在项目中结构中的位置 : res/xml/filepaths.xml


filepaths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path path="Download/" name="Download" />
    <!--物理路径相当于Context.getExternalFilesDir(String) + /Download/ -->
</paths>
上述内容指定了要分享文件的目录位置,对于我们下载安装apk来说,即apk文件下载到了手机的什么目录位置,一定要与自己apk的下载目录相同!
我项目中apk包的下载位置是

context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
/storage/emulated/0/Android/data/your-package/files/Download/appName.apk
下面还有一些path路径,请根据自己apk包的下载位置选择合适的path
<files-path name="name" path="path" /> 物理路径相当于Context.getFilesDir() + /path/

<cache-path name="name" path="path" /> 物理路径相当于Context.getCacheDir() + /path/

<external-path name="name" path="path" /> 物理路径相当于Environment.getExternalStorageDirectory() + /path/

<external-files-path name="name" path="path" /> 物理路径相当于Context.getExternalFilesDir(String) + /path/

<external-cache-path name="name" path="path" /> 物理路径相当于Context.getExternalCacheDir() + /path/
3 . 安装apk
private void installApk() {
    File file = new File(apk包的路径);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if(Build.VERSION.SDK_INT>=24) { //Android 7.0及以上
        // 参数2 清单文件中provider节点里面的authorities ; 参数3  共享的文件,即apk包的file类
        Uri apkUri = FileProvider.getUriForFile(context, "com.example.myapp.fileprovider", file);
        //对目标应用临时授权该Uri所代表的文件
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    }else{
        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
    }
    context.startActivity(intent);
}

想了解更多Android 7.0与之前版本的不同,详情请看 Android 7.0 行为变更

猜你喜欢

转载自blog.csdn.net/github_2011/article/details/74297460