什么是分區(qū)存儲(chǔ):
為了讓用戶更好地控制自己的文件并減少混亂,Android 10 針對(duì)應(yīng)用推出了一種新的存儲(chǔ)范例袱巨,稱為分區(qū)存儲(chǔ)金抡。分區(qū)存儲(chǔ)改變了應(yīng)用在設(shè)備的外部存儲(chǔ)設(shè)備中存儲(chǔ)和訪問文件的方式沪羔。以 Android 10(API 級(jí)別 29)及更高版本為目標(biāo)平臺(tái)的應(yīng)用在默認(rèn)情況下被授予了對(duì)外部存儲(chǔ)空間的分區(qū)訪問權(quán)限(即分區(qū)存儲(chǔ))臣镣。此類應(yīng)用只能訪問外部存儲(chǔ)空間上的應(yīng)用專屬目錄谣膳,以及本應(yīng)用所創(chuàng)建的特定類型的媒體文件净神。
適配背景:由于app需要到google play上架何吝,由于第一次提交該應(yīng)用,google play認(rèn)為是新應(yīng)用鹃唯,要求target sdk版本必須>=30(google play上的老應(yīng)用沒有這個(gè)限制)爱榕。于是把target sdk由28升到了30,又沒有及時(shí)對(duì)分區(qū)存儲(chǔ)進(jìn)行適配坡慌,引發(fā)了一些問題黔酥。
目前谷歌對(duì)分區(qū)存儲(chǔ)給了一個(gè)過渡期,由于國內(nèi)應(yīng)用市場并未對(duì)targetsdk版本做限制洪橘,網(wǎng)上適配也多以降級(jí)targetsdk的方式來解決跪者。
Android 存儲(chǔ)分區(qū)情況
Android 中存儲(chǔ)可以分為兩大類:專屬存儲(chǔ)和共享存儲(chǔ)
專屬存儲(chǔ) (Private Storage) : 每個(gè)應(yīng)用在都擁有自己的專屬目錄,其它應(yīng)用看不到熄求,彼此也無法訪問到該目錄:
- 內(nèi)部專屬目錄 (/data/data/packageName/) 渣玲;
- 外部專屬目錄 (/sdcard/Android/data/packageName/),
共享存儲(chǔ) (Shared Storage) : 存儲(chǔ)其他應(yīng)用可訪問文件抡四, 包含媒體文件柜蜈、文檔文件以及其他文件,對(duì)應(yīng)設(shè)備DCIM指巡、Pictures淑履、Alarms、Music藻雪、Notifications秘噪、Podcasts、Ringtones勉耀、Movies指煎、Download等目錄。
分區(qū)存儲(chǔ)在不同API上表現(xiàn)區(qū)別:
- 當(dāng)設(shè)置targetSdk<29時(shí)便斥,分區(qū)存儲(chǔ)不會(huì)開啟至壤;
- 當(dāng)設(shè)置targetsdk>=29時(shí),在android10機(jī)型上枢纠,谷歌新增
android:requestLegacyExternalStorage="true"
屬性可用于關(guān)閉分區(qū)存儲(chǔ)像街,不過此時(shí)在android11及以上機(jī)型上面,系統(tǒng)會(huì)忽略 requestLegacyExternalStorage 標(biāo)記,強(qiáng)制開啟分區(qū)存儲(chǔ)
當(dāng)targetSdk設(shè)置為>=29時(shí)镰绎,在android10上脓斩,在應(yīng)用非專有目錄上,比如mkdir畴栖,mkdirs随静,createNewFile等api都會(huì)受到影響,即使是在共享目錄DCIM吗讶,Pictures燎猛,Movies等下也無法使用這些api,必須使用MediaStore API創(chuàng)建或訪問关翎,但在android11及以上Google基于這些問題對(duì)分區(qū)存儲(chǔ)進(jìn)行了優(yōu)化扛门,這些api又可以正常使用了,Goole也已經(jīng)說明:如果您的應(yīng)用以 Android 10(API 級(jí)別 29)為目標(biāo)平臺(tái)纵寝,請(qǐng)停用分區(qū)存儲(chǔ)论寨,繼續(xù)使用適用于 Android 9 及更低版本的方法來執(zhí)行此操作。因此只要你的targetSdk一旦設(shè)置為29以上爽茴,務(wù)必添加android:requestLegacyExternalStorage="true"
屬性葬凳。讓android10及以下機(jī)型繼續(xù)使用舊存儲(chǔ)模型。
Android 10(Q) :
Android 10 中主要對(duì)共享目錄進(jìn)行了權(quán)限詳細(xì)的劃分室奏,不再能通過絕對(duì)路徑訪問火焰。
受影響的接口:
訪問不同分區(qū)的方式:
- 專屬目錄:和以前的版本一致,可通過 File() API 訪問胧沫,無需申請(qǐng)權(quán)限昌简。
- 共享目錄:需要通過MediaStore和Storage Access Framework API 訪問,視具體情況申請(qǐng)權(quán)限绒怨,下面詳細(xì)介紹纯赎。
其中,對(duì)共享目錄的權(quán)限進(jìn)行了細(xì)分:
無需申請(qǐng)權(quán)限的操作:
通過 MediaStore API對(duì)媒體集南蹂、文件集進(jìn)行媒體/文件的添加犬金、對(duì)自身APP 創(chuàng)建的 媒體/文件 進(jìn)行查詢、修改六剥、刪除的操作晚顷。
需要申請(qǐng)READ_EXTERNAL_STORAGE 權(quán)限:
通過 MediaStore API對(duì)所有的媒體集進(jìn)行查詢、修改疗疟、刪除的操作该默。
調(diào)用 Storage Access Framework API :
會(huì)啟動(dòng)系統(tǒng)的文件選擇器向用戶申請(qǐng)操作指定的文件
訪問方式:
Android 11 (R):
Android 11 (R) 在 Android 10 (Q) 中分區(qū)存儲(chǔ)的基礎(chǔ)上進(jìn)行了調(diào)整
- 使用直接文件路徑和原生庫訪問文件
為了幫助您的應(yīng)用更順暢地使用第三方媒體庫,Android 11 允許您使用除 MediaStore API 之外的 API 訪問共享存儲(chǔ)空間中的媒體文件策彤。不過权均,您也可以轉(zhuǎn)而選擇使用以下任一 API 直接訪問媒體文件:
File API顿膨。
原生庫锅锨,例如 fopen()叽赊。
簡單來說就是,可以通過 File() , mkDir() 等API 訪問有權(quán)限訪問的媒體集了必搞。