本文導讀:在安卓手機上,安裝或者卸載一個 App,會涉及到本地存儲系統的哪些目錄結構變化?做爲開發人員,如何恰當地存儲應用相關的信息?相關存儲目錄的生命週期、訪問方式和訪問權限又是怎樣的呢?帶着這些問題,但願讀完這篇文章,你可以有所收穫。javascript
對於設備中每個安裝的 App,系統都會在內部存儲空間的 data/data 目錄下以應用包名爲名字自動建立與之對應的文件夾。這個文件夾用於 App 中的 WebView 緩存頁面信息,SharedPreferences 和 SQLiteDatabase 持久化應用相關數據等。html
對於沒有 Root 過的手機,普通用戶是沒法查看 data/data 目錄內容的。不過開發人員可使用模擬器調試應用,並經過 DDMS(Dalvik Debug Monitor Server)提供的 File Explorer 工具查看模擬器設備的存儲空間。java
操做路徑:android
第一步:Android Studio --> Tools --> Android --> Android Device Monitor;程序員
第二步:Window --> Show View --> Android --> File Explorer。數據庫
Android SDK 提供有以下方法能夠獲取並操做內部存儲空間下應用私有目錄文件的方,都位於 Application Context 中,供開發者直接調用:瀏覽器
getFilesDir():緩存
getCacheDir():微信
deleteFile()app
fileList()
等等,也能夠經過 Environment 類訪問:
Environment.getDataDirectory();複製代碼
注意:當用戶卸載 App 時,系統自動刪除 data/data 目錄下對應包名的文件夾及其內容。
考慮內部存儲空間容量有限,普通用戶不能直接直觀地查看目錄文件等其餘緣由,Android 在外部存儲空間中也提供有特殊目錄供應用存放私有文件,文件路徑爲:
/storage/emulated/0/Android/data/app package name複製代碼
備註:通常設備都有內置 SD 卡,同時也提供外部 SD 卡拓展,可能對應路徑的目錄名有所差別。
值得注意的是,與內部存儲空間的應用私有目錄不一樣的是:
第一,默認狀況下,系統並不會自動建立外部存儲空間的應用私有目錄。只有在應用須要的時候,開發人員經過 SDK 提供的 API 建立該目錄文件夾和操做文件夾內容。
第二,自 Android 7.0 開始,系統對應用私有目錄的訪問權限進一步限制。其餘 App 沒法經過 file:// 這種形式的 Uri 直接讀寫該目錄下的文件內容,而是經過 FileProvider 訪問。(關於這個內容,接下來再寫一篇文章專門說說 7.0 的適配問題,歡迎關注個人微信公衆號:安卓筆記俠。)
第三,宿主 App 能夠直接讀寫內部存儲空間中的應用私有目錄;而在 4.4 版本開始,宿主 App 才能夠直接讀寫外部存儲空間中的應用私有目錄,使開發人員無需在 Manifest 文件中或者動態申請外部存儲空間的文件讀寫權限。
而相同點在於:同屬於應用私有目錄,當用戶卸載 App 時,系統也會自動刪除外部存儲空間下的對應 App 私有目錄文件夾及其內容。
一樣,Android SDK 中也提供有便捷的 API 供開發人員直接操做外部存儲空間下的應用私有目錄:
getExternalFilesDir()
getExternalCacheDir()
等等,固然,也能夠經過 Environment 類間接操做,只不過須要向用戶申請操做權限:
Environment.getExternalStorageDirectory();複製代碼
相似於 File 和 Cache 默認分類目錄,開發人員也能夠在應用私有目錄中建立屬於本身的自定義目錄,方便於分類存儲應用相關文件。
值得注意的一點是,對於外部存儲空間下的應用私有目錄文件,因爲普通用戶能夠自由修改和刪除,開發人員在使用時,必定要作好判空處理和異常捕獲,防止應用崩潰退出!
一般來講,應用涉及到的持久化數據分爲兩類:應用相關數據和應用無關數據。前者是指專供宿主 App 使用的數據信息,好比一些應用的配置信息,數據庫信息,緩存文件等。當應用被卸載,這些信息也應該被隨之刪除,避免存儲空間產生沒必要要的佔用。
相對而言,後者更偏向於這類信息:當應用被卸載,用戶仍然但願保留於設備當中的信息。常見如,拍照類應用的圖片文件,用戶是使用瀏覽器手動下載的文件等。
顯然,不管是內部存儲空間,仍是外部儲存空間,上述兩個應用私有目錄因爲其特有的生命週期(隨着應用卸載而自動清除)只適合存儲應用相關數據。
或者從訪問權限上來講,應用無關數據應該是宿主應用但願與其餘應用共享這些數據的,應該存放在外部存儲空間的公共目錄文件夾下。
外部存儲空間已經爲用戶默認分類出一些公共目錄。開發人員能夠經過 Environment 類提供的方法直接獲取相應目錄的絕對路徑,傳遞不一樣的 type 參數類型便可:
Environment.getExternalStoragePublicDirectory(String type);複製代碼
Envinonment 類提供諸多 type 參數的常量,好比:
DIRECTORY_MUSIC:Music
DIRECTORY_MOVIES:Movies
DIRECTORY_PICTURES:Pictures
DIRECTORY_DOWNLOADS:Download
等等,以第一個常量爲例,音樂類別的公共目錄絕對路徑爲:/storage/emulated/0/Music。若是你使用文件管理器打開設備的外部存儲空間的話,都可以看到這些公共目錄文件夾。
面對如此諸多的默認類別,開發人員在保存本身應用的公共文件時,也要養成良好的習慣,將要保存的數據分門別類地保存在不一樣公共目錄下。固然,你也能夠在公共目錄下再次建立屬於本身應用的目錄,便於管理。
注意:訪問外部存儲空間時記得申請讀寫權限!
通常來講,利用兩種應用私有目錄和公共目錄便可以存儲應用中須要保存的數據和文件。若是這些還不夠的話,那必定是你的開發姿式不對。在 Code Review 的前提下,若是仍是不夠的話,還能夠在外部存儲空間自由建立其餘目錄,經過這個方式獲取外部存儲空間的絕對路徑,而後操做文件:
Environment.getExternalStorageDirectory();複製代碼
使用應用私有目錄保存應用相關數據,使用公共目錄保存應用無關數據(共享數據)。不管哪一種狀況,都須要作好數據分類保存,便於清除等統一管理。隨便打開手機上的幾個應用,不難發現,不少應用都包含一個清理緩存的功能。事實上,開發人員清理的就是應用相關數據,也就是應用私有目錄下的文件。
考慮到外部存儲空間上的內容可能被用戶手動刪除,或者卸載拓展 SD 卡等不可控因素,操做前記得使用 Environment 類提供的 API 方法判斷容量是否充足、文件是否存在等狀況,作好異常捕獲,減小應用崩潰率。相信這必定是一個良好的習慣。
更多存儲選項和存儲框架,參考開發者官網:
關於我:亦楓,博客地址:yifeng.studio/,新浪微博:IT亦楓
微信掃描二維碼,歡迎關注個人我的公衆號:安卓筆記俠
不只分享個人原創技術文章,還有程序員的職場遐想