android 系统是开源的,于是各种产商各种瞎改android系统,工作了几个月,我发现单单就android的内外存储设备的路径我就不知道怎么获取了。上网查了几种方案,自己试验了下,感觉好迷茫啊。在这里记录下我试验的几种方案。

方案一:通过Enviroment类获取存储设备路径

android的官方文档上说,采用Enviroment.getExternalStorageDirectory()方法可以得到android设备的外置存储(即外插SDCARD),如果android设备有外插SDCARD的话就返回外插SDCARD的根目录路径,如果android设备没有外插SDCARD的话就返回android设备的内置SDCARD的路径。这套方案很快就被否决了,因为Enviroment类的这个方法里面的路径也是写死的,只有原生的android系统才使用这套方案,被更改过的anroid体统很多设备的路径都改了。

方案二:读取system/etc/vold.fstab文件的内容来获取存储设备路径

参考文档:http://blog.csdn.net/bbmiku/article/details/7937745

内置和外置SD卡的信息存在system/etc/vold.fstab 里面,我们可以从这里获得外置SD卡的路径。经本人实验,发现很多疑问。我的机子是三星I9300,我的机子没有外插SDCARD。通过eclipse获取vold.fstab文件,打开来看,有用的内容如下:

dev_mount sdcard /storage/extSdCard auto /devices/platform/s3c-sdhci.2/mmc_host/mmc1/

dev_mount sda /storage/UsbDriveA auto /devices/platform/s5p-ehci

dev_mount sdb /storage/UsbDriveB auto /devices/platform/s5p-ehci

dev_mount sdc /storage/UsbDriveC auto /devices/platform/s5p-ehci

dev_mount sdd /storage/UsbDriveD auto /devices/platform/s5p-ehci

dev_mount sde /storage/UsbDriveE auto /devices/platform/s5p-ehci

dev_mount sdf /storage/UsbDriveF auto /devices/platform/s5p-ehci

这里可没有我的内置SDCARD的路径啊,不懂。打开手机的文件系统发现我的内置的SDCARD路径是:/storage/emulated/0。于是我到eclipse的DDMS中去看下我的手机文件系统,发现storage路径下的文件结构为:
android 获取 内外存储设备路径疑问_第1张图片
从这个文件结构可以看出,真正有内容的应该是emulated/legacy和sdcard0才对,再从后面的连接来看,最后这两个目录都应该是指向/mnt/shell/emulated/0。接着打开/mnt/shell/emulated/0来看看,果然是我的sdcard目录


android 获取 内外存储设备路径疑问_第2张图片
这让我很疑惑,这样的话,读取vold.fstab文件来获取sdcard目录不就得不到/mnt/shell/emulated/0目录了么。方案二失败。

方案三:方案三的原理是linux命令,在命令窗口中输入 mount 或者 cat /proc/mounts 可得到系统挂载的存储。你也可以在DOS窗口中输入 adb shell -> mount ,或者 adb shell -> cat /proc/mounts 来查看( ”->“ 符号只是一个分割符,不要输)。好,我来DOS窗口中输入adb shell -> mount 来看下会得到什么


android 获取 内外存储设备路径疑问_第3张图片
这个我也看不懂,不过我猜最后一条应该是我的SDCARD的挂载了,因为有/mnt/shell/emulated 挂载路劲出现, 而/data/media是挂载的设备么?这是什么东西?好,我借部手机来看看,看其他的手机会mount出什么东西来。 那就借部note3来吧


android 获取 内外存储设备路径疑问_第4张图片
我借来的这部手机有外插SDCARD。可以看到最后两条应该是挂载SDCARD信息了。不过它的挂载设备是/dev/fuse, 和 /dev/block/vold/179:17 。 好吧,我晕了,等等,会不会 最后两条信息才是挂载SDCARD信息呢?我的是手机因为没有外插SDCARD,所以最后一条才是挂载SDCARD信息,有外插SDCARD的,最后两条是挂载SDCARD信息。这是规律?好吧,不是规律,我又借了部手机,mount了下,发现这个猜想纯属扯淡。

利用mount命令来获取SDCARD路径的方法,

参考:http://my.eoe.cn/1028320/archive/4718.html和 http://www.eoeandroid.com/thread-275560-1-1.html。

方案四:

android常见的SD卡存储位置
/storage/emulated/0/
/storage/extSdCard
/mnt/external_sd/
/mnt/sdcard2/
/mnt/sdcard/external_sd/
/mnt/sdcard-ext/
/mnt/sdcard/
/storage/sdcard0/
/mnt/extSdCard/
/mnt/extsd/
/mnt/emmc/
/mnt/extern_sd/
/mnt/ext_sd/
/mnt/ext_card/
/mnt/_ExternalSD/
/sdcard2/
/sdcard/
/sdcard/sd/
/sdcard/external_sd/
/mnt/sd/
/mnt/
/storage/
/mnt/sdcard/sd/
/mnt/exsdcard/
/mnt/sdcard/extStorages/SdCard/
/ext_card/
/storage/extSdCard

3.0以上可以通过反射获取:

1 StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
2 // 获取sdcard的路径:外置和内置
3 String[] paths = (String[]) sm.getClass().getMethod("getVolumePaths",null).invoke(sm,null);

Android 4.1上

1 StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
2 String[] volumePaths = sm.getgetVolumePaths();

可以获得所有mount的SD卡,难道我要一条一条路径去遍历?就算遍历到了,我也不知道哪条是内置存储,哪条是外置存储。而且以后哪个深井冰产商又整出一条路径出来,不就没完没了了嘛。

我现在很郁闷,到底怎么弄才有一套最佳方案?跪求大神解救我。

/** * 获取外置SD卡路径 *  * @return */public static List<String> getSDCardPaths() {List<String> sdcardPaths = new ArrayList<String>();String cmd = "cat /proc/mounts";Runtime run = Runtime.getRuntime();// 返回与当前 Java 应用程序相关的运行时对象try {Process p = run.exec(cmd);// 启动另一个进程来执行命令BufferedInputStream in = new BufferedInputStream(p.getInputStream());BufferedReader inBr = new BufferedReader(new InputStreamReader(in));String lineStr;while ((lineStr = inBr.readLine()) != null) {// 获得命令执行后在控制台的输出信息LogUtil.i("CommonUtil:getSDCardPath", lineStr);String[] temp = TextUtils.split(lineStr, " ");// 得到的输出的第二个空格后面是路径String result = temp[1];File file = new File(result);if (file.isDirectory() && file.canRead() && file.canWrite()) {LogUtil.d("directory can read can write:",file.getAbsolutePath());// 可读可写的文件夹未必是sdcard,我的手机的sdcard下的Android/obb文件夹也可以得到sdcardPaths.add(result);}// 检查命令是否执行失败。if (p.waitFor() != 0 && p.exitValue() == 1) {// p.exitValue()==0表示正常结束,1:非正常结束LogUtil.e("CommonUtil:getSDCardPath", "命令执行失败!");}}inBr.close();in.close();} catch (Exception e) {LogUtil.e("CommonUtil:getSDCardPath", e.toString());sdcardPaths.add(Environment.getExternalStorageDirectory().getAbsolutePath());}optimize(sdcardPaths);for (Iterator iterator = sdcardPaths.iterator(); iterator.hasNext();) {String string = (String) iterator.next();Log.e("清除过后", string);}return sdcardPaths;}private static void optimize(List<String> sdcaredPaths) {                if (sdcaredPaths.size() == 0) {                    return;                 }int index = 0;while (true) {if (index >= sdcaredPaths.size() - 1) {String lastItem = sdcaredPaths.get(sdcaredPaths.size() - 1);for (int i = sdcaredPaths.size() - 2; i >= 0; i--) {if (sdcaredPaths.get(i).contains(lastItem)) {sdcaredPaths.remove(i);}}return;}String containsItem = sdcaredPaths.get(index);for (int i = index + 1; i < sdcaredPaths.size(); i++) {if (sdcaredPaths.get(i).contains(containsItem)) {sdcaredPaths.remove(i);i--;}}index++;}}

一定记得在manifest.xml中加权限

更多相关文章

  1. Android获取SDCard路径/Android获取存储器挂载点
  2. Android闹钟设置的解决方案
  3. 那些iOS和Android跨平台解决方案
  4. 更改Android studio中SDK,AVD的默认路径
  5. Android Studio 配置模拟器AVD存放路径(默认在c盘,解决c盘空间不够
  6. afinal框架之Android视频下载,指定路径
  7. Android手机或Android平板电脑 应用不能全屏显示,解决方案!
  8. Android几种消息推送方案总结

随机推荐

  1. Android客户端自动更新代码
  2. Android(安卓)对UI操作的工具类UIUtils
  3. android 客户端 smtp 协议发送数据
  4. Android获取单选与复选框的值
  5. android 判断文件是否存在
  6. Android之MediaPlayer(两种)基本使用方式
  7. C#内置泛型委托之Func委托
  8. C++单例模式的懒汉模式和饿汉模式详解
  9. ASP.NET CORE实现跨域
  10. C++的数据共享与保护你了解吗