转自: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. pyinstaller打出的EXE包执行时报错“failed to excute ”信息

    我的程序是selenium自动化脚本,打包时执行的是 Python pyinstaller -F --onefile -w  XXX.py 这样打出的包执行后提示“failed to excute s ...

  2. CodeForces 203C Photographer

    简单贪心.注意内存够大,能满足所有顾客的特殊情况. #include <iostream> #include <cstring> #include <algorithm& ...

  3. MDX基础

    第一章 看了本书的第一章,总体一个印象,废话真多.话不多说:整理书中知识点,实践出真理! 知识点:MDX语法:简单的函数介绍; 首先语法网上流传的很多,读者应该具备cube(多维数据集)的知识基础,我 ...

  4. Nutch配置

    http://www.linuxidc.com/Linux/2011-12/48782.htm http://wiki.apache.org/nutch/NutchHadoopTutorial htt ...

  5. 超越css读书笔记

    一.运用所有有效的css选择符 1.属性选择符(基于一个元素是否有属性名称,例如href,或者属性值) 例如:img[alt]{border:1px;} 所有包含alt属性的图像都将会有一个灰色的边框 ...

  6. 关于” fatal error C1010: unexpected end of file while looking forprecompiled header directive”问题

    其中文意思是:致命错误C1010:意想不到的文件结束而寻找预编译头文件的指令错误执行cl exe. 经过多次的查找,终于解决这问题 方法一: 在头文件中加“#include "stdafx. ...

  7. maven02 命令

  8. UVA 1001 Say Cheese

    题意: 一只母老鼠想要找到她的玩具,而玩具就丢在一个广阔的3维空间上某个点,而母老鼠在另一个点,她可以直接走到达玩具的位置,但是耗时是所走过的欧几里得距离*10s.还有一种方法,就是靠钻洞,洞是球形的 ...

  9. IBM WebSphere MQ的C#工具类以及源码(net)

    简单的介绍一下MQ常用的对象 Queue Manager 队列管理器 主要负责管理队列.通道等,类似与Oracle中的Oracle实例的概念,在一台服务器中可以定义多个Queue Manager. Q ...

  10. Notification在不同版本SDK中的使用

    今天总结了一下Notification的使用,发现这个控件在版本上有点扯淡.API11和API16两个分水岭,导致菜鸟在学习的时候比较吃力,受影响的外界因素是多样的,其中比较重要的就是你测试的andr ...