瞭解 Android 應用的檔案儲存目錄,掌握持久化資料的正確姿勢

亦楓發表於2017-05-02

本文導讀:在安卓手機上,安裝或者解除安裝一個 App,會涉及到本地儲存系統的哪些目錄結構變化?作為開發人員,如何恰當地儲存應用相關的資訊?相關儲存目錄的生命週期、訪問方式和訪問許可權又是怎樣的呢?帶著這些問題,希望讀完這篇文章,你能夠有所收穫。

內部儲存空間中的應用私有目錄


對於裝置中每一個安裝的 App,系統都會在內部儲存空間的 data/data 目錄下以應用包名為名字自動建立與之對應的資料夾。這個資料夾用於 App 中的 WebView 快取頁面資訊,SharedPreferences 和 SQLiteDatabase 持久化應用相關資料等。

對於沒有 Root 過的手機,普通使用者是無法檢視 data/data 目錄內容的。不過開發人員可以使用模擬器除錯應用,並通過 DDMS(Dalvik Debug Monitor Server)提供的 File Explorer 工具檢視模擬器裝置的儲存空間。

瞭解 Android 應用的檔案儲存目錄,掌握持久化資料的正確姿勢

操作路徑:

第一步:Android Studio --> Tools --> Android --> Android Device Monitor;

第二步:Window --> Show View --> Android --> File Explorer。

Android SDK 提供有如下方法可以獲取並操作內部儲存空間下應用私有目錄檔案的方,都位於 Application Context 中,供開發者直接呼叫:

  • getFilesDir()

  • getCacheDir()

  • deleteFile()

  • 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亦楓

微信掃描二維碼,歡迎關注我的個人公眾號:安卓筆記俠

不僅分享我的原創技術文章,還有程式設計師的職場遐想

瞭解 Android 應用的檔案儲存目錄,掌握持久化資料的正確姿勢

相關文章