已知常用的5中存儲方式:
1.File I/O
2.SQLite
3.Preferences
4.Content provider
5.網絡存儲
本文介紹如何在您的應用中執行基本的檔案相關任務。
定您熟悉 Linux 檔案系統的基礎知識和 http://java.io 中的标準檔案輸入/輸出 API。
選擇内部或外部存儲所有 Android 裝置都有兩個檔案存儲區域:
内部和外部存儲。
這些名稱在 Android 早期産生,當時大多數裝置都提供内置的非易失性記憶體(内部存儲),
以及移動存儲媒體.
比如微型 SD 卡(外部存儲)。一些裝置将永久性存儲空間劃分為“内部”和“外部”分區,
即便沒有移動存儲媒體,也始終有兩個存儲空間,并且無論外部儲存設備是否可移動,
API 的行為均一緻。
以下清單彙總了關于各個存儲空間的實際資訊
内部存儲:
它始終可用。 隻有您的應用可以通路此處儲存的檔案。 當使用者解除安裝您的應用時,系統會從内部存儲中移除您的應用的所有檔案。
當您希望確定使用者或其他應用均無法通路您的檔案時,内部存儲是最佳選擇。
外部存儲:
它并非始終可用,因為使用者可采用 USB 儲存設備的形式裝載外部存儲,并在某些情況下會從裝置中将其移除。 它是全局可讀的,是以此處儲存的檔案可能不受您控制地被讀取。
當使用者解除安裝您的應用時,如果是您通過 getExternalFilesDir() api擷取的存儲路徑,并将您的應用的檔案儲存在目錄中時,
系統才會從此處移除您的應用的檔案。通過 getExternalStoragePublicDirectory() api擷取的存儲路徑,即使apk被移除後,檔案還會存儲在外部存儲中。對于無需通路限制以及您希望與其他應用共享或允許使用者使用計算機通路的檔案,外部存儲是最佳位置。
注:
在 Android N 之前,内部檔案可以通過放寬檔案系統權限讓其他應用通路。而如今不再是這種情況。
如果您希望讓其他應用通路私有檔案的内容,則您的應用可使用 FileProvider。
提示:
盡管應用預設安裝在内部存儲中,但您可在您的清單檔案中指定
android:installLocation
屬性,這樣您的應用便可安裝在在外部存儲中。
當 APK 非常大且它們的外部存儲空間大于内部存儲時,使用者更青睐這個選擇。 如需了解詳細資訊,請參閱應用安裝位置。
擷取外部存儲的權限
要向外部存儲寫入資訊,您必須在您的清單檔案中請求 WRITE_EXTERNAL_STORAGE 權限。
注意:
目前,所有應用都可以讀取外部存儲,而無需特别的權限。 但這在将來版本中會進行更改。如果您的應用需要讀取外部存儲(但不向其寫入資訊),那麼您将需要聲明 READ_EXTERNAL_STORAGE 權限。
要確定您的應用繼續正常工作,您應在更改生效前聲明此權限。将檔案儲存在内部存儲中在内部存儲中儲存檔案時,您可以通過調用以下兩種方法之一擷取作為 File 的相應目錄:
1.getFilesDir()
傳回表示您的應用的内部目錄的 File 。
2.getCacheDir()
傳回表示您的應用臨時緩存檔案的内部目錄的 File。
務必删除所有不再需要的檔案并對在指定時間您使用的記憶體量實作合理大小限制,比如,1MB。
如果在系統即将耗盡存儲,它會在不進行警告的情況下删除您的緩存檔案。要在這些目錄之一中建立檔案
1.
您可以使用 File() 構造函數,傳遞指定您的内部存儲目錄的上述方法之一所提供的 File。例如:File file = new File(context.getFilesDir(), filename);
2.
或者,您可以調用 openFileOutput() 擷取寫入到内部目錄中的檔案的 FileOutputStream。例如,下面顯示如何向檔案寫入一些文本:
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
3.或者,如果您需要緩存某些檔案,您應改用 createTempFile()。例如,以下方法從 URL 提取檔案名并正在您的應用的内部緩存目錄中以該名稱建立檔案:
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;
}
注:
您的應用的内部儲存設備目錄由您的應用在 Android 檔案系統特定位置中的軟體包名稱指定。
從技術上講,如果您将檔案模式設定為可讀,那麼,另一應用也可以讀取您的内部檔案。 但是,此應用也需要知道您的應用的軟體包名稱和檔案名。 其他應用無法浏覽您的内部目錄并且沒有讀寫權限,除非您明确将檔案設定為可讀或可寫。
隻要您為内部存儲上的檔案使用 MODE_PRIVATE,其他應用便從不會通路它們。将檔案儲存在外部存儲中由于外部存儲可能不可用
—比如,當使用者已将存儲裝載到電腦或已移除提供外部存儲的 SD 卡時—是以,在通路它之前,您應始終确認其容量。 您可以通過調用 getExternalStorageState() 查詢外部存儲狀态。 如果傳回的狀态為 MEDIA_MOUNTED,那麼您可以對您的檔案進行讀寫。 例如,以下方法對于确定存儲可用性非常有用:
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
盡管外部存儲可被使用者和其他應用進行修改,但您可在此處儲存兩類檔案:
公共檔案應供其他應用和使用者自由使用的檔案。 當使用者解除安裝您的應用時,使用者應仍可以使用這些檔案
例如,您的應用拍攝的照片或其他已下載下傳的檔案。私有檔案屬于您的應用且在使用者解除安裝您的應用時應予删除的檔案。 盡管這些檔案在技術上可被使用者和其他應用通路(因為它們存儲在外部存儲中), 但它們實際上不向您的應用之外的使用者提供任何輸出值。 當使用者解除安裝您的應用時,系統會删除應用外部私有目錄中的所有檔案。
例如,您的應用下載下傳的其他資源或臨時媒體檔案。
如果您要将公共檔案儲存在外部儲存設備上,請使用 getExternalStoragePublicDirectory() 方法擷取表示外部儲存設備上相應目錄的 File。 該方法使用指定您想要儲存以便它們可以與其他公共檔案在邏輯上組織在一起的檔案類型的參數,
比如 DIRECTORY_MUSIC 或 DIRECTORY_PICTURES。
例如:
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user’s public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, “Directory not created”);
}
return file; }
如果您要儲存您的應用專用檔案,您可以通過調用 getExternalFilesDir() 并向其傳遞訓示您想要的目錄類型的名稱,進而擷取相應的目錄。通過這種方法建立的各個目錄将添加至封裝您的應用的所有外部存儲檔案的父目錄,當使用者解除安裝您的應用時,系統會删除這些檔案。
例如,您可以使用以下方法來建立個人相冊的目錄:
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;
}
如果沒有适合您檔案的預定義子目錄名稱,您可以改為調用 getExternalFilesDir() 并傳遞 null。這将傳回外部存儲上您的應用的專用目錄的根目錄。切記,getExternalFilesDir() 在使用者解除安裝您的應用時删除的目錄内建立目錄。如果您正儲存的檔案應在使用者解除安裝您的應用後仍然可用—比如,當您的應用是照相機并且使用者要保留照片時—您應改用 getExternalStoragePublicDirectory()。
查詢可用空間
如果您事先知道您将儲存的資料量,您可以查出是否有足夠的可用空間,而無需調用 getFreeSpace() 或 getTotalSpace() 引起 IOException。這些方法分别提供目前的可用空間和存儲卷中的總空間。 此資訊也可用來避免填充存儲卷以緻超出特定門檻值。
但是,系統并不保證您可以寫入與 getFreeSpace() 訓示的一樣多的位元組。如果傳回的數字比您要儲存的資料大小大出幾 MB,或如果檔案系統所占空間不到 90%,則可安全繼續操作。否則,您可能不應寫入存儲。
注:
儲存您的檔案之前,您無需檢查可用空間量。 您可以嘗試立刻寫入檔案,然後在 IOException 出現時将其捕獲。 如果您不知道所需的确切空間量,您可能需要這樣做。 例如,如果在儲存檔案之前通過将 PNG 圖像轉換成 JPEG 更改了檔案的編碼,您事先将不知道檔案的大小。
删除檔案
您應始終删除不再需要的檔案。删除檔案最直接的方法是讓打開的檔案參考自行調用 delete()。
myFile.delete();
如果檔案儲存在内部存儲中,您還可以請求 Context 通過調用 deleteFile() 來定位和删除檔案:
myContext.deleteFile(fileName);
注:
當使用者解除安裝您的應用時,Android 系統會删除以下各項:您儲存在内部存儲中的所有檔案 您使用 getExternalFilesDir() 儲存在外部存儲中的所有檔案。
但是,您應手動删除使用 getCacheDir() 定期建立的所有緩存檔案并且定期删除不再需要的其他檔案。
總結:
android 存儲籠統的分為,内部存儲,外部存儲,内部存儲在android N 之後,為了安全考慮不對外開啟通路,如需進行通路,需要采用 FileProvider方式進行讀取。外部存儲分為可移動的和不可移動的。sd卡,usb裝置,或者機身記憶體32GB,16GB 等等,并且外部存儲根據是否通解除安裝apk時刻一同被移除,分為兩個位址存儲在不同位置,系統回有不同的行為,
擷取方式: