
For apps targeting Android 7.0, the Android framework enforces the StrictMode API policy that prohibits exposing file:// URIs outside your app. If an intent containing a file URI leaves your app, the app fails with a FileUriExposedException exception.To share files between applications, you should send a content:// URI and grant a temporary access permission on the URI. The easiest way to grant this permission is by using the FileProvider class. For more information on permissions and sharing files, see Sharing Files.
以上是官方文档给出的介绍,大致意思也就是: 对于面向 Android N 的应用,Android 框架执行的 StrictMode API 政策禁止向您的应用外公开 file:// URI。 如果一项包含文件 URI 的 Intent 离开您的应用,应用失败,并出现 FileUriExposedException 异常。
若要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。 进行此授权的最简单方式是使用 FileProvider 类。 如需有关权限和共享文件的更多信息,请参阅共享文件。
1 | FileProvider |
示例
我们先来看看以下的代码:
1 | package com.xw.fileproviderdemo; |
以上示代码通过调用系统的照相机拍照,保存图片到sdcard,并裁剪显示到界面上。
我们通过这个示例为代表,来说明本节的内容。
复现问题
当然在Android 7.0以下,你依然可以使用上面的代码来实现拍照裁剪显示。
但是当你使用的设备是Android 7.0及其以上的时候,使用以上代码,就会抛出开篇所提到的FileUriExposedException异常
android.os.FileUriExposedException:file://…. exposed beyond app through ClipData.Item.getUri()
解决方案
定义FileProvider
1 |
|
注:
- exported:必须为false,为true会报安全异常
- grantUriPermissions:为true 表示授予该URI临时访问权限
验证可用的文件
在res/xml资源目录下创建指定的xml文件
1 |
|
以上代码表示的是:可以访问外部存储目录更目录下的文件,因为拍照后的图片是保存在Environment.getExternalStorageDirectory()下的,
也就是
注:
- files-path 代表:Context.getFilesDir().
- cache-path 代表:getCacheDir().
- extenal-path 代表:Environment.getExternalStorageDirectory().
- external-files-path 代表:Context#getExternalFilesDir(String) Context.getExternalFilesDir(null).
- external-cache-path 代表:Context.getExternalCacheDir().
给Files生成Content URI
1 | private void takePhoto() { |
以上的代码,将getUriForFile()返回的uri打印出来是:
content://com.xw.fileproviderdemo.takePhoto.provider/image/xxxx.jpg
由此可以看出:
image:就是xml中
com.xw.fileproviderdemo.takePhoto.provider/image对应的路径就是/storage/emulated/0
那么com.xw.fileproviderdemo.takePhoto.provider/image/xxxx.jpg对应的路径就是/storage/emulated/0/xxxx.jpg
通过以上的代码修改,可以解决takePhoto()方法中拍照时的FileUriExposedException异常
再次运行项目,可以进行拍照了,拍照完成后,接下来需要进行裁剪,BOOM……Crash…Stop !!!,项目又崩溃了,然后抛出以下的异常:
给URI临时授权
同理,抛出的异常和上面takePhoto()一样,都是FileUriExposedException异常
将接收该uri的目的App的PackageName通过grantUriPermission()函数进行设置,授予读写权限:
1 | private void clipPhoto(Uri uri) { |
同样,调用的时候也将file uri的获取方式由fromfile改变为由FileProvider.getUriForFile获取:
1 | /*调用裁剪图片的方法进行裁剪图片*/ |
最后,再次运行,所有Exception都解决了,Perfect ~ !
效果如下:
- 以上就是简单的对Android 7.0上面权限改变之文件共享方面的概括总结,如有不足,欢迎指正,谢谢