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会有一些风险,比如:

  1. 文件是私有的,接收file://Uri的app无法访问该文件。
  2. 在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文件

 
 
 

 

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,这是相对地址,在使用的时候会存在一些问题。

你可能感兴趣的:(android)