如何获取外置的SD卡路径

SD卡分为内置SD卡和外置SD卡,在平时的工作很少会用到外置的SD卡,因为很多的手机不支持外置SD卡,但也有一些特殊的需求会用到外置的SD卡,不然google也不会对这方面做相应的处理,那么我们怎么才能准确的获取外置SD卡的路径呢?

方法一:(在API 23之前)

1.获取内置SD卡的路径:
        String sdcardPath1 = System.getenv("EXTERNAL_STORAGE"); 
        String sdcardPath2 = Environment.getExternalStorageDirectory().getAbsolutePath();
    2.获取外置SD卡的路径:
        String extSdcardPath = System.getenv("SECONDARY_STORAGE");

这里可能会有很多人去尝试一下这几种方法,博主也不列外,但是你看会发现sdcardPath1和sdcardPath2的路径会不一样,如sdcardPath1=/storage/emulated/legacy;
sdcardPath2=/storage/emulated/0;
这是为什么?不要担心,这是Android系统的问题,android 4.2使用fuse技术/dev/fuse 会被挂载到/storage/emulated/0 目录,为了兼容以前的版本,同时挂载到 /storage/emulated/legacy (故名思议,传统的),还建立三个软连接 /storage/sdcard0 ,/sdcard,/mnt/sdcard ,都指向 /storage/emulated/legacy。也就是说文件夹0和legacy指向的地址是一致的,都是存储盘里的。

在Enviroment类的源码中获得sd卡路径其实也是通过 System.getnv() 方法来实现的.在Environment的内部类UserEnvironment类的构造方法中:

String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
    final String rawSecondaryStorage = System.getenv(ENV_SECONDARY_STORAGE);

注意:在API 23版本或者更高,里面的ENV_SECONDARY_STORAGE被移除了。

方法二:

 Method getVolumList = StorageManager.class.getMethod("getVolumeList");
            getVolumList.setAccessible(true);
            Object[] results = (Object[])getVolumList.invoke(sm);
            if (results != null) {
                for (Object result : results) {
                    // 判断storage volume是否可以移除,true为外置SD卡,false为内置SD卡
                    Method mRemoveable = result.getClass().getMethod("isRemovable");
                    Boolean isRemovable = (Boolean) mRemoveable.invoke(result);
                    if (isRemovable) {
                        // 获取外置SD卡的路径
                        Method getPath = result.getClass().getMethod("getPath");
                        String path = (String) mRemoveable.invoke(result);
                        // 获取外置SD卡的挂载状态
                        Method getState = sm.getClass().getMethod("getVolumeState", String.class);
                        String state = (String)getState.invoke(sm, path);
                        if (state.equals(Environment.MEDIA_MOUNTED)) {
                            isMounted = true;
                            break;
                        }
                    }
                }
            }

代码是通过反射获取的,因为在StorageManager源码中这些方法是被hide的。代码已经注释了。
而获取内置的SD卡的路径还是一样,接口没变,只不过里面的实现有点变了。就拿Environment.getExternalStorageDirectory()来说,因为最终的实现也是通过String sdcardPath1 = System.getenv("EXTERNAL_STORAGE")上面已经说了。直接上源码:

public static File getExternalStorageDirectory() {
        throwIfUserRequired();
        return sCurrentUser.getExternalDirs()[0];
    }

可以看到他是通过sCurrentUser.getExternalDirs()[0]获取的,sCurrentUser是UserEnvironment的实例,那我们来看看getExternalDirs()方法:
API 23之后:

public File[] getExternalDirs() {
            final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,
                    StorageManager.FLAG_FOR_WRITE);
            final File[] files = new File[volumes.length];
            for (int i = 0; i < volumes.length; i++) {
                files[i] = volumes[i].getPathFile();
            }
            return files;
        }

他也是通过getVolumeList方法获取所有的StorageVolume,然后通过getPathFile()获取路径,是一个数组,file[0]是代表内置SD卡的。

而在API 23之前:

public static File getExternalStorageDirectory() {
        throwIfUserRequired();
        return sCurrentUser.getExternalDirsForApp()[0];
    }

他是通过getExternalDirsForApp()方法获取的,我们就来看看这个方法:

public File[] getExternalDirsForApp() {
            return mExternalDirsForApp;
        }

而mExternalDirsForApp是在UserEnvironment的构造方法中初始化的。

mExternalDirsForApp = externalForApp.toArray(new File[externalForApp.size()]);

网上还有一种方法可以获取所有存储空间的路径的方法:就是通过getStorageDirectories()获取,这个没找到,还请见谅。

这里面可能会有很多的问题,欢迎指出,一起学习讨论。

参考的文章:
如何正确获得Android内外SD卡路径
获取Android设备挂载的多有存储路径

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值