內(nèi)部或外部存儲
internal
和external
存儲的名字來源于早期的Android設備,它提供了內(nèi)置的非易失性內(nèi)存(內(nèi)部存儲),加上一個可移動的存儲介質(zhì),比如 SD 卡(外部存儲)
而現(xiàn)在為了兼容性,直接將存儲空間劃分為“內(nèi)部”和“外部”分區(qū),即沒有移動存儲介質(zhì),但同樣有兩個存儲空間,對于API來說,不管外部存儲是否是可以移動的,其執(zhí)行效果是相同的
內(nèi)部存儲:
- 它始終可用
- 只有應用可以訪問此處保存的文件
- 當用戶卸載應用時,系統(tǒng)會從內(nèi)部存儲中移除應用的所有文件。
當希望確保用戶或其他應用均無法訪問對應的文件時,內(nèi)部存儲是最佳選擇。
外部存儲:
- 并非始終可用,因為用戶可采用 USB 存儲設備的形式裝載外部存儲,并在某些情況下會從設備中將其移除。
- 它是全局可讀的,因此此處保存的文件可能不受控制地被讀取。
- 當用戶卸載應用時,只會移除通過
getExternalFilesDir()
獲取到的目錄下的文件
對于無需訪問限制以及希望與其他應用共享或允許用戶使用計算機訪問的文件,外部存儲是最佳位置。
權限
應用始終具有在其內(nèi)部存儲目錄中進行讀寫的權限
要向外部存儲寫入信息,必須在清單文件中請求WRITE_EXTERNAL_STORAGE
權限。
從 Android 4.4 (API level 19)開始,外部存儲設備上的私有文件,無需 WRITE_EXTERNAL_STORAGE
權限(即讀寫通過getExternalFilesDir(String)
和getExternalCacheDir()
獲取的目錄下對應的文件)
例如, 應用 com.example.foo
可以自由訪問外部存儲上的 Android/data/com.example.foo/
。
Android 6.0以后,需要運行時請求寫外部存儲的權限
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
文件保存到內(nèi)部存儲中
getFilesDir()
返回文件系統(tǒng)的絕對路徑,與通過openFileOutput(String, int)
創(chuàng)建文件的存儲位置一致
getCacheDir()
設備的內(nèi)部存儲空間不足時,Android 可能會刪除這些緩存文件以回收空間。 但不應該依賴系統(tǒng)來清理這些文件, 而應該始終自行維護緩存文件,使其占用的空間保持在合理的限制范圍內(nèi)(例如 1 MB)。 當用戶卸載您的應用時,這些文件也會被移除
創(chuàng)建緩存文件:
public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
} catch (IOException e) {
// Error while creating file
}
return file;
}
保存在外部存儲
公有文件
供其他應用和用戶自由使用的文件。 當用戶卸載您的應用時,用戶應仍可以使用這些文件,例如Download,Music,Pictures等
通過方法
getExternalStoragePublicDirectory()
//向其傳遞需要的目錄類型,例如 DIRECTORY_MUSIC、DIRECTORY_PICTURES、 DIRECTORY_RINGTONES
public File getAlbumStorageDir(String albumName) {
// 獲取公有的照片目錄
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
私有文件
屬于應用且在用戶卸載用時會刪除的文件。
例如,應用下載的其他資源或臨時介質(zhì)文件。
getExternalFilesDir(String type)
//使用外部存儲上的私有存儲目錄,type 參數(shù)指定子目錄的類型(例如 DIRECTORY_MOVIES),null會獲得私有目錄的根目錄。
getExternalCacheDir(String type)
//緩存文件保存到的外部存儲目錄,用戶卸載應用,文件也會被自動刪除
type參數(shù)的指定子目錄類型
//創(chuàng)建個人相冊的目錄
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
查詢外部存儲狀態(tài),是否可以讀寫或只能讀
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
刪除文件
myFile.delete();//文件自行刪除
myContext.deleteFile(fileName);//刪除內(nèi)部存儲對應的文件
Environment.getExternalStorageDirectory().getAbsolutePath()
Cursor cursor = MediaStore.Images.Media.query(
context.getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, STORE_IMAGES);
在 Android N 之前,內(nèi)部文件可以通過放寬文件系統(tǒng)權限讓其他應用訪問。而如今不再是這種情況。如果您希望讓其他應用訪問私有文件的內(nèi)容,則您的應用可使用FileProvider
使用作用域目錄訪問
在 Android 7.0 或更高版本中,如果您需要訪問外部存儲上的特定目錄,請使用作用域目錄訪問。 作用域目錄訪問可簡化您的應用訪問標準外部存儲目錄(例如 Pictures 目錄)的方式,并提供簡單的權限 UI,清楚地詳細介紹應用正在請求訪問的目錄。 有關作用域目錄訪問的更多詳情,請參閱使用作用域目錄訪問
data/app
data/data/<package-name>/
1.data/data/包名/shared_prefs
2.data/data/包名/databases
3.data/data/包名/files
4.data/data/包名/cache
一般來說,在storage文件夾中有一個sdcard文件夾,這個文件夾中的文件又分為兩類,一類是公有目錄,還有一類是私有目錄,其中的公有目錄有九大類,比如DCIM、DOWNLOAD等這種系統(tǒng)為我們創(chuàng)建的文件夾,私有目錄就是Android這個文件夾,這個文件夾打開之后里邊有一個data文件夾,打開這個data文件夾,里邊有許多包名組成的文件夾。
MOVIE PICTURE DCMI DOWNLOAD
/sdcard/Android/data/<package-name>/files
getExternalFileDir
/sdcard/Android/data/<package-name>/cache
getExternalCacheDir