目录
FileUriExposedException 错误
onActivityResult中resultCode为0(RESULT_CANCELED)
onActivityResult中Intent data为空
The exception that is thrown when an application exposes a file:// Uri to another app.
在Android N(7)以上(API 版本为24),当应用使用file:// 形式的Uri暴露给另一个应用时将会抛出该异常。而低于N之前的版本仍然可以使用file://的形式来共享Uri,但是十分不推荐这样做。
原因在于使用file://Uri会有一些风险,比如:
替代方案是通过FileProvider使用 content:// 形式的Uri并授临时权限给接收该Uri的应用。
解决方案:
FileProvider是ContentProvider的一个子类,它通过创建content:// 形式的Uri和其他应用之间进行文件安全共享。
Content URI通过使用临时访问权限允许你可以授予读写权限给其它应用,通过Intent.addFlags()添加权限。
只需通过以下几个步骤,就可以使用FileProvider解决问题
1.在manifest里注册增加
android:name是FileProvider组件的完整类名。
android:authorities是域名,为了保证唯一性(com.test.app,名字可自行替换)。
android:exported 设置false,因为你不需要暴露它。
android:grantUriPermissions设置true,表示允许你可以对文件授予临时权限。
2.添加file_paths.xml文件
3.使用FileProvider转化Uri
File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "test_image.jpg");
Uri imageUri = FileProvider.getUriForFile(getContext(), "com.test.app", newFile);//转化Uri
Intent intent =new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // action intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//设置拍照后存储Uri intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |Intent.FLAG_GRANT_WRITE_URI_PERMISSION);//添加运行时权限 startActivityForResult(intent,0);
在拍照返回后,我们通常用resultCode==RESULT_OK,判断当前拍照返回结果。
// 拍照返回
if (requestCode == 0 && resultCode == Activity.RESULT_OK) {
...
}
原因:调用MediaStore.EXTRA_OUTPUT设置自定义目录路径的问题,我们设置的路径文件不存在,拍照后保存的文件就出现问题。
解决方案:
判断file是否存在,不存在就调用mkdirs()
File imagePath = new File(Context.getFilesDir(), "images");
if (!imageFile.exists()){
imageFile.mkdirs();
}
File newFile = new File(imagePath, "test_image.jpg");
...
在拍照返回后,我们拿到的data为空。
原因:设置了拍照存储的Uri后,data就为空,我们只需要把我们设置的Uri保存,在拍照结果返回后处理就可以了。
解决方案:
File imagePath = new File(Context.getFilesDir(), "images");
if (!imageFile.exists()){
imageFile.mkdirs();
}
File newFile = new File(imagePath, "test_image.jpg");
Uri imageUri = FileProvider.getUriForFile(getContext(), "com.test.app", newFile);//转化Uri
//指定图片Uri,传文件地址
setCameraUri(Uri.parse(newFile.toString()));
通过Uri.parse(newFile.toString())拿到图片真实地址并保存,在拍照返回结果后处理相关逻辑
不要用FileProvider转化后的imageUri,这是相对地址,在使用的时候会存在一些问题。