Android调用系统相机拍照 7.0系统适配问题记录
目录
FileUriExposedException 错误
onActivityResult中resultCode为0(RESULT_CANCELED)
onActivityResult中Intent data为空
FileUriExposedException 错误
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会有一些风险,比如:
- 文件是私有的,接收file://Uri的app无法访问该文件。
- 在Android6.0之后引入运行时权限,如果接收file://Uri的app没有申请READ_EXTERNAL_STORAGE权限,在读取文件时会引发崩溃。
替代方案是通过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文件
<?xml version="1.0" encoding="utf-8"?>
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);
onActivityResult中resultCode为0(RESULT_CANCELED)
在拍照返回后,我们通常用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"); ...
onActivityResult中Intent data为空
在拍照返回后,我们拿到的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,这是相对地址,在使用的时候会存在一些问题。
更多相关文章
- 关于 SQLiteOpenHelper 的自创建数据库目录文件
- 设置android的布局文件的背景颜色为黑色
- Android 获取本地所有音频文件
- Android 权限清单
- android 读取根目录下的文件或文件夹
- Android Kotlin 动态申请权限
- Android实现文件保存数据,读取数据
- mono for android Json 上传文件