編輯:關於android開發
Android使用的文件系統和其它平台的磁碟式文件系統很相似。這節課描述了如何通過FileAPI在Android文件系統上進行讀取文件和寫入文件的操作。
一個File對象適合被用來按照從頭到尾的方式讀取或寫入大量的數據,它不適合被用來跳躍式訪問,也就是隨機訪問。舉個例子,這對圖片文件或者任何基於網絡的數據交換是非常適合的。
這節課展示了如何執行APP中最基本的文件相關任務。這節課假定你有Linux的文件系統基礎以及Java標准的輸入輸出基礎。
所有的Android設備有兩個文件存儲分區:”internal”和”external”分區。這些名詞來自於較早的Android版本,當大多數的設備提供了內置的固定內存,會添加一個可移除的存儲器媒體比如micro SD卡(外部存儲器)。一些設備固定的存儲器空間劃分為”internal”和”external”分區,所以甚至是沒有可移除的存儲媒體,那麼仍然還是會有兩個存儲器空間。API會表現出相同的行為,無論外部存儲器是不是可移除的。下面是對每個存儲器空間的事實總結。
Internal storage:
它總是可用的。 默認情況下APP將文件保存在這裡,只允許該APP可以訪問。 如果用戶卸載了你的APP,那麼系統會將APP的所有文件從這裡移除。如果你不想讓用戶或者其它APP訪問你文件的話,內部存儲器是一個合適的地方。
External storage:
它並不總是可用的,因為用戶可能將外部存儲掛載為USB存儲器,和另外一些可能會被從設備上移除的情況。 它是全局可訪問的,所以如果文件存儲在這裡,它可能會你的控制范圍之外被訪問。 當用戶卸載了你的APP,系統只會刪除你在getExternalFilesDir()返回目錄中保存的文件。如果不需要訪問限制的話,外部存儲器是一個合適的地方,它可以另其它的APP訪問你的文件,用戶也可以通過電腦訪問這些文件。
Note:盡管APP安裝的時候會默認被安裝在內部存儲器內,不過你可以在清單文件中通過指定android:installLocation屬性來指定應用安裝的位置。如果APK的尺寸很大,並且外部存儲空間比內部存儲空間大的話,用戶會很欣賞這點。更多相關信息,請參見: App Install Location。
如果要在外部存儲器寫入文件,你必須在清單文件中請求WRITE_EXTERNAL_STORAGE權限。
...
警告:目前所有的APP都有能力訪問外部存儲器而不需要指定權限。然而,這會在未來的發行版做更改。如果你的APP需要讀取外部存儲器的數據(不是寫入),那麼你需要聲明READ_EXTERNAL_STORAGE權限,來確保你的APP還可以在未來的版本中繼續工作,在更改生效之前,你應該現在就聲明這項權限。
android:name="android.permission.READ_EXTERNAL_STORAGE" /> ... 然而,如果你的APP使用了WRITE_EXTERNAL_STORAGE權限,那麼它會隱性的含有讀取外部存儲器的權限。
你在內部存儲器中保存文件不要任何權限。你的應用程序總是有權讀取和寫入文件到內部存儲器目錄。
當要保存文件到內部存儲器時,你可以通過下面兩個方法中的一個獲得一個合適的目錄對象File:
getFilesDir() 返回一個代表APP的內部存儲器目錄的File對象。
getCacheDir() 返回一個File對象,這個對象代表了APP在內部存儲器中的臨時文件緩存目錄。為了確保文件不再需要的時候可以刪除到它,應該在任何給定時間內對內存的數量實現一個合理的尺寸限制,比如1MB。如果系統開始在存儲器上緩慢運行,那麼可能會刪除你的臨時文件,而不會有任何警告。
為了在這些目錄中創建一個文件,你可以使用File()的構造方法,傳遞一個上面的方法目錄到File的構造方法中,來指定內部存儲器目錄。就像這樣:
File file = new File(context.getFilesDir(), filename);
或者,你可以調用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();
}
又或者,如果你需要緩存一些文件,你應該使用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;
}
**Note:**APP的內部存儲路徑是通過APP的包名特別指定的,並且被放置在Android文件系統中一個特殊的位置。技術上講,其它的APP是可以讀取你的內部文件的,如果你設置的文件模式是可讀的。然而,其它的APP也應該知道你APP的包名和文件名。其它的APP不能浏覽你的內部目錄,並且沒有訪問和寫入的權限,除非你特別設置了文件是和讀寫的。所以,一旦你對內部存儲器文件使用了MODE_PRIVATE模式,那麼其它APP永遠不可能訪問到這些文件。
因為外部存儲器有可能是不可用的,比如當用戶將它掛載到了PC上,或者將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;
}
盡管外部存儲器是可以被用戶或者其它APP修改的,這裡有兩種你可能會用到的文件保存類別。
Public文件:
在這種情況下,文件應該會被其它APP或者用戶隨便訪問。當用戶卸載了你的APP,那麼這些文件還會保留給用戶。
舉個例子,APP捕獲的照片或者下載的其它文件。
Private文件:
這些文件會正當的屬於你的APP,並且在用戶卸載APP的時候會刪除它們。盡管這些文件從技術上講是可以被用戶或者其它APP訪問的,因為這些文件是在外部存儲器上。實際上這些文件不會提供給APP之外的用戶。當用戶卸載了APP,那麼系統會將這些文件從外部存儲器中刪除。
舉個例子,APP下載的附加資源或者臨時的媒體文件。
如果你想在外部存儲器上保存公開的文件,使用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()方法獲取合適的目錄,然後給它傳你喜歡的一個類型的目錄名稱。每一個目錄會通過這種方式創建並被添加到父目錄中,以便封裝所有在外部存儲器上的文件,當用戶卸載APP的時候會刪除它們。
下面這個方法你可使用它創建一個個人的相冊目錄:
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,這會返回APP在外部存儲器上私有目錄的根目錄。
記住在getExternalFilesDir()目錄中創建的目錄會隨著APP的卸載被刪除。如果你想在刪除之後仍然保留這些文件,比如你的APP是個攝像機應用,用戶希望保留下來這些照片,你應該使用getExternalStoragePublicDirectory()方法。
無論你使用的是getExternalStoragePublicDirectory()要共享文件還是使用getExternalFilesDir()保護你APP內的文件,你使用API提供的常量比如DIRECTORY_PICTURES作為目錄的名稱來說是非常重要的。這些目錄的名稱可以為系統合適的對待,舉個例子,如果文件存儲在DIRECTORY_RINGTONES的目錄中,系統媒體掃描器會將它識別為鈴聲文件,而不是音樂文件。
如果你可以提前知道你保存的數據有多少,你可以查詢是否有足夠的空間可以使用,通過調用getFreeSpace()或者getTotalSpace()達到這一點。這些方法分別提供了當前可用空間和磁盤容量上的總空間,這些信息有助於避免填充的磁盤容量超過固定的阈值。
然而,系統不會保證你可以寫入與getFreeSpace()返回的剩余空間容量相當的數據。如果返回的數字是幾MB,大於你想存儲的數據大小,又或者系統當前使用容量少於總容量的90%,那麼現在處理可能是安全的。否則,你可能不適合寫入到存儲器中。
Note:如果你在保存文件之前不檢查剩余可用空間,你可以試著以正確的方式寫入文件,如果事件發生了,那麼可能會引起IOException異常。如果你不知道你需要的精確空間,那麼你可能就需要這麼去做。舉個例子,如果你在存儲文件之前從PNG編碼改為了JPEG編碼,你可能就不會提前知道文件的大小。
你應該在文件不再需要的時候將它們刪除。最直接了當的方式就是擁有一個已經打開了的文件的引用,然後調用它的delete()方法。
myFile.delete();
如果文件被存在了內部存儲器上,你也可以要求Context定位,然後調用deleteFile()方法刪除文件。
myContext.deleteFile(fileName);
Note:當用戶卸載了你的APP,Android系統會刪除以下文件:
所有保存在內部存儲器中的文件
所有保存getExternalFilesDir()目錄下的外部存儲器中的文件
無論如何,你應該定期手動刪除所有的緩存文件,即便是通過getCacheDir()方法創建的,還應該定期刪除你不再需要的其它文件。
用Kotlin實現Android定制視圖(KAD 06),kotlinandroid作者:Antonio Leiva 時間:Dec 27, 2016 原文鏈接:https
將學校擺在桌面上-實時更新校內數據的Android桌面部件,校內android項目地址: https://github.com/hwding/AeolosXDUWidge
基於PinnedSectionListView實現聯系人通訊錄並且點擊打電話,手機通訊錄聯系人恢復PinnedSectionListView具體下載地址、使用方法和注意事
安卓第十五天筆記-圖形圖像一些簡單處理,安卓第圖形圖像安卓第十五天筆記-圖形圖像一些簡單處理 多媒體編程簡介--圖形的一般處理 1.計算機中圖形計算的大小 一般白色就是0