Android(Q)10 上的分區外部存儲訪問

Android(API 29)10 發佈至今已經有很多設備完成升級,如:小米九、Redmi K20pro、華爲 P30pro/Mate30pro 、榮耀 v30/v20、Oppo Reno、ONnePlus 7T、谷歌 Pixel 等都已經升級到 Android 10 的支持,很多應用市場也要求應用須要針對 Android 10 進行適配,其中最大的變動之一就是 scoped storagehtml

在針對目前 小米、華爲、Pixel 的幾臺 Android 10 手機作了測試,在不設置 requestLegacyExternalStorage 的前提下獲得結論(官方還沒徹底開啓限制的前提):android

  • 一、targetSDK 用 28 編譯的在 Android 10 上仍是能夠讀取到所有文件, 以後覆蓋安裝一個使用 targetSDK 29 的,還能繼續能夠訪問全路徑。ide

  • 二、卸載後直接用 targetSDK 29 編譯的會讀取不到。測試

而官方明確表示:ui

明年(2020),主要平臺版本將要求全部應用都使用分區存儲,不管應用的目標 SDK 級別是多少。所以,您應該提早確保您的應用可以使用分區存儲。爲此,請確保針對搭載 Android 10(API 級別 29)及更高版本的設備啓用了該行爲。 code

因此不論是使用 requestLegacyExternalStorage 仍是下降 targetSDK 都沒法在接下來2020 年的 Android(API 29)10 新版更新中被豁免。cdn

雖然做爲 Android 開發會由於沒法對用戶存儲目錄「隨心所欲」而頭痛,可是做爲用戶倒是感受欣喜的。視頻

由於長期以來 Android 用戶的本地存儲目錄都十分雜亂,開發者只要申請一次權限就能夠「隨心所欲」地建立和讀取本地存儲,雖然谷歌在 Android 4.4(API 19))引入了存 SAF(Storage Access Framework) , 可是開發者大部分時候都選擇無視。htm

我甚至想要一個系統標誌出這個文件是誰建立的 API ,由於最近遇到這個問題卻沒有頭緒: 爲何相冊里老是多出一張空白圖片,刪了後不久又重現?blog

官方解讀

爲了讓用戶更好地管理本身的文件並減小混亂,Android 10(API 29)開始應用在默認狀況下會被要求使用 scoped storage(即分區存儲),也就是說應用只能看到本身專有的目錄(Context.getExternalFilesDir())以及特定類型的媒體文件。

注意這個是強制性的,可是會有緩衝期,官方明確額表示,除非你的應用真的有強烈須要訪問專有目錄以及 MediaStore 以外的文件,不然最好使用分區存儲。

使用分區存儲的應用對本身建立的文件始終擁有讀/寫權限,不管文件是否位於應用的專有目錄內。這說明了默認分區存儲內的文件也只有應用本身能看到,就像是沙盒內,同時 getExternalFilesDir() 下的文件會隨着應用卸載而清除。

也就是說應用能夠無需申請任何權限使用 getExternalFilesDir()MediaStoreSAF 讀寫文件,**固然若是使用 MediaStore 讀取其餘應用的媒體集合時,是須要 READ_EXTERNAL_STORAGE **。

MediaStore 中支持的類型有:

  • 照片:存儲在 MediaStore.Images 中。
  • 視頻:存儲在 MediaStore.Video 中。
  • 音頻文件:存儲在 MediaStore.Audio 中。

另外還有其餘的限制,好比:

  • 應用沒有 ACCESS_MEDIA_LOCATION 權限,那麼訪問到的媒體資源中的 Exif 元數據會被修改.
  • 使用 MediaStore.Files 也僅顯示照片、視頻和音頻文件,例如不會顯示錶中的 PDF 文件。

總結起來結論就是:

  • 一、獲取系統相冊、視頻,圖片等須要經過 SAF ,利用 ContentResolverCursor 來提供。
  • 二、訪問公有目錄也須要經過 MediaStoreContentResolver ,好比保存圖片到外部公共存儲,拷貝文件到 Download 目錄等等。
  • 三、好比 new File(path).exists(); 等的判斷在公共目錄下不能再用了。

簡單來講就是:應用在本身的沙盒內能夠「隨心所欲」,經過 MediaStore 能夠分類整理文件,經過 SAF 能夠訪問其餘應用的公共媒體文件。

相關實踐操做推薦百度團隊的:《Android 10分區存儲介紹及百度APP適配實踐》

相關文章
相關標籤/搜索