目录
- FileUriExposedException
- 使用FileProvider
- 在manifest清单文件中注册provider
- 第二步:指定共享的目录
- file_paths
- 使用
- 参考
前言
刚刚说完6.0 ,继续说说7.0,只能说,权限越来越严格,现在的7.0 手机越来越多咯,从Android6.0引入的动态权限控制(Runtime Permissions)到Android7.0的“私有目录被限制访问”,都是泪
FileUriExposedException
为啥要做7.0 适配啊 ,为啥,不做就给你来个这个错误,哈哈
触发原因
在Android7.0中尝试传递 file:// URI 会触发 FileUriExposedException。
换句话说,只要我们用到URI 的地方,恭喜,全部FileUriExposedException,
使用FileProvider
第一步:在manifest清单文件中注册provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.allens.test.provider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
说明
-
exported
:要求必须为false,为true则会报安全异常 -
grantUriPermissions:true
,表示授予 URI 临时访问权限。 -
com.allens.test
就是程序的包名
android:authorities="com.allens.test.provider"
第二步:指定共享的目录
为了指定共享的目录我们需要在资源(res)目录下创建一个xml目录,然后创建一个名为file_paths
(名字可以随便起,只要和在manifest注册的provider所引用的resource保持一致即可)的资源文件
file_paths
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--path:需要临时授权访问的路径(.代表在相机调用时候访问的是所有路径,而文件写入时访问的路径是Android/data/com.ijuyin.prints.news/)-->
<!--name: 是你为设置的这个访问路径起的名字-->
<paths>
<external-path
name="camera_photos"
path="." />
<external-path
name="files_root"
path="Android/data/com.ijuyin.prints.news/" />
<external-path
name="external_storage_root"
path="." />
</paths>
</resources>
使用
所有以前使用URI的地方 例如 imageUri = Uri.fromFile(mTmpFile);
全部改成下面的代码
Uri imageUri;
//判断是否是7.0以上的设备
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//通过FileProvider创建一个content类型的Uri
imageUri = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".provider", mTmpFile);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}else{
// 还用以前的就好了
imageUri = Uri.fromFile(mTmpFile);
}
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI
startActivityForResult(intent, REQUEST_CAMERA);