/storage/sdcard0, /sdcard, /mnt/sdcard ,/storage/emulated/legacy 的区别
原文鏈接:http://blog.csdn.net/ouyang_peng
關(guān)于android的4.2的0文件夾的詳解
—- android 4.0 —-
在galaxy nexus(GN)手機上userdata分區(qū)很大,被掛在/data目錄,用戶的數(shù)據(jù)通常是放在sd卡上,然而gn是沒有sd卡的,所以google想了一個辦法,就是虛擬一個。
所以,在userdata分區(qū)下有個目錄叫media,是內(nèi)置sd卡的數(shù)據(jù)存儲位置,使用fuse技術(shù)將/data/media虛擬成為一個叫做/dev/fuse的設(shè)備,為了讓程序能認出來,被同時掛載在 /mnt/sdcard 目錄,
又為了兼容以前的程序,做了一個快捷方式(Linux系統(tǒng)里叫軟連接) /sdcard 指向的是 /mnt/sdcard .
當然,這些都是4.0的做法。
—- android 4.1 —-
在4.1里,同樣也會使用fuse技術(shù),/dev/fuse 會被同時掛載到/storage/sdcard0 目錄,這個sdcard0表示第一個sd卡(如果有外置sd卡,那會多一個 /storage/sdcard1,比如我的xoom), /sdcard
軟連接會指向 /storage/sdcard0 ,此時/mnt/sdcard 也是個軟連接,會指向/storage/sdcard0。
如果你通過otg線接U盤,會被掛載到 /storage/usb0目錄,stickmount這個軟件為了讓圖庫、快圖、mx player等軟件,能看到u盤里的數(shù)據(jù),又同時掛載到 /storage/sdcard0/usStorage/sda1.
也許你會問,為什么不是usb0,而是sda1,這是linux的對硬盤的命名方式,如果你的u盤有多個分區(qū),就分別是sda1,sda2這樣一直排下去了。
—- android 4.2 —-
好了,我們開始說4.2系統(tǒng)。
谷歌是不是沒事干啊,非要給android搞個多用戶,你想想啊,在中國,可能因為經(jīng)濟問題,家里不是每人一個電腦,在美國,幾乎需要用電腦的人,都會自己有一臺或多臺,一臺電腦多人用的情況少之又少,這就是為什么叫PC了,顧名思義,個人電腦。像手機和平板這些東西,更加私人化了,很少公用了吧,我想在中國也是如此吧。
當然,谷歌也不完全是抽風,因為他有更大的戰(zhàn)略部署,而且平板也的確有多人用的可能。
所以谷歌搞出來一個多用戶,那每個人的應(yīng)用、數(shù)據(jù)、個性配置都要分開吧。 應(yīng)用和個性配置好弄,想想啊,通過權(quán)限控制,每人只能看自己的應(yīng)用就行了,桌面也可以用自己的。
那數(shù)據(jù)怎么辦????
好吧,調(diào)整用戶數(shù)據(jù)的掛載結(jié)構(gòu)。android 4.2,同樣也會使用fuse技術(shù)/dev/fuse 會被掛載到/storage/emulated/0 目錄,為什么是0呢,你還記得上邊的sdcard0吧,第一個的意思。(如果有第二個,應(yīng)該就是/storage/emulated/1,我們的三兒子沒有外置sd卡,所以沒法驗證)
為了兼容以前,同時掛載到 /storage/emulated/legacy (故名思議,傳統(tǒng)的),還建立三個軟連接 /storage/sdcard0 ,/sdcard,/mnt/sdcard ,都指向 /storage/emulated/legacy
還有值得一提的是,4.2剛出來,這塊變動又比較大,所以stickmount要升級到2.2之后,才可以通過otg掛載u盤了。
所以大家不用為0而苦惱了,這是正常的“生理特征”。
也許你會問,這個0和多用戶有什么關(guān)系呢,那是因為多用戶這個新特性,只在平板上才啟用,在手機上會被禁用的。但是底層實現(xiàn)是一致的。 /mnt/shell/emulated 目錄和 /storage/emulated 下的文件夾是一樣的。(注意,這個/mnt/shell/emulated 不是掛載出來的)
由于我沒有平板升級到4.2,所以只是推測,/mnt/shell/ 是為了多用戶準備的,因為linux的多用戶是基于shell實現(xiàn)的。
—————————–補充———————————–
4.2 在平板上的多用戶
我前一段時間給XOOM Wifi刷上了CM10.1的4.2.1,成功開啟多用戶特性。新建的用戶id從10開始。
默認用戶的sdcard目錄: /storage/emulated/0
新建的第一個用戶的sdcard目錄: /storage/emulated/10
新建的第二個用戶的sdcard目錄: /storage/emulated/11
關(guān)于0/0/0/0文件夾問題
是舊版本的CMW recovery在執(zhí)行wipe data時導(dǎo)致建立新的0文件夾,請升級到cmw recovery 6.0.1.9 之后的版本,至于已經(jīng)出現(xiàn)了多層0目錄,請用RootExplorer剪切粘貼回/storage/emulated/0 下,推薦使用最新版CMW recovery
===============轉(zhuǎn)自:http://blog.csdn.NET/gxj1680/article/details/8900270
最近的手機助手碰到一些關(guān)于sdcard目錄的問題,特記下來以作備忘
在android 4.2版本之前,通過Environment.getExternalStorageDirectory()獲取的sdcard默認目錄是正常的,可進行讀寫,一般的結(jié)果是“/mnt/sdcard”,但是在4.2版本之后,獲取的sdcard目錄是“/storage/emulated/0”,使用File.exist()方法返回true表示文件/目錄是存在的,但是通過adb向該返回的目錄中寫數(shù)據(jù)(上傳文件=)是不成功的,返回的錯誤是”No such file or directory”,個人判斷是返回的路徑“/storage/emulated/0”其實是個類似快捷方式的文件,通過特定的解析方式可以認為是目錄,但對于adb來說,該路徑就是個文件,adb沒有做過多的屬性=判斷。上述判斷也是有依據(jù)的,通過adb的shell命令獲取指定目錄下的文件/文件夾列表, 該路徑顯示的是文件,且有大小。
之前就有猜測,關(guān)于目錄結(jié)構(gòu)中會存在不同程度的虛擬鏈接文件,google了下確實如此,以下的3處虛擬符號鏈接(類似windows下的快捷方式)是:
“/storage/emulated/0 and /storage/emulated/0/0 (new and “backup” locations, respectively)
/storage/emulated/legacy and /storage/emulated/legacy/0 (new and “backup” locations, respectively)
/storage/sdcard0 and /storage/sdcard0/0 (new and “backup” locations, respectively)”
所以在處理sdcard目錄時,盡量自己先判斷處理后提供同一的接口
import java.io.File; import android.os.Environment; import android.text.TextUtils; public class CommonData { private static String CD_S_SdcardPath = ""; private static String CD_S_SdcardPathAbsolute = ""; public static String getSdcardPath(){ if (TextUtils.isEmpty(CD_S_SdcardPath)) CD_S_SdcardPath = Environment.getExternalStorageDirectory().getPath(); if (CD_S_SdcardPath.contains(CommonType.CT_S_Sdcard_Sign_Storage_emulated)) CD_S_SdcardPath = CD_S_SdcardPath.replace(CommonType.CT_S_Sdcard_Sign_Storage_emulated, CommonType.CT_S_Sdcard_Sign_Storage_sdcard); return CD_S_SdcardPath; } public static String getAbsoluteSdcardPath(){ if (TextUtils.isEmpty(CD_S_SdcardPathAbsolute)) CD_S_SdcardPathAbsolute = Environment.getExternalStorageDirectory().getAbsolutePath(); if (CD_S_SdcardPathAbsolute.contains(CommonType.CT_S_Sdcard_Sign_Storage_emulated)) CD_S_SdcardPathAbsolute = CD_S_SdcardPathAbsolute.replace(CommonType.CT_S_Sdcard_Sign_Storage_emulated, CommonType.CT_S_Sdcard_Sign_Storage_sdcard); return CD_S_SdcardPathAbsolute; } public static File getSdcardPathFile(){ return new File(getSdcardPath()); } public static String checkAndReplaceEmulatedPath(String strSrc){ if (strSrc.contains(CommonType.CT_S_Sdcard_Sign_Storage_emulated)) strSrc = strSrc.replace(CommonType.CT_S_Sdcard_Sign_Storage_emulated, CommonType.CT_S_Sdcard_Sign_Storage_sdcard); return strSrc; } }其中
public static final String CT_S_Sdcard_Sign_Storage_emulated = "storage/emulated/"; public static final String CT_S_Sdcard_Sign_Storage_sdcard = "storage/sdcard";獲取sdcard目錄時,統(tǒng)一有該類提供,以便兼容4.2的sdcard目錄
注:至于通過Environment.getExternalStorageDirectory()獲取的目錄不能寫入的問題,原因還不清楚,如果你知道,請告知,謝謝
注:以上是個人觀察所得,難免有錯誤,如知曉,請告知
/
//2013.05.10修正,關(guān)于目錄/storage/emulated/legacy/目錄的問題
因為google在4.2中考慮多用戶的問題,對每個用戶(user)來說,看各自的文件夾可以,但對于數(shù)據(jù)文件夾的處理就稍微麻煩了,所以調(diào)整了數(shù)據(jù)的掛載結(jié)構(gòu),如使用fuse技術(shù)/dev/fuse 會被掛載到/storage/emulated/0 目錄,為了兼容以前,同時掛載到 /storage/emulated/legacy (故名思議,傳統(tǒng)的),還建立三個軟連接 /storage/sdcard0 ,/sdcard,/mnt/sdcard ,都指向 /storage/emulated/legacy/,(鏈接參見:http://bbs.gfan.com/android-5382920-1-1.html),但是就可能造成獲取文件目錄中的文件(如image)時,會出現(xiàn)相同的圖片(本來上傳1張,但出現(xiàn)了2張==)
將上面的類的判斷修改如下
public class CommonData { private static String CD_S_SdcardPath = ""; private static String CD_S_SdcardPathAbsolute = ""; public static String getSdcardPath(){ if (TextUtils.isEmpty(CD_S_SdcardPath)) CD_S_SdcardPath = Environment.getExternalStorageDirectory().getPath(); CD_S_SdcardPath = checkAndReplaceEmulatedPath(CD_S_SdcardPath); return CD_S_SdcardPath; } public static String getAbsoluteSdcardPath(){ if (TextUtils.isEmpty(CD_S_SdcardPathAbsolute)) CD_S_SdcardPathAbsolute = Environment.getExternalStorageDirectory().getAbsolutePath(); CD_S_SdcardPathAbsolute = checkAndReplaceEmulatedPath(CD_S_SdcardPathAbsolute); return CD_S_SdcardPathAbsolute; } public static File getSdcardPathFile(){ return new File(getSdcardPath()); } public static String checkAndReplaceEmulatedPath(String strSrc){ <span style="color:#ff0000;">Pattern p = Pattern.compile("/?storage/emulated/\\d{1,2}"); Matcher m = p.matcher(strSrc); if (m.find()){ strSrc = strSrc.replace(CommonType.CT_S_Sdcard_Sign_Storage_emulated, CommonType.CT_S_Sdcard_Sign_Storage_sdcard); }</span> // if (strSrc.contains(CommonType.CT_S_Sdcard_Sign_Storage_emulated) && !CD_S_SdcardPath.contains(CommonType.CT_S_Sdcard_Sign_Storage_emulated_legacy)) // strSrc = strSrc.replace(CommonType.CT_S_Sdcard_Sign_Storage_emulated, CommonType.CT_S_Sdcard_Sign_Storage_sdcard); return strSrc; } }另外,針對image的上傳后通過provider獲取image圖片時同一張圖片給了2份,地址分別是”/storage/emulated/legacy/dcim/camera/1.jpg”和”/storage/sdcard0/DCIM/Camera/1.jpg”,其中l(wèi)egacy的屬于兼容的,但獲取能獲取出來,所以獲取時要進行過濾處理
/
public static final String SDPATH = Environment .getExternalStorageDirectory().getAbsolutePath();
//獲取外部存儲的路徑返回絕對路徑的,其實就是你的SD卡的文件路徑
/storage/sdcard
/sdcard
/mnt/sdcard
以上三者的區(qū)別?
/sdcard是/mnt/sdcard的符號鏈,指向/mnt/sdcard,
/storage/sdcard 是sdcard的分區(qū)……
/sdcard/: this is a symlink to…
/mnt/sdcard (Android < 4.0)
/storage/sdcard0 (Android 4.0+)
internal storage - Confused by the many locations of the virtual /sdcard/ - Android Enthusiasts Stack Exchange
總結(jié)
以上是生活随笔為你收集整理的/storage/sdcard0, /sdcard, /mnt/sdcard ,/storage/emulated/legacy 的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 按键手机怎么装java_怎样把USB键盘
- 下一篇: android 4.2目录结构,关于an