1. 程式人生 > >android7.0 獲取uri

android7.0 獲取uri

android7.0以後,使用Uri.fromFile會報FileUriExposedException異常,這是因為android7.0以後執行了更加嚴格的檔案管理,要解決這一錯誤需要使用7.0新新增的FileProvide類,FileProvider官方文件:官方連結

FileProvider使用步驟:

1、定義一個FileProvider

在manifest裡面定義一個FileProvider:

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider" android:exported="false" android:grantUriPermissions="true"> ... </provider> ... </application> </manifest>

name直接使用系統的android.support.v4.content.FileProvider,如果需要自己繼承FileProvider,則在這裡寫自己的FileProvider,一定要寫全名,即:包名+類名。exported設定為false,即FileProvider不需要共享,grantUriPermissions設定為true,即允許獲取臨時讀取uri的許可權。

2、指定可用檔案

在res資原始檔夾下建立xml資料夾,在xml資料夾下建立一名為file_paths的資原始檔:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="images"/>
    ...
</paths>

paths元素必須包含以下一個或者多個子元素:

  1. files-path 對應目錄Context.getFilesDir()
  2. cache-path 對應目錄Context.getCacheDir()
  3. external-path 對應目錄Environment.getExternalStorageDirectory()
  4. external-files-path 對應目錄Context,getExternalFilesDir(String) 或者Context.getExternalFilesDir(null)
  5. external-cache-path 對應目錄Context.getExternalCacheDir()。

這一點要謹記,在後面建立檔案時會用到。
name 是分享的檔案路徑的一部分,它會覆蓋要分享的真實的路徑,即path指定的路徑。
path 即檔案真實路徑,最後創建出來的檔案路徑為(參照上述例子):Context.getFilesDir()+path+”/”+檔名。

然後在第一步的provider中引用這個資原始檔:

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

3、生成Uri

首先建立檔案:

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");

在建立第一個檔案即imagePath時,使用Context.getFilesDir()是因為第二步的資原始檔裡面使用了files-path,如改成external-path,則這裡要改成Environment.getExternalStorageDirectory(),其餘皆同。“images”對應的是第二步資原始檔裡面的path資源。最終newFile的檔名為:Context.getFilesDir()+”images/default_image.jpg”。

接下來,生成Uri:

Uri contentUri = FileProvider.getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);

getUriForFile方法中的第二個引數要與第一步中在manifest檔案裡面建立的provider裡面的android:authorities名稱一樣。

4、分享

使用intent分享檔案時,要加入臨時許可權,已拍照為例:

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);  
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);  
i.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);  
startActivity(i);