Android 报错:android.os.FileUriExposedException: file:///storage/… exposed

原因:
android 23 以后传递软件包网域外的 file://URI 可能给接收器留下无法访问的路径。 因此,尝试传递 file://URI 会触发 FileUriExposedException。若要在应用间共享文件,您应发送一项 content://URI,并授予 URI 临时访问权限

解决办法1、

在需要的activity的onCreate方法中添加如下代码:

//API24以上系统分享支持file:///开头
StrictMode.VmPolicy.Builder builder = newStrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();

该方法关闭了StrictMode严格模式中虚拟机策略检测中关于文件uri暴露的检测:detectFileUriExposure()。
如果要使用这种方法,推荐使用更加暴力的
builder.detectAll()
关闭所有检测

解决办法2、
使用 FileProvider ,这也是官方推荐使用的方式

1、在AndroidManifest.xml文件中添加:

<application>    
...
<provider        
android:authorities="你应用的包名.fileprovider"        
android:name="android.support.v4.content.FileProvider"        
android:grantUriPermissions="true"        
android:exported="false">        
<meta-data            
android:name="android.support.FILE_PROVIDER_PATHS"            
android:resource="@xml/filepaths"/>    
</provider>    
...
</application>

其中:
authorities:app的包名.fileProvider
grantUriPermissions:必须是true,表示授予 URI 临时访问权限
exported:必须是false
resource:中的@xml/file_paths是我们接下来要添加的文件

2、在res目录下新建一个xml文件夹,并且新建一个文件名为 filepaths 的xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths>    
<external-path path="CHINARES_UT/" name="files_path" />
</paths>

其中:
paths标签中:
files-path代表的根目录: Context.getFilesDir().getPath()
external-path代表的根目录: Environment.getExternalStorageDirectory().getPath()
cache-path代表的根目录: getCacheDir().getPath()

path 代表需要共享的目录
name 只是一个标识,随便取

例:如上配置共享了使用 Environment.getExternalStorageDirectory().getPath() 方式获取的根目录下 CHINARES_UT 文件夹的内容

3、使用:

只需要在构建资源标识符Uri时,判断当前SDK是否大于等于24,然后采用不同方式构建即可,代码如下:

Uri uri;
File file = new File("文件路径");
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= 24) {    
uri = FileProvider.getUriForFile(this.getApplicationContext(), "应用包名.fileprovider", file);
} else {    
uri = Uri.fromFile(file);
}

具体使用举例:
android分享文件到微信和QQ

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐