最近项目中有一个很简单的需求:就是用系统自带图库打开在APP中下载的图片,结果就遇到了

android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/xxx.jpg exposed beyond app through Intent.getData()

的异常。

原来从Android 7.0开始,谷歌收回了访问文件的权限,即一个应用提供自身资源文件给其它应用使用时,如果给出 file://xxx 这样格式的URI的话,谷歌会认为目标应用不具备访问此文件的权限,便会抛出 FileUriExposedException 的异常。我这里的解决方法是使用 FileProvider,来生成一个content://xxx 格式的URI,并授予此 URI 临时访问权限,ok,异常解决了。下面我们来一起看看实现方式吧:

1.在 Manifest中声明FileProvider

                                        

name为 FileProvider的完整类名:android.support.v4.content.FileProvider ,是固定的;

authorities为自定义的权限名称,大家可以自定义,通常都会带上包名来避免与其他应用冲突;

exported为 false,代表只有同一个应用程序的组件或带有相同用户ID的应用程序才能使用,在 FileProvider的使用中一定要填false,否则会报错;

grantUriPermissions为true,代表允许通过接受传递的权限方式进行访问,拥有共享文件的临时权限。即如果应用A具有读取  ContentProvider 的权限,它去调用另一个应用B的activity,但是B没有读取此 ContentProvider 的权限,那么应用A可以将自己的权限通过intent传递给应用B,让其也具有访问此ContentProvider 的权限。(因此后面代码中会对Intent 进行设置: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

2.在res下的xml文件夹中新建一个provider_paths.xml文件(名字可自定义,和上一步中resource的value一致即可)

                

内部的element可以是 files-path,cache-path,external-path等,代表的根目录分别对应为:Context.getFilesDir(),Context.getCacheDir(),Environment.getExternalStorageDirectory()等。

name是一个标识,作为根目录的名称,可以自定义;

path代表根目录下要共享的目标。

这里大家也许看的会有些困惑,我举个简单的例子:

大家都知道 ContentProvider 使用 URI 标识要操作的数据,这里的内容 URI 主要包括两部分:authority:整个提供程序的符号名称;path:指向表的名称/路径,所以内容 URI 统一的形式就是:content://authority/path。

那么当我们以上面为例,通过 FileProvider 获取到的某资源文件(比如根目录下的xxx.jpg)的uri链接即为:content://com.xxx.fileprovider/gallery_photos/xxx.jpg

3.在代码中调用(我这里就以实现用系统自带图库打开下载的一张图片为例了)

                    Intent intent = new Intent(Intent.ACTION_VIEW);                    Uri photoURI = FileProvider.getUriForFile(getApplicationContext(),                            "com.xxx.fileprovider",                            file);//file即为所要共享的文件的file                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//授予临时权限别忘了                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                    intent.setDataAndType(photoURI, "image/*");                    startActivity(intent);

ok,至此 FileProvider 的基本使用就完成了。

更多相关文章

  1. Android(安卓)apk文件拆解与重新打包
  2. android studio中xml文件报错: URI is not registered的解决办法
  3. Android::开机自启动C程序
  4. Android(安卓)TV 键值修改流程
  5. android 缓存 清理
  6. Android软件测试的日志文件问题
  7. Android如何在app中通过一个按钮直接跳转到的系统的权限设置页面
  8. Android(安卓)Studio中读取文本文件内容方法
  9. android flash分区(nand flash)

随机推荐

  1. Android日期空间(DatePickerDialog)中的年
  2. Android 4.0 横竖屏切换注意事项
  3. Android Studio 1.0 官网下载链接
  4. Android拍照,上传,预览综合【修改】
  5. Android Maven 采用第三方jar包,程序运行
  6. Android ExpandableListView开发简介
  7. Ubuntu下android studio 编译报错A probl
  8. Android如何在广播接收器中启动活动和弹
  9. android 短信监听
  10. Android EditText 监听回车键