成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我想把 FileProvider 聊的更透徹一些

開發 開發工具
從 Android N(7.0) 開始,將嚴格執行 StrictMode 模式,也就是說,將對安全做更嚴格的校驗。而從 Android N 開始,將不允許在 App 間,使用 file:// 的方式,傳遞一個 File ,否者會拋出 FileUriExposedException 的錯誤,會直接引發 Crash。

 一、前言

從 Android N(7.0) 開始,將嚴格執行 StrictMode 模式,也就是說,將對安全做更嚴格的校驗。而從 Android N 開始,將不允許在 App 間,使用 file:// 的方式,傳遞一個 File ,否者會拋出 FileUriExposedException 的錯誤,會直接引發 Crash。

但是,既然官方對文件的分享做了一個這么強硬的修改(直接拋出異常),實際上也提供了解決方案,那就是 FileProvider,通過 comtent:// 的模式替換掉 file:// ,同時,需要開發者主動升級 targetSdkVersion 到 24 才會執行此策略,也留給了開發者升級的時間。

本文就 FileProvider 需要了解的所有細節,進行一個詳盡的說明。

二、如何使用 FileProvider

1、什么是 FileProvider

FileProvider 是 Android support v4 包下,提供的一個 ContentProvider 的子類,用于向其他 App 分享文件,并且是在 v4 包下,所以只要引入了 v4 包,就可以做到全版本兼容。

既然 FileProvider 本質上就是一個 ContentProvider ,它其實也繼承了 ContentProvider 的特性。ContentProvider 其實就是在可控的范圍內,向外部其他的 App 分享數據。而 FileProvider 將這樣的數據變成了一個 File 文件而已。

2、在什么場景下需要使用 FileProvider

在 App 間對 file:// 的分享做了嚴格的校驗之后,其實也是出于安全考慮,這就導致了,所有包含 file:// 的URI 的 Intent 離開你的 App ,都受此限制。所以說,只要你的 App 內,通過一個 Intent 傳遞了一個 file:// 的 Uri ,就需要小心使用了。

在實際開發過程中,使用最多的場景有一下幾個:

  • 調用相機拍照。
  • 剪裁圖片。
  • 調用系統安裝器去安裝 Apk。

3、如何使用 FileProvider

1)在 AndroidManifest 中配置

前面提到,FileProvider 實際上是一個 ContentProvider ,所以如果需要使用它,就需要在 AndroidManifest.xml 中聲明它。

可以看到,provider 標簽下,配置了幾個屬性:

  • name :配置當前 FileProvider 的實現類。
  • authorities:配置一個 FileProvider 的名字,它在當前系統內需要是唯一值。
  • exported:表示該 FileProvider 是否需要公開出去,這里不需要,所以是 false。
  • granUriPermissions:是否允許授權文件的臨時訪問權限。這里需要,所以是 true。

可以看到 name 屬性就是標記當前 FileProvider 的實現類,對于一個 App Module 而言,如果只是自己使用,可以直接使用 v4 包下的 FileProvider ,但是如果是作為一個 Lib Module 來供其他項目使用,最好還是重新空繼承一個 FileProvider ,這里填寫我們的繼承類即可。

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

在配置 Provider 的時候,還需要額外配置一個 <meta-data/> 標簽,它用于配置 FileProvider 支持分享出去的目錄。這個 <meta-data/> 標簽的 name 值是固定的,resource 需要指向一個 根節點為 paths 的 xml 資源文件。

然后就可以對 provider_paths.xml 進行配置。

paths 標簽內,必須配置最少一個 xxx-path 標簽,上圖給出的例子,配置的是 files-path 這些配置的信息,都是可以在官方文檔中找到答案的,這里直接以查閱源碼的方式來查看他們分別代表的意思。

這些配置,在 FileProvider 的源碼內,都是以一個個 TAG_Xxx 標記的。

而他們分別代表的目錄,也可以在源碼內找到答案。

可以看到,不同的標簽,代表不同的目錄。

  • root-path:表示根目錄,『/』。
  • files-path:表示 content.getFileDir() 獲取到的目錄。
  • cache-path:表示 content.getCacheDir() 獲取到的目錄
  • external-path:表示Environment.getExternalStorageDirectory() 指向的目錄。
  • external-files-path:表示 ContextCompat.getExternalFilesDirs() 獲取到的目錄。
  • external-cache-path:表示 ContextCompat.getExternalCacheDirs() 獲取到的目錄。

注意,這里 ContextCompat 只是對 Context 做了一個兼容處理,其實就是對 Api level 19 做了一個分解,分別代表不同的獲取方式,以 getExternalFilesDirs() 為例。

3) 使用 content://

配置工作已經全部完成,后面就需要將之前傳遞的 file:// 替換成 FileProvider 需要的 content:// ,這就需要用到 FileProvider.getUriForFile() 方法了,以下是它的完整簽名。

getUriForFile() 方法,需要一個 authority 的參數,這正是前面在 AndroidManifest.xml 中 配置的 android:authorities 。

調用此方法,會自動得到一個 file:// 轉換成 content:// 的 一個 Uri 對象,可以供我們直接使用。

4) 授予臨時的讀寫權限

在配置 provider 標簽的時候,有一個屬性 android:grantUriPermissions="true" ,它表示允許它授予 Uri 臨時的權限。

當我們生成出一個 content:// 的 Uri 對象之后,其實也無法對其直接使用,還需要對這個 Uri 接收的 App 賦予對應的權限才可以。

授權類型的常量,被定義在 Intent 類中。

可以看到,直接就是讀和寫的權限授予。

而這個授權的動作,提供了兩種方式來授權:

1、使用 Context.grantUriPermission() 為其他 App 授予 Uri 對象的訪問權限。

它的完整簽名如下:

grantUriPermission() 方法包含三個參數,這三個參數都非常的好理解。

  • toPackage :表示授予權限的 App 的包名。
  • uri:授予權限的 content:// 的 Uri。
  • modeFlags:前面提到的讀寫權限。

這種情況下,授權的有效期限,從授權一刻開始,截止于設備重啟或者手動調用 Context.revokeUriPermission() 方法,才會收回對此 Uri 的授權。

2、配合 Intent.addFlags() 授權。

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

這種方式相信大家都比較熟悉,就不細說了。而使用這種形式的授權,權限截止于該 App 所處的堆棧被銷毀。也就是說,一旦授權,直到該 App 被完全退出,這段時間內,該 App 享有對此 Uri 指向的文件的對應權限,我們無法再主動收回此權限了。

雖然使用 Intent.addFlags() 的方式,一旦授權將無法主動回收,但是大多數情況下,也是會使用此種方式進行授權,除了操作起來方便之外,既然授權了也無需太擔心對方會有破壞的行為。有點切合 用人不疑,疑人不用 的道理。

擁有了授權權限的 content:// 的 Uri 之后,就可以通過 startXxx 或者 setResult() 的方式,將 Uri 傳遞給其他的 App。

5)舉個例子

到這里,基本上關于 FileProvider 的使用,都做了一個詳盡的說明,接下來舉個簡單的例子來看看如何使用它。

調起系統安裝器來安裝一個 Apk 。

三、FileProvider 的注意事項

1、authorities 的唯一性

在 AndroidManifest.xml 中配置 provider 的時候,需要保證 android:authorities 的值,在整個系統中的唯一性。其實這也很好理解,看了 FileProvider.getUriForFile() 之后,發現它是通過 android:authorities 屬性配置的值,來唯一確定由誰來響應這個 provider 的,所以它需要保證在系統內唯一,否者安裝的時候會拋出異常。

而在常規開發過程中,如果是一個 App Module 在使用 FileProvider 的話,那么只需要我們自己規范不要寫同一個 authorities 即可。但是如果是作為一個 Lib Module 發布出去的話,是需要考慮使用者的如何使用的,所以為了友好起見,最好使用 applicationId 來配置 provider 標簽。

這樣配置之后,就會使用 Gradle 中配置的 applicationId 的值替換這里,而使用 FileProvider.getUriForFile() 的時候,只需要根據 applicationId 拼接一個 authorities 值即可,簡單修改一下上面調用系統去安裝 APK 的例子。

2、Lib 下的 targetSdkVersion

前面提到,如果不將 targatSdkVersion 升級到 24 的話,之前的方式依然是可用的,不會有 FileUriExposedException 的隱患。但是如果你的項目是作為一個 Lib Module 這種 SDK 的形式發布出去,供其他人使用的話,這里的 targetSdkVersion 就不受 Lib 的 targetSdkVersion 控制,而是主項目的 targetSdkVersion。

所以如果是以 SDK 的形式集成到別的 App 內使用的話,如果需要用發送一個 File 給其他 App,一定要適配 FileProvider 。

3、不使用 v4 包

FIleProvider 是存在于的 Support v4 包下,所以想要使用 FileProvider 就必須集成 v4 包。但是對于一個本身無需使用 v4 包的項目來說,為了 FileProvider 來集成 v4 包,無形中就增加了安裝包的體積。

但是仔細看 FileProvider ,其實并沒有引用到什么更多的 package ,而 FileProvider 本質上也只是一個 ContentProvider ,所以我們只需要將它的代碼復制出來,簡單修改一下保證可以正確運行,就可以使用,而不是必須繼承 v4 包。

四、小結

FileProvider 的核心就是提高安全性,讓開發者來限制自己本 App 的文件對外的訪問權限,以提高安全性。

所以在開發過程中,只需要配合 FileProvider 將我們可能需要第三方 App 用到的文件目錄加入到可授權的范圍,然后在發送 Intent 的時候,對其進行授權即可,其他的操作和之前并無變化,這里就不一一列舉了。

【本文為51CTO專欄作者“張旸”的原創稿件,轉載請通過微信公眾號聯系作者獲取授權】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2021-06-30 07:19:35

微服務業務MySQL

2024-11-04 09:00:00

Java開發

2024-02-19 10:29:24

模型駕駛

2017-10-23 12:22:58

Android編程基礎總結

2014-03-17 10:10:58

CC++編程書籍

2023-03-13 09:07:02

2019-08-01 12:56:00

Python代碼記錄

2021-08-26 09:31:40

Nacos配置注冊

2015-12-30 11:14:57

前端工具

2021-12-22 10:49:42

架構運維技術

2023-10-31 07:39:36

2021-01-08 05:16:01

5G4GRRU

2018-01-03 10:32:21

面試經驗套路

2012-08-22 13:57:24

HybridHybrid開發

2021-05-25 05:28:05

uniCloud前端項目

2019-04-19 12:46:18

面試丁校招簡歷

2019-08-13 16:01:12

2020-08-26 08:54:17

CSSFont Size屬性

2013-03-29 13:17:53

XCode調試技巧iOS開發

2011-07-13 09:13:56

Android設計
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日日噜噜噜夜夜爽爽狠狠视频97 | 91 在线| 中文字幕视频在线观看 | 欧美h| 91精品中文字幕一区二区三区 | av香蕉 | 在线视频中文字幕 | 精品国产乱码久久久久久丨区2区 | 国产精品免费小视频 | 国产精品一区二区三区在线 | 人人干人人艹 | 欧美一级欧美三级在线观看 | 性国产xxxx乳高跟 | 欧美一区二区三区四区五区无卡码 | www.亚洲精品| 一区二区三区播放 | 久久久久久久一区二区 | 国产精品久久久久久久久久免费看 | 中文字幕一区在线观看视频 | 欧美亚洲国产一区二区三区 | 国产精品国产 | 国产一级片 | 欧美激情五月 | 神马久久av| 亚洲国产精品久久久久秋霞不卡 | 一区二区三区在线观看视频 | 第一区在线观看免费国语入口 | 欧美精品乱码久久久久久按摩 | 久久99精品国产麻豆婷婷 | 日韩免费福利视频 | 久久久久久综合 | 免费播放一级片 | 日韩1区| 高清视频一区二区三区 | 日韩欧美一级片 | 国产福利视频在线观看 | cao在线| 成人在线a| 国产精品欧美一区二区三区不卡 | 99re热精品视频 | 一级黄色绿像片 |