- android 7.0 新增私有目录访问权限
Google 官方说明:
为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问 (0700)。此设置可防止私有文件的元数据泄漏
官方文档:
https://developer.android.google.cn/about/versions/nougat/android-7.0-changes.html#perm
- 7.0 以上访问 file://uri 触发 FileUriExposedException(安全异常)
例如安装 apk 的方法
public static void installApp(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
7.0 以上会报错,如下:
异常
- 解决方案 使用 FileProvider
在 res 目录 xml 文件夹下创建你的 provider path 文件
manifest_folderprovider 文件内容
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="随便起名不能为空" path=""/>
<grant-uri-permission android:path="string"
android:pathPattern="string"
android:pathPrefix="string" />
</paths>
在 AndroidManifest 的 application 节点声明 provider
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="你的应用程序包名.provider"
android:exported="false"
android:grantUriPermissions="true"
>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/ls_provider_paths"
/>
</provider>
</application>
最后安装时获取临时权限
public static void installApp(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri;
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// 7.0 以上
uri = FileProvider.getUriForFile(context, "你的应用程序包名.provider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
// 7.0 以下
uri = Uri.fromFile(file);
}
intent.setDataAndType(uri, "application/vnd.android.package-archive");
context.startActivity(intent);
}
- 注意
如果你引用的第三方包已经使用了 provider 会报如下错误:
build_error原因:声明冲突
解决办法:打开 AndroidManifest 文件 Tab 页中的 Merged Manifest 发现冲突 log ,并且系统已给出了解决建议:
声明冲突原来是 provider 节点的 authorities 声明和 meta-data 节点的 resource 声明,将这俩覆盖
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="你的应用程序包名.provider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities"
>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/ls_provider_paths"
tools:replace="android:resource"
/>
</provider>
</application>
到此,问题解决。
网友评论