摘要
Android 使用 VFS (Virtual File System) 虛擬文件系統(tǒng)鱼响。VFS提供了供存儲(chǔ)設(shè)備掛載的節(jié)點(diǎn)鸣剪,同一存儲(chǔ)設(shè)備經(jīng)過(guò)分區(qū)后,不同的分區(qū)可以掛載到不同的節(jié)點(diǎn)上丈积,如手機(jī)的內(nèi)置存儲(chǔ)卡筐骇。
關(guān)鍵字
內(nèi)置存儲(chǔ)卡 / 外置SD卡
內(nèi)部存儲(chǔ) / 外部存儲(chǔ)
目錄結(jié)構(gòu)
VFS 的目錄以 /
為根節(jié)點(diǎn),根節(jié)點(diǎn)下面又有不同的節(jié)點(diǎn)江滨。物理存儲(chǔ)設(shè)備就是掛載到這些節(jié)點(diǎn)上铛纬。
-
/data/data
該節(jié)點(diǎn)是用戶應(yīng)用的安裝目錄,如百度地圖的安裝路徑是 /data/data/com.baidu.com唬滑,該目錄需要root權(quán)限 -
/system
該節(jié)點(diǎn)是系統(tǒng)應(yīng)用的安裝目錄 -
/storage
該節(jié)點(diǎn)是內(nèi)置存儲(chǔ)卡和外置SD卡的掛載點(diǎn)
外置SD卡掛載節(jié)點(diǎn):/storage/sdcard1
內(nèi)置存儲(chǔ)卡掛載節(jié)點(diǎn):/storage/emulated/0
不同的設(shè)備掛載節(jié)點(diǎn)不同告唆,有的可能在 /mnt下
內(nèi)部存儲(chǔ)和外部存儲(chǔ)
內(nèi)部存儲(chǔ)卡/外置SD卡
≠ 內(nèi)部存儲(chǔ)/外部存儲(chǔ)
首先明確,內(nèi)置存儲(chǔ)卡/外置SD卡 是在物理層面相對(duì)于手機(jī)大眾用戶來(lái)說(shuō)的晶密。
外置SD卡:可手動(dòng)插拔的SD卡擒悬。
內(nèi)置存儲(chǔ)卡:焊接在手機(jī)內(nèi)部不可拆卸的存儲(chǔ)卡。
而稻艰,內(nèi)部存 /外部存儲(chǔ) 是在文件系統(tǒng)邏輯層面相對(duì)于開發(fā)者來(lái)說(shuō)的懂牧,指具體的路徑。
一般針對(duì)某個(gè)應(yīng)用而言的尊勿,屬于該應(yīng)用的存儲(chǔ)路徑叫內(nèi)部存儲(chǔ)僧凤,反之為外部存儲(chǔ)。
內(nèi)部存儲(chǔ)
路徑:/data/data/package_name
/data/data/
下都是已安裝應(yīng)用的目錄元扔,該目錄下包含的文件都是以包名作為文件名的目錄躯保,例如/data/data/com.sankuai.meituan
- 內(nèi)部存儲(chǔ)的文件是應(yīng)用的私有文件,其他應(yīng)用不能訪問(wèn)澎语。
- 應(yīng)用訪問(wèn)自己的內(nèi)部存儲(chǔ)不需要權(quán)限途事,訪問(wèn)外部存儲(chǔ)需要申請(qǐng)權(quán)限。
- 應(yīng)用卸載后咏连,這些文件也會(huì)被移除盯孙。
獲取內(nèi)部存儲(chǔ)的方式如下:
Context
File getDir(String name, String mode) ;
// /data/data/com.sankuai.meituan
File getFilesDir();
// /data/data/com.sankuai.meituan/files
File getCacheDir()
// /data/data/com.sankuai.meituan/cache
String getApplicationInfo().dataDir;
// /data/data/com.sankuai.meituan
其中,參數(shù) mode
指創(chuàng)建模式祟滴,一種 4 種
-
MODE_PRIVATE
振惰,設(shè)為私有文件 -
MODE_APPEND
,openFileOutput垄懂,文件存在則追加內(nèi)容 -
MODE_WORLD_READABLE
骑晶,API 17 廢棄 -
MODE_WORLD_WRITEABLE
痛垛,API 17 廢棄
注意: Android 7.0 以上android.os.Build.VERSION.SDK_INT>=Build.VERSION_CODES.N
使用3/4 常量時(shí),將會(huì)導(dǎo)致SecurityException桶蛔,這意味著不能通過(guò)名稱共享私有文件匙头。
嘗試共享 file://URI
URI將會(huì)導(dǎo)致FileUriExposedException,StrictMode API政策禁止在您的應(yīng)用外部公開file://URL仔雷。如果您的應(yīng)用需要與其他應(yīng)用共享私有文件蹂析,則可以使用 FileProvider 與 FLAG_GRANT_READ_URI_PERMISSION 配合使用。Android 7.0 行為變更 通過(guò)FileProvider在應(yīng)用間共享文件吧
外部存儲(chǔ)
外部存儲(chǔ)碟婆,可以是 外置SD卡 或 內(nèi)置存儲(chǔ)卡的部分分區(qū)电抚。
外部存儲(chǔ),分為 公共目錄 和 私有目錄
版本 | 存儲(chǔ)位置 | 是否需要讀寫權(quán)限 |
---|---|---|
Android 4.4以前 | 外部存儲(chǔ)(公共目錄和私有目錄) | 需要 |
Android 4.4以后 | 外部存儲(chǔ)(公共目錄) | 需要 |
Android 4.4以后 | 外部存儲(chǔ)(私有目錄) | 不需要 |
外部存儲(chǔ) - 私有目錄
- 屬于應(yīng)用私有竖共,但是這些私有數(shù)據(jù)可以被其他應(yīng)用訪問(wèn)和修改(通過(guò)私有目錄的地址)
- 應(yīng)用卸載時(shí)蝙叛,此目錄及其內(nèi)容將被刪除。
- 系統(tǒng)媒體掃描程序不會(huì)讀取這些目錄的文件公给,因此不能從MediaStore內(nèi)容提供程序訪問(wèn)這些文件
獲取方式
Context
File getExternalCacheDir()
// /storage/emulated/0/Android/data/com.sankuai.meituan/cache
File getExternalFilesDir(String type)
// /storage/emulated/0/Android/data/com.sankuai.meituan/files
外部存儲(chǔ)注意事項(xiàng)
- 使用前先檢查文件狀態(tài)
外部存儲(chǔ)的文件借帘,所有的應(yīng)用和用戶都能移除和修改這些權(quán)限。
在使用外部存儲(chǔ)執(zhí)行工作之前淌铐,應(yīng)該使用 getExternalStorageState() 檢查介質(zhì)是否可用肺然,介質(zhì)可能已經(jīng)裝載到設(shè)備,處于缺失腿准、只讀或其他某種狀態(tài)狰挡。
檢查可用性的方法:
String status = Environment.getExternalStorageState();
boolean mounted = status.equals(Environment.MEDIA_MOUNTED)
|| status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
return mounted;
- 對(duì)于支持外插SD卡的設(shè)備,外部存儲(chǔ)包括兩部分:內(nèi)置存儲(chǔ)卡和外置SD卡释涛;
Android 4.3 以下,只能通過(guò)Context#getExternalFilesDir(type)
來(lái)獲取外部存儲(chǔ)在內(nèi)置存儲(chǔ)卡分區(qū)的私有目錄倦沧,無(wú)法獲取外置SD卡唇撬。
Android 4.3 開始,可以通過(guò)Context#getExternalFilesDirs(type)
獲取一個(gè)File數(shù)組展融,包含了內(nèi)置存儲(chǔ)卡分區(qū)和外置SD的私有目錄地址窖认。
可以使用兼容庫(kù)的靜態(tài)方法 ContextCompate.getExternalFilesDirs() 兼容 4.3。
總結(jié)
- 應(yīng)用使用內(nèi)部存儲(chǔ)不需要權(quán)限告希,內(nèi)部存儲(chǔ)屬于應(yīng)用的私有存儲(chǔ)區(qū)域扑浸,其他應(yīng)用不可訪問(wèn),但應(yīng)用卸載燕偶,內(nèi)部存儲(chǔ)中對(duì)應(yīng)的文件也會(huì)刪除喝噪。
- 外部存儲(chǔ)分為公共目錄和私有目錄,外部存儲(chǔ)是可以全局訪問(wèn)的指么,但需要申請(qǐng)讀寫權(quán)限酝惧。Android4.4以后私有目錄不需要申請(qǐng)讀寫權(quán)限榴鼎。
- 如果緩存的數(shù)據(jù)量較大,請(qǐng)不要保存到內(nèi)部存儲(chǔ)中晚唇。
- 如果想保存可共享給其他應(yīng)用的數(shù)據(jù)巫财,請(qǐng)保存到外部存儲(chǔ)的公共目錄中。
- clear data 和 clear cache 兩個(gè)都是應(yīng)用的緩存數(shù)據(jù)哩陕,清理的是外部存儲(chǔ)中的私有目錄下的files/cache平项,即 /storage/emulated/0/Android/data/com.sankuai.meituan/cache