Android 7.0應用間文件共享

最近在開發過程中遇到了這樣一個錯誤,android.os.FileUriExposedException: file:///storage/emulated/0/xxx/xxx.doc exposed beyond app through Intent.getData()
出現這個問題是在使用Intent附帶uri打開sd卡下的doc文件,而在Android 7.0後,應用使用 StrictMode模式,API 禁止向您的應用外公開 file://URI並且使用Intent附帶uri訪問本地文件時,也是需要經過授權處理的。若要在應用間共享文件,您應發送一項 content://URI,並授予 URI 臨時訪問權限。進行此授權的最簡單方式是使用 FileProvider類
解決方法
1.在res目錄下新建一個xml文件夾,在此文件夾下創建file_path.xml文件(命名任意),文件內容如下

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path  path="." name="external_path"/>
    <cache-path path="." name="cache_path" />
    <files-path path="." name="files_path" />
    <external-files-path path="." name="external_files_path" />
    <external-cache-path path="." name="external_cache_path" />
</paths>

path:需要臨時授權訪問的路徑(.代表所有路徑)
name:就是你給這個訪問路徑起個名字
內部的element可以是files-path,cache-path,external-path,external-files-path,external-cache-path,分別對應Context.getFilesDir(),Context.getCacheDir(),Environment.getExternalStorageDirectory(),Context.getExternalFilesDir(),Context.getExternalCacheDir()等幾個方法

2.在AndroidManifest.xml的標籤下新增以下內容:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.example.demo.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_path"/>
</provider>

注意:
authorities:可以自定義,但爲了區分,建議用:app的包名.provider
grantUriPermissions:必須是true,表示授予 URI 臨時訪問權限
exported:必須是false
resource:中的@xml/file_paths是我們接下來要添加的文件

3.在使用Intent打開文件時,做如下判斷

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_DEFAULT);
Uri uri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    //第二個參數是manifest中定義的`authorities`
    uri = FileProvider.getUriForFile(context, "com.example.demo.provider", new File(param));
} else {
    uri = Uri.fromFile(new File(param));
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
intent.setDataAndType(uri, "image/*");
context.startActivity(intent);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章