FileUriExposedException_Android7.0適配

一. FileUriExposedException的解決

問題

因爲在Android7.0上,google使用了新的權限機制,因此致使在調用相機的時候,若是傳遞的URI爲」file://」類型,的系統會拋出FileUriExposedException這個錯誤.具體堆棧信息以下:css

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. 解決URI
    原本是直接經過Uri.fromFile(file)獲取的uri,而後經過Intent傳出,在Android7.0及以上版本能夠採用以下方式獲取urijava

    // 中間的參數 authority 能夠隨意設置.
    Uri uri = FileProvider.getUriForFile(context,"org.diql.fileprovider", file);

    經過這個方法,系統會產生一個臨時的uri來進行替換掉原始的uri.android

  2. AndroidManifest.xml中配置markdown

    <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>
  3. res中建立相應的文件來讓系統最終生成相應的的uri.
    res的如2中的路徑新建對應的文件,這裏就是res->xml->file_paths.xml.其中’file_paths.xml’文件的內容以下app

    <?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>

原本覺得問題就此解決了,可是又產生了下面的問題ide

二. 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)
...

問題解決

明明這個路徑對應的文件是存在的,爲何會找不到呢,感受到確定是路徑配置那裏出問題,通過查找資料,才發現file_paths.xml中配置的external-path是以下做用:oop

該方式提供在外部存儲區域根目錄下的文件。它對應Environment.getExternalStorageDirectory返回的路徑:eg:」/storage/emulated/0」;google

external-files-path的做用是我須要的這種路徑即:spa

該方式提供在應用的外部存儲區根目錄的下的文件。它對應Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)返回的路徑。eg:」/storage/emulated/0/Android/data/com.jph.simple/files」。.net

將這個修改好以後就一切大工告成了.

參考資料

  1. http://blog.csdn.net/xifengwanzhao/article/details/53587234
  2. FileProvider所支持的幾種path類型 http://www.jianshu.com/p/121bbb07cb07
相關文章
相關標籤/搜索