日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Android 一起來(lái)看看 7.0 的新特性 FileProvider

 codingSmart 2021-10-22

公眾號(hào)回復(fù) 5 試試

前言

對(duì)于 Android 7.0,提供了非常多的變化,不過(guò)和我們開(kāi)發(fā)者關(guān)聯(lián)最大的,或者說(shuō)必須要適配的就是去除項(xiàng)目中傳遞 file:// 類似格式的 Uri 了。

對(duì)于面向 Android 7.0 的應(yīng)用,Android 框架執(zhí)行的 StrictMode API 政策禁止在應(yīng)用外部公開(kāi) file:// URI , 如果一項(xiàng)包含文件 URI 的 intent 離開(kāi)應(yīng)用,則應(yīng)用出現(xiàn)故障,并出現(xiàn) FileUriExposedException 異常。

要應(yīng)用間共享文件,您應(yīng)發(fā)送一項(xiàng)  content:// URI,并授予 URI 臨時(shí)訪問(wèn)權(quán)限。進(jìn)行此授權(quán)的最簡(jiǎn)單方式是使用 FileProvider 類。如需了解有關(guān)權(quán)限和共享文件的詳細(xì)信息,請(qǐng)參閱 共享文件

FileProvider 實(shí)際上是 ContentProvider 的一個(gè)子類,它的作用也比較明顯,file://Uri 不給用,那么換個(gè) Uri 為 content:// 來(lái)替代。

Provider 使用詳解

1、定義 FileProvider

我們先在 AndroidManifest 中進(jìn)行注冊(cè)

為什么要申明呢?當(dāng)然是因?yàn)?FileProvider 是 ContentProvider 的子類啊。

2、指定可分享的文件路徑

FileProvider 只能為指定的目錄中的文件生成內(nèi)容 URI。要指定目錄,就必須使用 <paths> 元素的子元素在 XML 中指定其存儲(chǔ)區(qū)域和路徑。

我們先創(chuàng)建一個(gè)名為 res/xml/filepaths.xml 的新文件

在 filepaths.xml 文件中,便可以指定文件存儲(chǔ)的區(qū)域和路徑。例如,以下路徑元素告訴 FileProvider,你打算為私有文件區(qū)域的 images/ 子目錄 請(qǐng)求內(nèi)容 URI

<paths> 必須包含以下元素中一個(gè)或者多個(gè)子元素

paths 節(jié)點(diǎn)內(nèi)部支持以下幾個(gè)子節(jié)點(diǎn),分別為:

子節(jié)點(diǎn)含義
<root-path>代表設(shè)備的根目錄 new File("/")
<files-path>代表 context.getFileDir()
<cache-path>代表 context.getCacheDir()
<external-path>代表 Environment.getExternalStorageDirectory()
<external-files-path>代表 context.getExternalFilesDirs()
<external-cache-path>代表 getExternalCacheDirs()

每個(gè)節(jié)點(diǎn)都使用兩個(gè)屬性:

  • name

  • path

path 即為代表目錄下的子目錄,例如:

<external-path name="external" path="pics"/>

代表的目錄即為:Environment.getExternalStorageDirectory()/pics

當(dāng)這么聲明以后,代碼可以使用你所聲明的當(dāng)前文件夾以及其子文件夾

可能你會(huì)有疑問(wèn),為什么要寫(xiě)這么個(gè) xml 文件,有啥用呢?

我們剛才說(shuō)了,現(xiàn)在要使用 content://uri 替換 file://uri,那么,content://uri 如何定義呢?總不能使用文件路徑吧,那不是騙自己么

所以,需要一個(gè)虛擬的路徑對(duì)文件路徑進(jìn)行映射,所以需要編寫(xiě)個(gè) xml 文件,通過(guò) path 以及 xml 節(jié)點(diǎn)確定可訪問(wèn)的目錄,通過(guò) name 屬性來(lái)映射真實(shí)的文件路徑

寫(xiě)好 filepaths.xml 文件之后,要將此文件鏈接到 FileProvider 中,就必須添加一個(gè) <meta-data> 元素作為定義 FileProvider<provider> 元素的子元素。將 <meta-data> 元素的 android : name 屬性設(shè)置為 android.support.FILE_PROVIDER_PATHS, 將元素的 "android : resource" 屬性設(shè)置為 @xml / filepaths (注意不要指定 .xml 拓展名)。例如:

3、使用 FileProvider 生成內(nèi)容 URI

配置工作已經(jīng)全部完成了,后面就需要將之前傳遞的 file:// 替換成 FileProvoider 需要用到的 content://,這就需要用到 FileProvider.getUriForFile() 方法了

可以看到 getUriForFile(),需要傳入 一個(gè)
authority 的參數(shù),這正是我們前面在 AndroidManifest.xml 文件中配置的 android:authorities 參數(shù)

調(diào)用這個(gè)方法會(huì)自動(dòng)得到一個(gè) file:// 轉(zhuǎn)換成 content:// 的一個(gè) Uri 對(duì)象,可以供我們直接使用

4、給 Uri 授予臨時(shí)權(quán)限

當(dāng)我們生成一個(gè) content:// 的 Uri 對(duì)象之后,其實(shí)還無(wú)法對(duì)其直接使用,還需要對(duì)這個(gè) Uri 接收的 App 賦予對(duì)應(yīng)的權(quán)限才可以。

這個(gè)授權(quán)的動(dòng)作,提供了兩種方式來(lái)授權(quán):

① 通過(guò) Context 的 grantUriPermission() 方法授權(quán)

Context 提供了兩個(gè)方法

  • grantUriPermission(String toPackage, Uri uri, int modeFlags)

  • revokeUriPermission(Uri uri, int modeFlags);

可以看到 grantUriPermission() 方法需要傳遞一個(gè)包名,就是你給哪個(gè)應(yīng)用授權(quán),但是很多時(shí)候,比如分享,我們并不知道最終用戶會(huì)選擇哪個(gè) app,所以我們可以這樣:

根據(jù) Intent 查詢出所有符合的應(yīng)用,都給他們授權(quán),然后在不需要的時(shí)候通過(guò) revokeUriPermission 移除權(quán)限。

② 配合 Intent.addFlags() 授權(quán)

既然這是一個(gè) Intent 的 Flag,Intent 也提供了另外一種比較方便的授權(quán)方式,那就是使用 Intent.setFlags() 或者 Intent.addFlag 的方式

使用這種形式的授權(quán),權(quán)限截止于該 App 所處的堆棧被銷毀。也就是說(shuō),一旦授權(quán),知道該 App 被完全退出,這段時(shí)間內(nèi),該 App 享有對(duì)此 Uri 指向的文件的對(duì)應(yīng)權(quán)限,我們無(wú)法主動(dòng)收回該權(quán)限了。

總結(jié)

Android 7.0 禁止在應(yīng)用外部公開(kāi) file:// URI,所以我們必須使用 content:// 替代 file://,這時(shí)主要需要 FileProvider 的支持,而因?yàn)?FileProvider 是 ContentProvider 的子類,所以需要在 AndroidManifest.xml 文件中進(jìn)行注冊(cè),而又因?yàn)樾枰獙?duì)真實(shí)的 filepath 進(jìn)行映射,所以需要編寫(xiě)一個(gè) xml 文檔,用于描述可使用的文件夾目錄,以及通過(guò) name 去映射該文件夾目錄。

當(dāng)我們生成一個(gè) content:// 的 Uri 對(duì)象之后,還需要對(duì)這個(gè) Uri 接收的 App 賦予對(duì)應(yīng)的權(quán)限,到此本文的內(nèi)容就基本結(jié)束了。

參考

  • http://blog.csdn.net/lmj623565791/article/details/72859156

  • http://www.jianshu.com/p/3879bb6ff0ed

  • https://developer./training/secure-file-sharing/index.html

與之相關(guān)

非常有用的資源合集-開(kāi)發(fā)設(shè)計(jì)再也不愁啦

2017 | 我在 5 個(gè)月時(shí)間里分享了 98 篇文章

微信號(hào):code-xiaosheng

公眾號(hào)

「code小生」

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多