转自:http://my.oschina.net/liucundong/blog/288183

我有一台中兴的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的挂载点信息。
我们可以遍历这个文件来获取所有的挂载点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    /**
     * 遍历 "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存储目录了。

判断逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    /**
     * 获取扩展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手机自带内部存储路径的获取 (转)的更多相关文章

  1. 网络编程之PC版与Android手机版带断点续传的多线程下载

    一.多线程下载         多线程下载就是抢占服务器资源         原理:服务器CPU 分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服 ...

  2. android 各个存储路径及获取方法总结

    最长用到的就这三个位置 /data/data/包名/ /sdcard/Android/data/包名/ /sdcard/xxx 前两个是应用内部存储, 会随着app的卸载而自动删除, sdcard中其 ...

  3. Android手机外置SD卡(TF卡)的获取方法

    Android手机上的外置SD卡,起初的时候,即在Android出世的前几年,那时手机的存储是十分有限的,不像现在到处可见16G.32G和64G的存储,因而那时候的手机有的厂商允许插入外置的SD卡,此 ...

  4. android手机自带浏览器无法识别apk文件

    在项目中遇到安卓自带浏览器下载成功 , 但无法打开已下载的APK文件自动安装的问题,特别是三星系列的手机普遍存在这种问题,google后发现也有朋友遇到类似的问题: http://bbs.csdn.n ...

  5. android gridview几个重要属性(android:listSelector自带内部padding分析)

    一.android:scrollbarStyle  决定状态条的位置     常用属性outsideOverlay,滚动条在最外层,gridview设置的padding在滚动条的内侧   二.andr ...

  6. android中的文件操作详解以及内部存储和外部存储(转载)

    原文链接:http://m.blog.csdn.net/article/details?id=17725989 摘要 其实安卓文件的操作和java在pc环境下的操作并无二致,之所以需要单独讲解是因为安 ...

  7. 【转】 android中的文件操作详解以及内部存储和外部存储

    摘要 其实安卓文件的操作和Java在pc环境下的操作并无二致,之所以需要单独讲解是因为安卓系统提供了不同于pc的访问文件系统根路径的api,同时对一个应用的私有文件做了统一的管理.根据我的经验,初学者 ...

  8. Android SDCard和内部存储中gcc编译后的可执行文件无法运行提示 cannot execute - Permission denied

    原因是mount的方式问题,root后运行 su mount -o rw,remount /mnt/sdcard   //SDCard mount -o rw,remount /mnt/interna ...

  9. Android Environment.getExternalStorageDirectory() 获取的是内部存储还是外部存储? - z

    这几天在做Android应用的远程更新功能,将下载的更新包放在移动设备上指定的目录.用的是  Environment.getExternalStorageDirectory() 这个方法,然后在获取的 ...

随机推荐

  1. 匈牙利算法(素数伴侣(HW1112))

    #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vector> #include<string&g ...

  2. Net Core WebApi单元测试

    单元测试 本篇将结合这个系列的例子的基础上演示在Asp.Net Core里如何使用XUnit结合Moq进行单元测试,同时对整个项目进行集成测试. 第一部分.XUnit 修改 Project.json  ...

  3. Azure File SMB3.0文件共享服务(2)

    使用Powershell创建文件共享 Azure的文件存储结构如下所示,最基本的文件存储包含存储账号,文件共享,在文件共享下面你可以建立文件目录,上传文件: 在开始使用Powershell创建文件共享 ...

  4. Linux文件解压缩详解

    tar命令 我们知道在Windows下最常见的压缩文件就只有两种,一是,zip,另一个是.rar.可是Linux就不同了,它有.gz..tar.gz.tgz.bz2..Z..tar等众多的压缩文件名, ...

  5. NFC 与点对点应用

    http://wenku.baidu.com/view/6a7623a28762caaedc33d426.html

  6. 电子科大POJ "整数的千位分隔"

    整数的千位分隔 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) C-source ...

  7. 栈ADT的数组实现

    /* 栈的数组实现声明 */ struct StackRecord; typedef struct StackRecord *Stack; #define MinSstackSize 5 #defin ...

  8. Linux主机规划与磁盘分区

    各硬件设备在Linux中的文件名 在Linux系统当中,几乎所有的硬件设备文件都在/dev这个目录内. 各硬件设备在Linux中的文件名: 设备 设备在Linux中的文件名 IDE接口的硬盘 /dev ...

  9. jQuery中设置form表单中action值的方法

    jQuery中设置form表单中action值的方法 (2011-03-17 10:18:19) 转载▼ 标签: 杂谈   html代码: <form id="myFormId&quo ...

  10. UVA 489-- Hangman Judge(暴力串处理)

     Hangman Judge  In ``Hangman Judge,'' you are to write a program that judges a series of Hangman gam ...