Android 存儲概覽
存儲區?
Android 一開始就將存儲區分為內部存儲和外部存儲,對應手機自帶的存儲和可插拔的 sd 卡(可類比于 PC 的硬盤和 U盤)。
內部存儲容量有限,Google 建議 App 數據盡量存儲于外部存儲中。
隨著硬件技術發展,自帶大容量空間的手機開始出現,關于內部存儲的描述逐漸偏離現實了,于是從 Android 4.4(API 19)開始,官方不再將機身存儲等同于內部存儲,而是從邏輯上將其一部分劃到外部存儲,限制剩下那部分的容量,也就是現在所謂的內部存儲。這一操作,使得原本內部存儲和外部存儲的特性和使用場景得以延續。
當然,如果在 4.4 系統及以上的手機上插了 sd 卡,那么 sd 卡也屬于外部存儲。
我們可以使用如下代碼打印出所有的外部存儲:
File[] files;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);
for(File file:files){
Log.e("main",file);
}
}
對于 4.4 以上的插了 sd 卡的大容量手機,應該會打印出如下信息:
/storage/emulated/0/Android/data/packname/files/mounted
/storage/B3E4-1711/Android/data/packname/files/mounted
文件
應用專屬文件
僅供應用使用的文件,可以存儲到內部存儲或外部存儲中的本應用專屬目錄,本應用訪問時不需要任何權限。在數據安全方面,雖然都是專屬目錄,但是內部存儲可以保證其它應用訪問不到,而外部存儲就比較復雜了。
在較低版本的 Android 系統中,只要聲明READ_EXTERNAL_STORAGE權限就能訪問位于外部存儲空間中應用專屬目錄之外的任何文件;只要聲明WRITE_EXTERNAL_STORAGE權限就能向應用專屬目錄以外的任何文件寫入數據。
這實在是相當危險,誰也不希望自家應用中的數據被抓取或篡改。于是從Android 10(API 29)開始有了分區存儲的概念,應用在默認情況下就能訪問外部存儲空間上自己的專屬目錄,以及本應用所創建的特定類型的媒體文件(使用MediaStore API,下面會講到)。如此,除非特殊情況,應用不再需要聲明上述權限了。
此時,如果應用在運行時請求與存儲相關的權限,將會彈出請求對話框(動態申請)表明應用正在請求對外部存儲空間的廣泛訪問權限。
Android 11(API 30)開始更進一步,干脆將 WRITE_EXTERNAL_STORAGE 權限的作用抹除(即使聲明了該權限也沒用)。這將應用的寫權限完全限制在了本應用相關目錄(專屬目錄和本應用創建的媒體文件)中。
ps:Android 11 引入了_MANAGE_EXTERNAL_STORAGE_權限,該權限替代 WRITE_EXTERNAL_STORAGE,提供對應用專屬目錄和 MediaStore 之外文件的寫入權限,但對使用的要求更嚴格。如需了解詳情,請參閱有管理存儲設備上所有文件。
共享文件
存儲您的應用打算與其它應用共享的文件,包括媒體(圖片、音頻文件、視頻)、其它類型文件。
媒體文件
使用 MediaStore API 訪問。注意:即使您的應用已卸載,作為共享文件(保存在媒體庫中)的媒體文件仍會保留在用戶的設備上。
除訪問自己的媒體文件外,訪問其它應用的媒體文件需要權限——在 Android 11(API 30)或更高版本中,需要 READ_EXTERNAL_STORAGE;在 Android 10(API 29)中,需要 READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE;在更低版本中,訪問所有文件均需要相關權限。——不過這也不是絕對的。
比如照片選擇器,它提供了一個可瀏覽界面,為用戶提供了一種安全的內置授權方式,讓用戶可以向應用授予限于所選圖片和視頻的訪問權限,而非整個媒體庫的訪問權限,該權限保留至設備重啟或應用停止運行。使用照片選擇器可以看作定制的動態申請權限的界面,至少從Android 13(API 32)開始,無需事先聲明 READ_EXTERNAL_STORAGE。
其它文件
自 Android 4.4(API 19)始,官方提供了存儲訪問框架,便于應用與外部存儲卷和云端存儲空間在內的文檔提供器互動。此框架支持用戶與系統選擇器互動,從而選擇文檔提供器以及供您的應用創建、打開或修改的特定文檔和其它文件。
同照片選擇器類似,由于用戶參與選擇您的應用可以訪問的文件或目錄,因此該機制無需任何系統權限,同時用戶控制和隱私保護也得到了增強。
這些文件存儲在應用專屬目錄和媒體庫之外,且在應用卸載后仍會保留在設備上。
使用存儲訪問框架涉及以下步驟:
- 應用調用包含存儲相關操作的 intent(
ACTION_CREATE_DOCUMENT保存文件;ACTION_OPEN_DOCUMENT打開文件;ACTION_OPEN_DOCUMENT_TREE授予應用對該目錄中所有文件和子目錄的訪問權限)。 - 用戶看到一個系統選擇器,供其瀏覽文檔提供器并選擇將執行存儲相關操作的位置或文檔。
- 應用獲得對代表用戶所選位置或文檔的 URI 的讀寫訪問權限。利用該 URI,應用可以在選擇的位置執行操作。
數據
應用配置項
不贅述,就是簡單的鍵值對。值得一提的是,之前都是使用SharedPreferences進行應用配置項的操作,現在官方建議使用Jetpack DataStore,允許您使用協議緩沖區存儲鍵值對或類型化對象。DataStore 基于Kotlin 協程和Kotlin.Flow以異步、一致的事務方式存儲數據。
數據庫
基于SQLite的數據存儲,一般選擇Jetpack.Room這個半 ORM 簡化數據 CRUD 操作。卸載應用時數據庫會跟著刪除。

浙公網安備 33010602011771號