安卓碎片化的問題,由來已久,此次來看一下文件儲存碎片化的問題。到底要怎麼去正確選擇和管理文件存儲呢?java
Android手機一直以來被人詬病越用越卡,越用存儲空間越少,常常有要靠各類清理app清理垃圾,到最後不得對手機進行雙清,緣由除了硬件老化和Android的底層實現問題以外,開發者對文件管理的忽視製造出大量沒法清理的「垃圾」也是形成手機卡慢的緣由之一。android
Android的開放性給了開發者巨大的自由度,但自由不是讓咱們濫用權限和隨意開發的藉口,每個開發者都應該注重細節,連曾經一片混亂的第三方推送都開始統一整合規範化了,若是你還在隨意開發,不如如今開始,注重細節,提升用戶的Android手機體驗?api
總所周知,Android手機存儲分爲兩個部分:內部存儲和外部存儲,內部存儲通常是手機自帶的存儲空間,外部存儲指外插SD卡提供的存儲空間;隨着手機發展,這兩個存儲的定義又有了一些些變化,新的手機再也不有外插SD卡的概念,採起了內置閃存(eMMC、UFS等)的方式,因此內部存儲和外部存儲在新的Android手機上已經在同一個硬件上了。但爲了兼容舊設備和讓用戶獲得更好的體驗,咱們仍然須要管理好手機上內外存儲的使用。緩存
作過文件相關管理的同窗應該都曾經被android衆多的文件api搞得一片混亂過,如今來理一理.微信
我把應用操做的文件存儲位置分爲三個部分:app
咱們有兩種api去獲取這三個部分的存儲位置,它們分別歸屬於Context和Environment。工具
Context是應用的上下文,它用來獲取與應用相關的文件目錄,能夠獲取應用私有和應用公有目錄,經常使用的api有(後面是所對應的路徑):spa
1. Context#getCacheDir() /data/user/0/cn.appname.xxx/cache
2. Context#getDir("spanner",MODE_PRIVATE) /data/user/0/cn.appname.xxx/app_spanner
3. Context#getFileDir() /data/user/0/cn.appname.xxx/files
3. Context#getExternalCacheDir() /storage/emulated/0/Android/data/cn.appname.xxx/cache
4. Context#getExternalFilesDir(Environment.DIRECTORY_PICTURES) /storage/emulated/0/Android/data/cn.appname.xxx/files/Pictures
Context#getExternalFilesDir(null) /storage/emulated/0/Android/data/cn.appname.xxx/files
5. Context#getExternalMediaDirs() /storage/emulated/0/Android/media/cn.appname.xxx
複製代碼
前兩個是應用內部存儲私有目錄,後面4個都是應用外部存儲私有文件目錄。 注意:/data/user/0/ 等同於 /data/data/code
Environment和應用無關,它用於獲取公有存儲位置的文件目錄,經常使用的api有:cdn
1. Environment#getExternalStorageDirectory() /storage/emulated/0
2. Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) /storage/emulated/0/DCIM
Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) /storage/emulated/0/Pictures
3. Environment#getDataDirectory() /data
4. Environment#getDownloadCacheDirectory() /data/cache
5. Environment#getRootDirectory() /system
複製代碼
到底何時要用什麼api呢?
應用私有目錄由Context獲取控制,分爲內部存儲和外部存儲,內部存儲不須要申請文件讀寫權限也可以使用,外部存儲須要權限(getetExternalCacheDir() 和 getExternalFilesDir() 這兩個方法從4.4以後再也不須要讀寫權限)。用戶對app進行數據清理或卸載能夠清理外部存儲和內部存儲下的全部文件目錄。
內部存儲
內部存儲的文件夾其餘應用和用戶沒法直接訪問,能夠用於存放敏感數據。
getCacheDir()
getFileDir()
getDir(String name,int mode)
外部存儲
在Android Q以前其餘應用是能夠訪問修改外部存儲的應用私有目錄的,這個要注意。
使用外部存儲以前必定要檢查外部存儲是否可用,由於舊設備不必定會有外部存儲,新手機也不必定會給你讀寫權限,就算用戶不給你權限,你的app也要運行啊,否則就不用你的了。
public static boolean isSDCardEnable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
複製代碼
getExternalCacheDir()
getExternalFilesDir(String type)
getExternalMediaDirs()
獲取公有目錄要使用Environment的Api,它返回的目錄全都是共享的公有目錄。形成Android手機文件存儲混亂的罪魁禍首!爲數衆多的無責任開發者在這裏胡亂建立文件夾,亂起名、亂放文件,普通用戶根本沒法判斷哪些文件夾、文件是有用的,卸載app以後留下龐大的沒法清理的垃圾文件,致使手機空間不足。因而它們在Android Q被廢棄了,可是Q以前仍是能好好使用的,我認爲要開始減小使用它們,更多地使用Context下的私有目錄API。
getExternalStorageDirectory()
getExternalStoragePublicDirectory(String type)
使用頻率極高的api,返回在根目錄下的名爲type的文件夾,我把它分爲兩種用法:一種是傳入Environment的DIRECTORY常量再建立子目錄使用;一種是傳入appPackageName或者易被識別歸屬的名稱建立子目錄使用。前者會比較通用,內容能夠被各類工具app搜索發現(包括微信);後者算是私用,能夠存放不跟隨app生命的文件,即卸載後也能夠保留。
Environment.DIRECTORY_DCIM是手機的相冊,這個文件夾都是系統相關的app在用,存放相機拍攝的圖片,手機截圖之類的,不推薦開發者使用這個文件夾,避免混亂。值得一提的是淘寶有在使用這個文件夾,用於保存它的商品分享截圖,這個位置的確能夠避免被微信封殺~哈哈
Environment.DIRECTORY_PICTURES用於存放各類「正式的」圖片,強烈建議在這裏建立文件夾存放你想要被用戶發現的圖片,而且微信會掃描這個文件夾,讓你的圖片更容易分享。不過還。
Environment.DIRECTORY_DOWNLOADS能夠用於存放app更新的apk等下載資源。
其餘幾個比較少用就不介紹了。
上面提到Environment的兩個公有目錄經常使用API在Android Q被廢棄了,應用存儲功能沙箱化,文件存放到沙箱外面要使用 DocumentFile,共享媒體文件要使用MediaStore進行,詳細的適配已有其餘開發者分享出來了,推薦一下這篇:feng.moe/archives/47…
我很喜歡的承香墨影也出了篇適配指南,內容更加詳細:mp.weixin.qq.com/s/aiDMyAfAZ…
最後說一下幾個重要的事:
此次的分享到這裏,但願看完這篇文章以後可以讓你更瞭解如何管理手機文件夾。