FileUriExposedException_Android7.0适配

本文介绍了如何解决Android 7.0及以上版本中出现的FileUriExposedException问题,并详细阐述了解决方案,包括使用FileProvider获取URI及正确配置AndroidManifest.xml和file_paths.xml的方法。

一. FileUriExposedException的解决

问题

由于在Android7.0上,google使用了新的权限机制,所以导致在调用相机的时候,如果传递的URI为”file://”类型,的系统会抛出FileUriExposedException这个错误.具体堆栈信息如下:

    android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/***/files/Cache/30001748.jpg exposed beyond app through ClipData.Item.getUri() at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799) at android.net.Uri.checkFileUriExposed(Uri.java:2346) at android.content.ClipData.prepareToLeaveProcess(ClipData.java:832) at android.content.Intent.prepareToLeaveProcess(Intent.java:8923) at android.content.Intent.prepareToLeaveProcess(Intent.java:8908) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1519) at android.app.Activity.startActivityForResult(Activity.java:4288) ... at android.view.View.performClick(View.java:5611) at android.view.View$PerformClick.run(View.java:22276) at android.os.Handler.handleCallback(Handler.java:754) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:160) at android.app.ActivityThread.main(ActivityThread.java:6139) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

解决办法

  1. 解决URI 
    本来是直接通过Uri.fromFile(file)获取的uri,然后通过Intent传出,在Android7.0及以上版本可以采用如下方式获取uri

    // 中间的参数 authority 可以随意设置.
    Uri uri = FileProvider.getUriForFile(context,"org.diql.fileprovider", file);
    • 1
    • 2

    通过这个方法,系统会产生一个临时的uri来进行替换掉原始的uri.

  2. AndroidManifest.xml中配置

    <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="org.diql.fileprovider" //这里就是1中的参数 authority android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  3. res中创建相应的文件来让系统最终生成相应的的uri. 
    res的如2中的路径新建对应的文件,这里就是res->xml->file_paths.xml.其中’file_paths.xml’文件的内容如下

    <?xml version="1.0" encoding="utf-8"?>
        <resource xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="cache" path="Cache/" /> //这里的"Cache/"就是问题中抛出异常的那个路径 </resource>
    • 1
    • 2
    • 3
    • 4

本来以为问题就此解决了,但是又产生了下面的问题

二. IllegalArgumentException: Failed to find configured root that contains …

问题2

java.lang.RuntimeException: Unable to start activity ComponentInfo{.../....EditInfoActivity}: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/.../files/Cache/30001748.jpg at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2680) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1492) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:160) at android.app.ActivityThread.main(ActivityThread.java:6139) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764) ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

问题解决

明明这个路径对应的文件是存在的,为什么会找不到呢,感觉到肯定是路径配置那里出问题,经过查找资料,才发现file_paths.xml中配置的external-path是如下作用:

该方式提供在外部存储区域根目录下的文件。它对应Environment.getExternalStorageDirectory返回的路径:eg:”/storage/emulated/0”;

external-files-path的作用是我需要的这种路径即:

该方式提供在应用的外部存储区根目录的下的文件。它对应Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)返回的路径。eg:”/storage/emulated/0/Android/data/com.jph.simple/files”。

将这个修改好之后就一切大工告成了.

参考资料

  1. http://blog.youkuaiyun.com/xifengwanzhao/article/details/53587234
  2. FileProvider所支持的几种path类型 http://www.jianshu.com/p/121bbb07cb07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值