Android FileProvider 的使用

1、前言

從 Android N(7.0) 開始葬凳,將嚴格執(zhí)行 StrictMode 模式。而從 Android N 開始室奏,將不允許在 App 間火焰,使用 file:// 的方式,傳遞一個 File 胧沫,否者會拋出 FileUriExposedException 的異常引發(fā) Crash昌简。解決方案就是通過 FileProvider 用 content:// 代替 file://占业,需要開發(fā)者主動升級 targetSdkVersion 到 24 才會執(zhí)行此策略。

2纯赎、讀取目錄

2.1 內(nèi)部存儲

每安裝一個 App 系統(tǒng)都會在內(nèi)部存儲空間的 data/data 目錄下以應(yīng)用包名為名字自動創(chuàng)建與之對應(yīng)的文件夾谦疾,這個文件夾用于持久化 App 中的 WebView 緩存頁面信息、SharedPreferences犬金、SQLiteDatabase 等應(yīng)用相關(guān)數(shù)據(jù)念恍。當(dāng)用戶卸載 App 時,系統(tǒng)自動刪除 data/data 目錄下對應(yīng)包名的文件夾及其內(nèi)容晚顷。

獲取并操作內(nèi)部存儲空間中的應(yīng)用私有目錄的方法如下:

  • context.getFilesDir()
  • context.getCacheDir()
  • context.deleteFile()
  • context.fileList()
  • Environment.getDataDirectory()

2.2 外部存儲

考慮到普通用戶無法訪問應(yīng)用的內(nèi)部存儲空間峰伙,比如用戶想從應(yīng)用里面保存一張圖片,那么這張圖片應(yīng)該存儲在外部存儲空間音同,用戶才能訪問的到

外部存儲空間路徑為:/storage/emulated/0/Android/data/<包名>

外部存儲分為應(yīng)用私有目錄公共目錄

(1)應(yīng)用私有目錄

默認情況下词爬,系統(tǒng)并不會自動創(chuàng)建外部存儲空間的應(yīng)用私有目錄。只有在應(yīng)用需要的時候权均,開發(fā)人員通過 SDK 提供的 API 創(chuàng)建該目錄文件夾和操作文件夾內(nèi)容。

當(dāng)用戶卸載 App 時锅锨,系統(tǒng)也會自動刪除外部存儲空間下的對應(yīng) App 私有目錄文件夾及其內(nèi)容叽赊。

獲取并操作外部存儲空間中的應(yīng)用私有目錄的方法如下:

  • context.getExternalFilesDir()
  • context.getExternalCacheDir()
  • Environment.getExternalStorageDirectory()

(2)公共目錄

外部存儲空間中的公共目錄用來存放當(dāng)應(yīng)用被卸載時,仍然可以保存在設(shè)備中的信息必搞,如:拍照類應(yīng)用的圖片文件必指,用戶是使用瀏覽器手動下載的文件等。恕洲、

外部存儲空間已經(jīng)為用戶默認分類出一些公共目錄塔橡。開發(fā)人員可以通過 Environment 類提供的方法直接獲取相應(yīng)目錄的絕對路徑,傳遞不同的 type 參數(shù)類型即可:

  • Environment.getExternalStoragePublicDirectory(String type);

Envinonment 類提供諸多 type 參數(shù)的常量霜第,比如:

  • DIRECTORY_MUSIC:/storage/emulated/0/Music
  • DIRECTORY_MOVIES:/storage/emulated/0/Movies
  • DIRECTORY_PICTURES:/storage/emulated/0/Pictures
  • DIRECTORY_DOWNLOADS:/storage/emulated/0/Download

3葛家、FileProvider

3.1 什么是 FileProvider

FileProvider 是 ContentProvider的子類 目前 support v4 包 和 androidx的core包里面都有提供。FileProvider 本質(zhì)上就是一個 ContentProvider 泌类,它其實也繼承了 ContentProvider 的特性癞谒。其實ContentProvider 就是在可控的范圍內(nèi),向外部其他的 App 分享數(shù)據(jù)刃榨。而 FileProvider 將這樣的數(shù)據(jù)變成了一個 File 文件而已弹砚。

3.2 使用 FileProvider 的場景

在 App 內(nèi),通過一個 Intent 傳遞了一個 file:// 的 Uri 的場景都需要使用 FileProvider 枢希,如:

  • 調(diào)用相機拍照
  • 剪裁圖片
  • 調(diào)用系統(tǒng)安裝器去安裝 Apk

3.3 如何使用 FileProvider

(1)在 AndroidManifest.xml 中聲明

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

可以看到桌吃,provider 標(biāo)簽下,配置了幾個屬性:

  • name:配置當(dāng)前 FileProvider 的實現(xiàn)類苞轿。
  • authorities:配置一個 FileProvider 的名字茅诱,它在當(dāng)前系統(tǒng)內(nèi)需要是唯一值逗物。
  • exported:表示該 FileProvider 是否需要公開出去,傳 false 表示不公開让簿。
  • granUriPermissions:是否允許授權(quán)文件的臨時訪問權(quán)限敬察。傳 true 表示需要 。

(2)指定可分享的文件路徑

沒有 xml 目錄可自行創(chuàng)建

src/main/res/xml/file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!--支持本地路徑-->
    <!--表示Environment.getExternalStorageDirectory() 指向的目錄-->
    <external-path name="external_storage_root" path="." />

    <!--表示 content.getFileDir() 獲取到的目錄-->
    <files-path name="files-path" path="." />

    <!--表示 content.getCacheDir() 獲取到的目錄-->
    <cache-path name="cache-path" path="." />

    <!--表示 ContextCompat.getExternalFilesDirs() 獲取到的目錄-->
    <external-files-path name="external_file_path" path="." />

    <!--表示 ContextCompat.getExternalCacheDirs() 獲取到的目錄-->
    <external-cache-path name="external_cache_path" path="." />

    <!--支持根路徑-->
    <root-path name="root_path" path="" />
</paths>
TAG Value Path
TAG_ROOT_PATH root-path /
TAG_FILES_PATH files-path /data/data/<包名>/files
TAG_CACHE_PATH cache-path /data/data/<包名>/cache
TAG_EXTERNAL external-path /storage/emulate/0
TAG_EXTERNAL_FILES external-files-path /storage/emulate/0/Android/data/<包名>/files
TAG_EXTERNAL_CACHE external-cache-path /storage/emulate/0/Android/data/<包名>/cache

(3)將 file:// 轉(zhuǎn)為 content://

使用 FileProvider.getUriForFile() 方法將 file:// 轉(zhuǎn)為 content://

// File 轉(zhuǎn) Uri
private Uri getUriForFile(File file) {
    String packageName = getPackage(this).packageName;
    Uri contentUri = FileProvider.getUriForFile(this, packageName+".fileProvider", file);
    return contentUri;
}

// 獲取當(dāng)前包名
public static PackageInfo getPackage(Context context) {
    PackageManager manager = context.getPackageManager();
    try {
        PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
        return  info;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return null;
    }
}

4尔当、參考

http://www.reibang.com/p/c87ff5eda539

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莲祸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子椭迎,更是在濱河造成了極大的恐慌锐帜,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畜号,死亡現(xiàn)場離奇詭異缴阎,居然都是意外死亡,警方通過查閱死者的電腦和手機简软,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門蛮拔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痹升,你說我怎么就攤上這事建炫。” “怎么了疼蛾?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵肛跌,是天一觀的道長。 經(jīng)常有香客問我察郁,道長衍慎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任皮钠,我火速辦了婚禮稳捆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鳞芙。我一直安慰自己眷柔,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布原朝。 她就那樣靜靜地躺著驯嘱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪喳坠。 梳的紋絲不亂的頭發(fā)上鞠评,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音壕鹉,去河邊找鬼剃幌。 笑死聋涨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的负乡。 我是一名探鬼主播牍白,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抖棘!你這毒婦竟也來了茂腥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤切省,失蹤者是張志新(化名)和其女友劉穎最岗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朝捆,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡般渡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芙盘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驯用。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖儒老,靈堂內(nèi)的尸體忽然破棺而出晨汹,到底是詐尸還是另有隱情,我是刑警寧澤贷盲,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站剥扣,受9級特大地震影響巩剖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钠怯,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一佳魔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晦炊,春花似錦鞠鲜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稳衬,卻和暖如春霞捡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背薄疚。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工碧信, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赊琳,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓砰碴,卻偏偏與公主長得像躏筏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子呈枉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容