Android應用開發中,常使用Environment類去獲取外部存儲目錄,在訪問外部存儲之前一定要先判斷外部存儲是否已經是可使用(已掛載&可使用)狀態,
並且需要在AndroidManifest.xml文件中添加外部存儲讀和寫的權限。
Environment類中提供了幾個靜態常量用於標識外部存儲的狀態,這些狀態都是String類型直接使用equals()判斷即可!
SD狀態 |
現象描述
|
/mnt/sdcard目錄是否存在
|
canRead返回
|
canWrite返回
|
在/mnt/sdcard創建文件
|
在/mnt/sdcard創建文件夾
|
|
MEDIA_MOUNTED
|
SD卡正常掛載
|
TRUE
|
TRUE
|
TRUE
|
TRUE
|
TRUE
|
|
MEDIA_REMOVED
|
無介質
|
TRUE
|
FALSE
|
FALSE
|
false: 原因Permission denied
|
FALSE
|
|
MEDIA_UNMOUNTED
|
有介質,未掛載,在系統中刪除
|
TRUE
|
FALSE
|
FALSE
|
false: 原因Permission denied
|
FALSE
|
|
MEDIA_BAD_REMOVAL
|
介質在掛載前被移除,直接取出SD卡
|
TRUE
|
FALSE
|
FALSE
|
false: 原因Permission denied
|
FALSE
|
|
MEDIA_CHECKING
|
正在磁盤檢查,剛裝上SD卡時
|
TRUE
|
FALSE
|
FALSE
|
false: 原因Permission denied
|
FALSE
|
|
MEDIA_SHARED
|
SD卡存在但沒有掛載,並且通過USB大容量存儲共享,操作打開USB存儲
|
TRUE
|
FALSE
|
FALSE
|
false: 原因Permission denied
|
FALSE
|
|
MEDIA_MOUNTED_READ_ONLY
|
sd卡存在並且已掛載,但是掛載方式為只讀
|
-
|
-
|
無法模擬,SD卡不允許修改權限
|
|||
MEDIA_NOFS |
介質存在但是為空白或用在不支持的文件系統
|
-
|
-
|
無法模擬,SD卡格式化后再加載會自動生成系統文件
|
|||
MEDIA_UNMOUNTABLE |
存在SD卡但是不能掛載,例如發生在介質損壞
|
-
|
-
|
無法模擬 |
通過上表可以看出,只有在SD卡狀態為MEDIA_MOUNTED時/mnt/sdcard目錄才是可讀可寫,並且可以創建目錄及文件。
所以我們讀取SD卡時一般會這么寫:只有滿足條件時:才在if與具體里面執行特定的邏輯:比如下載圖片到SD卡:
1 String state; 2 String path; 3 state = Environment.getExternalStorageState(); 4 if(state.equals(Environment.MEDIA_MOUNTED)){ 5 path =Environment.getExternalStorageDirectory().getAbsolutePath(); 6 }
下面是Android重的一段代碼。主要是示例Environment檢測sdcard狀態的應用!
1 // 使用http協議下載圖片 2 HttpClient httpClient = new DefaultHttpClient(); 3 HttpPost httpPost = new HttpPost(path); 4 HttpResponse response = null; 5 // 獲取SDcard的目錄 6 File file = Environment.getExternalStorageDirectory(); 7 FileOutputStream outputStream = null; // 這是方便在后面關閉IO流 8 try { 9 response = httpClient.execute(httpPost); 10 if (response.getStatusLine().getStatusCode() == 200) { 11 // 將獲得的資源放入字節數組中 12 byte[] result = EntityUtils.toByteArray(response.getEntity()); 13 // 將數據寫入到SD卡上面的指定名字的文件里面,首先創建一個文件 14 // 同時需要判斷如果SD卡是在掛載的狀態嗎,那么OK可以寫了 15 if (Environment.getExternalStorageState().equals( 16 Environment.MEDIA_MOUNTED)) { 17 18 } 19 File new_file = new File(file, "x.jpg"); 20 outputStream = new FileOutputStream(new_file); 21 outputStream.write(result, 0, result.length); 22 } 23 24 } catch (Exception e) { 25 // TODO: handle exception 26 e.printStackTrace(); 27 } finally { 28 try { 29 outputStream.close(); 30 } catch (IOException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 } 35
1 //這兩個配置文件中的狀態是不可少的,要向支持連接網絡還需要網絡允許 2 <uses-permission Android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 3 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 4 <uses-permission android:name="android.permission.INTERNET"/>
在Environment中還提供了Android標准目錄的路徑,以String類型提供。
DIRECTORY_ALARMS 系統提醒鈴聲存放的標准目錄。
DIRECTORY_DCIM 相機拍攝照片和視頻的標准目錄。
DIRECTORY_DOWNLOADS 下載的標准目錄。
DIRECTORY_MOVIES 電影存放的標准目錄。
DIRECTORY_MUSIC 音樂存放的標准目錄。
DIRECTORY_NOTIFICATIONS 系統通知鈴聲存放的標准目錄。
DIRECTORY_PICTURES 圖片存放的標准目錄
DIRECTORY_PODCASTS 系統廣播存放的標准目錄。
DIRECTORY_RINGTONES 系統鈴聲存放的標准目錄。
static File getDataDirectory() 獲得data的目錄(/data)。
static File getDownloadCacheDirectory() 獲得下載緩存目錄。(/cache)
static File getExternalStorageDirectory() 獲得外部存儲媒體目錄。(/mnt/sdcard or /storage/sdcard0)
static File getRootDirectory() 獲得系統主目錄(/system)
除了用Environment獲取存儲目錄之外,還可以通過把路徑寫死的方式,比如要讀取外部存儲/mnt/sdcard目錄下的文件,可以在程序中直接用全路徑,
但是這樣做是很不好的,應該Android實在是太開放了,外部存儲的目錄的什么還是要固件制作商才知道,但是有一點是毋庸置疑的,就是Android框架層里面
已經是指定好了Environment.getDownloadCacheDirectory()的返回路徑。所以,盡量用這種方式來獲取和存儲數據,以免固件廠商不同而造成路徑的差異。
Android的實際開發中還用了兩個非常重要的緩存目錄,一個是應用程序自己的緩存空間,另一個是外部存儲為該應該程序提供的緩存空間。有什么差別?
使用過LruCache和DisLruCache的童鞋應該知道。
這兩個方法是通過上下文對象Context獲取的,只要應用程序被卸載,這兩個目錄下的文件都要被清空。
context.getCacheDir() 獲取應用程序自己的緩存目錄
context.getExternalCacheDir() 獲取應用程序在外部存儲的存儲目錄
參考了:http://blog.csdn.net/yuzhiboyi/article/details/8645730
http://www.kuqin.com/shuoit/20141130/343550.html