之前的项目有用户反馈在Android 7.0既以上版本在更换头像时出现崩溃现象,通过测试跟踪,发现报FileUriExposedException错误。今天做一下总结,并分享一下。
Android 6.0之后,需要动态申请权限。调用摄像头拍照获取图片这个功能,需要动态申请照相机权限、SD卡读写权限。
从Android 7.0开始,一个应用提供自身文件给其他应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException错误。有两种解决方法:FileProvider方式和VmPolicy方式。FileProvider方式是谷歌官方推荐的解决方法,具体操作如下。
1、在AndroidManiFest.xml中添加如下代码(红色部分)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="">
<application>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>
2、在res目录下新建一个xml文件夹,并且新建一个provider_paths的xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--"."表示所有路径-->
<external-path name="external_files" path="."/>
</paths>
3、使用到uri的代码
public void startCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
File cameraFile = FileUtils.createCameraFile(this);
cameraPath = cameraFile.getAbsolutePath();
Uri photoURI;
if(Build.VERSION.SDK_INT <= 23){
photoURI= Uri.fromFile(cameraFile);
}else{
/**
* 7.0 调用系统相机拍照不再允许使用Uri方式,应该替换为FileProvider
* 并且这样可以解决MIUI系统上拍照返回size为0的情况
*/
photoURI = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", cameraFile);
}
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(cameraIntent, REQUEST_CAMERA);
}
}
如上修改后再次调试,程序能正常运行。
关于FileProvider知识,在下篇中讲解。