Android 應用間共享文件(FileProvider)

在 Android 7.0 中調用系統相機拍照,通過SD卡獲取原圖,拋出FileUriExposedException異常

從 Android 7.0 開始,應用間共享文件時,如果使用 file://格式的 Uri,就會拋出 FileUriExposedException。
谷歌官方推薦,使用 FileProvider 來生成一個 content://格式的Uri。

FileProvider的使用

1. 在 Manifest 中聲明 provider

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.marklei.fileproviderdemo">

    <application
        ...>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.marklei.fileproviderdemo"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
        ...
    </application>
</manifest>

exported: false 表示 provider 不需要對外開放
grantUriPermissions: true,表示授予 Uri 臨時訪問權限。

2. res/xml/ 下定義對外暴露的文件夾路徑
file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path
        name="my_images"
        path="images/" />
</paths>

name: 一個引用字符串。
path: 文件夾“相對路徑“,完整路徑取決於當前的標籤類型。

path 可以爲空,表示制定目錄下的所有文件、文件夾都可以被共享。

3. 生成 content://類型的 Uri
通過 FileProvider.getUriForFile 來實現:

    File dir = new File(getFilesDir(), "images");
    String fileName = System.currentTimeMillis() + ".jpg";
    File file = new File(dir, fileName);
    Uri uri = FileProvider.getUriForFile(this, "com.marklei.fileproviderdemo", file);

dir: 使用的路徑需要和 file_paths.xml 中聲明的其中一個相符。
getUriForFile: 第一個參數是Context;第二個參數是在 manifest#provider 中定義的 android:authorities 屬性的值;第三個參數是File。

4. 使用 Intent 傳遞 Uri
調用拍照代碼:

    File file = ...;

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    Uri uri = FileProvider.getUriForFile(this, "com.marklei.fileproviderdemo", file);   
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(intent, REQ_CODE);

項目源碼:https://github.com/Freakmaster/FileProviderDemo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章