我有一臺中興的Android手機,型號是 ZTE U930HD,手機沒有插入外置SD卡(也就是Micro SD Card,原名Trans-flash Card(TF卡),2004年正式改名爲Micro SD Card),可是機身自帶了一個內置存儲卡(也就是eMMC存儲,大小爲2G)。
我把這個手機用數據線插到電腦上,也會看到盤符,經過安裝「R.E 管理器」等文件管理應用,也能夠管理文件,而且能看到該存儲的掛載目錄是:/mnt/sdcard2
可是,
我打印 Environment.getExternalStorageState(),卻返回 」removed「;
這是怎麼回事?明明手機自己帶着內置SD卡,卻爲什麼提示這麼一個信息?
我又試着去打印了Environment.getExternalStorageDirectory(),返回:「/mnt/sdcard」
看起來能夠解釋了,在我這個中興手機上,調用Environment.getExternalStorageDirectory(),返回的存儲目錄並非系統內置的SD卡目錄。
我又換了一個 Sony L39u,一個 MOTO G,調用Environment.getExternalStorageDirectory()返回的目錄就是系統內置的SD卡目錄。
不一樣的設備上,調用getExternalStorageDirectory()返回值卻不同。查詢了Android的文檔,才找到緣由,原來這個方法返回的是當前設備廠商所認爲的「外部存儲」,有可能返回外置的SD卡目錄(Micro SD Card),也可能返回內置的存儲目(eMMC)。
總結一下:
一部分手機將eMMC存儲掛載到 /mnt/external_sd 、/mnt/sdcard2 等節點,而將外置的SD卡掛載到 Environment.getExternalStorageDirectory()這個結點。
此時,調用Environment.getExternalStorageDirectory(),則返回外置的SD的路徑。
而另外一部分手機直接將eMMC存儲掛載在Environment.getExternalStorageDirectory()這個節點,而將真正的外置SD卡掛載到/mnt/external_sd、/mnt/sdcard2 等節點。
此時,調用Environment.getExternalStorageDirectory(),則返回內置的SD的路徑。
至此就能解釋爲都是無外置SD卡的狀況下,在中興手機上,調用
打印 Environment.getExternalStorageState(),卻返回 」removed「,在索尼、MOTO G上就返回:「mounted」
緣由已經知道了,但是如何在無外置SD卡的時候,獲取到這個內置eMMC存儲的具體路徑呢?
好比,我這個中興手機,既然使用 Environment.getExternalStorageDirectory() 獲取到的是外置SD卡路徑,可是我又沒有插入SD卡,這個時候我想使用內置的eMMC存儲來存儲一些程序中用到的數據,我怎麼去獲取這個eMMC存儲的路徑呢?
答案是:經過掃描系統文件"system/etc/vold.fstab」來實現。
"system/etc/vold.fstab」 只是一個簡單的配置文件,它描述了Android的掛載點信息。
咱們能夠遍歷這個文件來獲取全部的掛載點:
html
/** * 遍歷 "system/etc/vold.fstab」 文件,獲取所有的Android的掛載點信息 * * @return */ private static ArrayList<String> getDevMountList() { String[] toSearch = FileUtils.readFile("/etc/vold.fstab").split(" "); ArrayList<String> out = new ArrayList<String>(); for (int i = 0; i < toSearch.length; i++) { if (toSearch[i].contains("dev_mount")) { if (new File(toSearch[i + 2]).exists()) { out.add(toSearch[i + 2]); } } } return out; }
以後,當 Environment.getExternalStorageState()返回「removed」的時候(即,當沒有掛載外置SD卡的時候),經過getDevMountList()方法獲取一個list,這個list中能夠進行寫操做的那個就是系統自帶的eMMC存儲目錄了。
判斷邏輯:java
/** * 獲取擴展SD卡存儲目錄 * * 若是有外接的SD卡,而且已掛載,則返回這個外置SD卡目錄 * 不然:返回內置SD卡目錄 * * @return */ public static String getExternalSdCardPath() { if (SDCardUtils.isMounted()) { File sdCardFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()); return sdCardFile.getAbsolutePath(); } String path = null; File sdCardFile = null; ArrayList<String> devMountList = getDevMountList(); for (String devMount : devMountList) { File file = new File(devMount); if (file.isDirectory() && file.canWrite()) { path = file.getAbsolutePath(); String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date()); File testWritable = new File(path, "test_" + timeStamp); if (testWritable.mkdirs()) { testWritable.delete(); } else { path = null; } } } if (path != null) { sdCardFile = new File(path); return sdCardFile.getAbsolutePath(); } return null; }
參考:
[1] http://hubingforever.blog.163.com/blog/static/17104057920129198236599/
[2] http://stackoverflow.com/questions/5694933/find-an-external-sd-card-location
[3] http://developer.android.com/about/versions/android-3.0.html
android