android下得到手機自帶存儲的路徑


我有一臺中興的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的掛載點信息。
咱們能夠遍歷這個文件來獲取全部的掛載點:java

 /**
      * 遍歷 "system/etc/vold.fstab」 文件,獲取所有的Android的掛載點信息
     
      * @return
      */
     private  static  ArrayList<String> getDevMountList() {
         String[] toSearch = 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;

    }linux

/**ide

     * read filespa

     * code

     * @param filePathorm

     * @param charsetName The name of a supported {@link java.nio.charset.Charset </code>charset<code>}ci

     * @return if file not exist, return null, else return content of filerem

     * @throws RuntimeException if an error occurs while operator BufferedReader文檔

     */get

    public static String readFile(String filePath) {

        String fileContent = "";

        File file = new File(filePath);

        if (file == null || !file.isFile()) {

            return null;

        }

 

        BufferedReader reader = null;

        try {

            InputStreamReader is = new InputStreamReader(new FileInputStream(file));

            reader = new BufferedReader(is);

            String line = null;

            int i = 0;

            while ((line = reader.readLine()) != null) {

                fileContent += line + " ";

            }

            reader.close();

            return fileContent;

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            if (reader != null) {

                try {

                    reader.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

        return fileContent;

    }



以後,當 Environment.getExternalStorageState()返回「removed」的時候(即,當沒有掛載外置SD卡的時候),經過getDevMountList()方法獲取一個list,這個list中能夠進行寫操做的那個就是系統自帶的eMMC存儲目錄了。

判斷邏輯:

/**
      * 獲取擴展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 ;
     }


但有的手機設備中沒法用getExternalSdCardPath()獲得內置存儲的路徑,在system/etc/vold.fstab文件裏並無列明,如三星手機。這時須要經過使用linux的 mount命令來實現讀取路徑。

/*

得到外部內置存在路徑

經過執行mount命令來得到內置存儲的路徑

*/

public String getExterPath(){

//獲得路徑

String sdcard_path="";

try {

Runtime runtime = Runtime.getRuntime();

Process proc = runtime.exec("mount");

InputStream is = proc.getInputStream();

InputStreamReader isr = new InputStreamReader(is);

String line;


BufferedReader br = new BufferedReader(isr);

while ((line = br.readLine()) != null) {

if (line.contains("secure")) continue;

if (line.contains("asec")) continue;


if (line.contains("fat")) {

String columns[] = line.split(" ");

if (columns != null && columns.length > 1) {

sdcard_path = sdcard_path.concat(columns[1]);

}

} else if (line.contains("fuse")) {

String columns[] = line.split(" ");

if (columns != null && columns.length > 1) {

sdcard_path = sdcard_path.concat(columns[1] );

}

}

}

}

catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return sdcard_path;

}

相關文章
相關標籤/搜索