解决Android N报错: android.os.FileUriExposedException

从谷歌官方文档的描述来看,在Android N版本以上,直接将file://形式的Uri暴露给了APP应用,会抛出FileUriExposedException异常。
Android N以下版本,仍然可以使用file://形式的Uri,但强烈不推荐。
不推荐使用file://的原因在于:

  1. 如果文件是私有的,app将无法访问该文件。
  2. 在Android6.0之后引入运行时权限,如果接收file://Uri的app没有申请READ_EXTERNAL_STORAGE权限,在读取文件时会引发崩溃。

Android N以上版本,将使用content://代替file://形式的Uri,系统将赋予APP临时的权限去获取目标Uri的资源。

1.FileProvider

FileProvider是ContentProvider的一个子类。使用FileProvider可以创建content://形式的Uri,保证APP对文件资源的安全共享。
要使用FileProvider解决Android N以上版本android.os.FileUriExposedException的问题,首先要在AndroidManifest.xml注册该FileProvider:



    
        ...
        
                
       
   

然后在res文件夹里添加创建xml/file_paths.xml文件:



    
    
    
      
    
    
    
    
    
    
    
      
 

创建content://Uri,通过FileProvider.getUriForFile(Context context, String authorities, File file)实现。为了实现兼容,可通过根据设备系统使用不同的方法获取Uri:

public class FileUtils {
    public static Uri getUri(Context context, String authorites, File file) {
        Uri uri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //设置7.0以上共享文件,分享路径定义在xml/file_paths.xml
            uri = FileProvider.getUriForFile(context, authorites, file);
        } else {
            // 7.0以下,共享文件
            uri = Uri.fromFile(file);
        }
        return uri;
    }
}

这样就同时兼容file://content://的Uri形式,下面的例子是调用系统相机拍照时,通过FileUtils获取照片保存路径的Uri:

File file = new File(Environment.getExternalStorageDirectory() + "/files/", System.currentTimeMillis() + ".jpg".)
cameraFile.getParentFile().mkdirs();
// 获取照片保存路径Uri
Uri uri = FileUtils.getUri(getContext(), "com.myPackage.fileProvider", )
// 调用系统相机
startActivityForResult(
                new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(MediaStore.EXTRA_OUTPUT, uri),
                REQUEST_CODE_CAMERA);

参考博客:

  1. 使用FileProvider解决Android 7(N)以上FileUriExposedException
  2. Android 7.0 FileProvider 使用说明

你可能感兴趣的:(解决Android N报错: android.os.FileUriExposedException)