当前位置: 首页 > article >正文

Android内部存储与外置SDCard

Android手机存储
通常有三个部分
1、Ram
Ram 也就是相当于PC内存条的东东,没什么好说的。


2、手机存储
手机内通常内置一块eMMC存储设备,也就是常说的Rom。个人觉得这个Rom就相当于PC的硬盘。


其实,手机自带存储叫Rom有点过时了,所谓的“ROM是只读内存(Read-Only Memory)的简称。ROM所存数据,一般是装入整机前事先写好的,整机工作过程中只能读出,而不像随机存储器那样能快速地、方便地加以改写。ROM所存数据稳定 ,断电后所存数据也不会改变;其结构较简单,读出较方便,因而常用于存储各种固定程序和数据”。在Android之前的手机,包括智能机(Nokia、WM等)和非智能机(索爱,Moto P2K平台,MTK等)都有一个单独的ROM芯片保存系统文件。
系统区存储
随着这块芯片的存储容量越来越大,如今的手机很多都进行了分区。一部分相当于以前的Rom,相对于PC就好像是windows的C盘一样,但依然是可写的,用于存储系统,以及安装的程序。“data/data/包名”目录下可存储应用的私有数据,其它应用没有权限读写。
虚拟SD卡(通常说的内部存储)
这是eMMC芯片的另一部分,相当于PC的D盘,至于可不可以把eMMC芯片分更多区,这个没有找到相关资料,也没有发现这样的设备,应该暂时不用管吧。


3、外部存储
也就是外置的SDcard这些东东。




介绍了Android手机的存储情况,那么问题来啦。
都知道取SDcard的路径用的是Android提供的接口 Environment.getExternalStorageDirectory(),但是接口只有一个,取到的是虚拟的SDcard,还是真正的外置SDcard就不知道了。实际上两个都有可能,不同的手机产商得到的结果会不一样。如何取到另一个以及如何知道哪个是真正的外置SDcard。
方法一:通过分析mount指令的返回结果(百度来的,网址不记得了)
public static String[] getAllSDCard() {
String s = "";
try {
Process process = new ProcessBuilder().command("mount")

       .redirectErrorStream(true).start();

process.waitFor();

InputStream is = process.getInputStream();
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
   s = s + new String(buffer);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}


//用行分隔mount列表
String[] lines = s.split("\n");
for(int i=0; i<lines.length; i++) {
//如果行内有挂载路径且为vfat类型,说明可能是内置或者外置sd的挂载点
if(-1 != lines[i].indexOf("sdcard") && -1 != lines[i].indexOf("vfat")) {
   //再用空格分隔
   String[] blocks = lines[i].split("\\s");
   for(int j=0; j<blocks.length; j++) {
       //判断是否是挂载为vfat类型
       if(-1 != blocks[j].indexOf("sdcard")) {
           //Test if it is the external sd card.
       }
   }
}
}
return lines;
}


方法二:读系统文件,从文件中提取出来 (百度来的)
    public static Map<String, File> getAllStorageLocations() {
        Map<String, File> map = new HashMap<String, File>(10);


        List<String> mMounts = new ArrayList<String>(10);
        List<String> mVold = new ArrayList<String>(10);
        mMounts.add("/mnt/sdcard");
        mVold.add("/mnt/sdcard");


        try {
            File mountFile = new File("/proc/mounts");
            if(mountFile.exists()){
                Scanner scanner = new Scanner(mountFile);
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("/dev/block/vold/")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[1];


                        // don't add the default mount path
                        // it's already in the list.
                        if (!element.equals("/mnt/sdcard"))
                            mMounts.add(element);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        try {
            File voldFile = new File("/system/etc/vold.fstab");
            if(voldFile.exists()){
                Scanner scanner = new Scanner(voldFile);
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("dev_mount")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[2];


                        if (element.contains(":"))
                            element = element.substring(0, element.indexOf(":"));
                        if (!element.equals("/mnt/sdcard"))
                            mVold.add(element);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }




        for (int i = 0; i < mMounts.size(); i++) {
            String mount = mMounts.get(i);
            if (!mVold.contains(mount))
                mMounts.remove(i--);
        }
        mVold.clear();


        List<String> mountHash = new ArrayList<String>(10);


        for(String mount : mMounts){
            File root = new File(mount);
            if (root.exists() && root.isDirectory() && root.canWrite()) {
                File[] list = root.listFiles();
                String hash = "[";
                if(list!=null){
                    for(File f : list){
                        hash += f.getName().hashCode()+":"+f.length()+", ";
                    }
                }
                hash += "]";
                if(!mountHash.contains(hash)){
                    String key = "SD_CARD" + "_" + map.size();
                    if (map.size() == 0) {
                        key = "SD_CARD";
                    } else if (map.size() == 1) {
                        key = "EXTERNAL_SD_CARD";
                    }
                    mountHash.add(hash);
                    map.put(key, root);
                }
            }
        }


        mMounts.clear();


        if(map.isEmpty()){
                 map.put("SD_CARD", Environment.getExternalStorageDirectory());
        }
        return map;
    }


事实上,方法一与方法二都可以取到当前挂载的SDcard列表,然而并不能区分是不是虚拟的。


可是系统自带的设置是可以区分,没有办法,只能去看设置的源码。在memory.java中,终于有了我想要的答案。
答案就在这里:
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        final Context context = getActivity();
        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        mStorageManager = StorageManager.from(context);
        mStorageManager.registerListener(mStorageListener);
        addPreferencesFromResource(R.xml.device_info_memory);
        addCategory(StorageVolumePreferenceCategory.buildForInternal(context));
        final StorageVolume[] storageVolumes = mStorageManager.getVolumeList();
        for (StorageVolume volume : storageVolumes) {
            if (!volume.isEmulated()) {
                addCategory(StorageVolumePreferenceCategory.buildForPhysical(context, volume));
            }
        }
        setHasOptionsMenu(true);
    }


通过mStorageManager.getVolumeList()就可以得到存储器的列表,volume.isEmulated()可判断是不是虚拟的。一部分手机的isEmulated得到的都是false,结合isRemovable可得到更准确的判断。因为这些方法与类被SDK隐藏了,不能直接调用,所以只能通过java的反射机制了。
方法三:
public static void getAllStorages(Context c) {
StorageManager storageManager = (StorageManager) c
.getSystemService(Context.STORAGE_SERVICE);
try {
Class<?>[] paramClasses = {};
Method getVolumePathsMethod = StorageManager.class.getMethod(
"getVolumeList", paramClasses);
getVolumePathsMethod.setAccessible(true);
Object[] params = {};
Object[] invoke = (Object[]) getVolumePathsMethod.invoke(storageManager, params);
Class<?> volume = Class.forName("android.os.storage.StorageVolume");
Field[] fields = volume.getDeclaredFields();
for (Field f:fields) 
LOG.d(f.getName());
Field fieldPath = volume.getDeclaredField("mPath");
Field fieldEmulated = volume.getDeclaredField("mEmulated");
Field fieldRemove = volume.getDeclaredField("mRemovable");
fieldPath.setAccessible(true);
fieldEmulated.setAccessible(true);
fieldRemove.setAccessible(true);
for (int i = 0; i < invoke.length; i++) {
File filePath = (File) fieldPath.get(invoke[i]);
boolean emulated = fieldEmulated.getBoolean(invoke[i]);
boolean remove = fieldRemove.getBoolean(invoke[i]);
LOG.i("\npath : " + filePath.getPath() + "  isEmulated : " + emulated + "  isRemovable : " + remove);
}
} catch (Exception e) {
e.printStackTrace();
}
}
http://www.lryc.cn/news/2415542.html

相关文章:

  • 一份关于windows server服务器的安全漏洞处理建议(来自绿盟安全评估)_允许traceroute探测漏洞
  • 数据结构——家谱管理系统
  • java天美美容院管理系统(开题+源码)
  • 网页常用外链网址总结
  • 一个月收益高达16.5K,来看我是如何通过Python技术手段变现,逐步迈向财富自由的!
  • 【教程】迅为iTOP-4412精英版exynos4412开发板搭建原生Linux最小系统(二)
  • 如何更新 Symantec AntiVirus 企业版的病毒定义
  • 信号处理国际会议排名
  • CE修改器第一关之下载安装使用教程
  • 服务器好玩的项目_【警示分析】秘乐、赞丽、AOT、车秘等等,你正在玩和最关心的项目,降魔一一给你分析现状!必看!!!...
  • 从BOSCore公投WPS提案,探讨区块链社区治理新思路
  • Ubuntu安装搜狗拼音输入法-sogoupinyin
  • Android SystemServer进程启动流程
  • 周围剃光头顶留长发型_你说她们在“装嫩”?不好意思,这些发型你试了就会真香...
  • PHP | php入门知识(数据类型、类型比较、常量、字符串、运算符)
  • CSS常用例子
  • 一套webshell提权教程
  • 密码编码学与网络安全———原理与实践(第六版) (第2章) 笔记
  • linux 多进程函数,多进程之信号量 Linux函数 semget();semctl();semop(); [转]
  • 爬虫入门到进阶(七)
  • (转)“Word上次启动时失败,以安全模式启动Word....”解决办法
  • MyEclipse 注册码分享
  • 基于matlab实现人脸识别检测系统
  • Visual Studio 2008 专业版
  • proto语法说明
  • 最新短视频去水印解析API接口分享
  • 三星 原生android,原生Android 4.0 三星GALAXY Nexus评测
  • java技术讨论QQ群号码:40820473
  • 无人机倾斜摄影测量技术,倾斜摄影三维建模测量技术及其应用详解
  • 数字图像基本知识