관리 메뉴

드럼치는 프로그래머

[안드로이드] Android 확장(추가) SDCard 경로 얻기 본문

★─Programing/☆─Android

[안드로이드] Android 확장(추가) SDCard 경로 얻기

드럼치는한동이 2013. 6. 20. 17:22

최근에 출시된 Android 단말기들은 Micro SD Card를 삽입하지 않아도 

기본적으로 내장 메모리를 가지고 있으며, 추가적으로 sd card를 삽입할 수도 있게 되었습니다.


문제는 Android 기본 API로는 이 추가적으로 삽입된 sd card의 경로는 알수가 없다는 것 입니다. 


일반적으로는 /mnt/sdcard/external_sd/ 라는 경로를 가지고 있게되는데요... 문제는 

이 경로는 제조사측에서 마음이 바뀌면 충분히 경로 명이 바뀔 수 있다는 것 입니다. 


그래서 추가적으로 삽입된 sd card의 경로를 가져올 수 있는 코드를 한번 작성해 보았습니다



  동작방식

 

 1. Android는 리눅스 커널기반에서 동작되므로 모든 장치는 mount되어야만 사용할 수 있습니다.


 2. mount에 대한 정보는 "/system/etc/vold.fstab", "/proc/mounts" 파일로 관리하고 있습니다.


 3. 이 두가지 파일을 이용하여 mount된 Filesystem의 Path를 얻어 옵니다.


 4. 추출된 Filesystem List에서 disk의 크기를 구하여 1Gbyte 미만의 Filesystem은 리스트에서 제거합니다. 


 5. 얻고자 하는 Filesystem만 올수 있도록 알려진 filesystem이 포함된 경우 해당 filsystem을 list에서 제거합니다. 


/**
 * 추가 적인 외부 확장 SDCard path 얻기.
 * 조건으로 걸러진 최종 String List size가 1이 아니면 null 리턴
 * @return
 */
public static String getMicroSDCardDirectory() {
    List<String> mMounts = readMountsFile();
    List<String> mVold = readVoldFile();
     
    for (int i=0; i < mMounts.size(); i++) {
        String mount = mMounts.get(i);
         
        if (!mVold.contains(mount)) {
            mMounts.remove(i--);
            continue;
        }
         
        File root = new File(mount);
        if (!root.exists() || !root.isDirectory()) {
            mMounts.remove(i--);
            continue;
        }
         
        if (!isAvailableFileSystem(mount)) {
            mMounts.remove(i--);
            continue;
        }
         
        if (!checkMicroSDCard(mount)) {
            mMounts.remove(i--);
        }
    }
     
    if (mMounts.size() == 1) {
        return mMounts.get(0);
    }
     
    return null;
}
 
private static List<String> readMountsFile() {
    /**
     * Scan the /proc/mounts file and look for lines like this:
     * /dev/block/vold/179:1 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0602,dmask=0602,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
     
     * When one is found, split it into its elements
     * and then pull out the path to the that mount point
     * and add it to the arraylist
     */
    List<String> mMounts = new ArrayList<String>();
 
    try {
        Scanner scanner = new Scanner(new File("/proc/mounts"));
         
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
             
            if (line.startsWith("/dev/block/vold/")) {
                String[] lineElements = line.split("[ \t]+");
                String element = lineElements[1];
                                     
                mMounts.add(element);
            }
        }
    } catch (Exception e) {
        // Auto-generated catch block
        e.printStackTrace();
    }
     
    return mMounts;
}
 
private static List<String> readVoldFile() {
    /**
     * Scan the /system/etc/vold.fstab file and look for lines like this:
     * dev_mount sdcard /mnt/sdcard 1 /devices/platform/s3c-sdhci.0/mmc_host/mmc0
     *
     * When one is found, split it into its elements
     * and then pull out the path to the that mount point
     * and add it to the arraylist
     */
     
    List<String> mVold = new ArrayList<String>();
     
    try {
        Scanner scanner = new Scanner(new File("/system/etc/vold.fstab"));
         
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
             
            if (line.startsWith("dev_mount")) {
                String[] lineElements = line.split("[ \t]+");
                String element = lineElements[2];
                 
                if (element.contains(":")) {
                    element = element.substring(0, element.indexOf(":"));
                }
 
                mVold.add(element);
            }
        }
    } catch (Exception e) {
        // Auto-generated catch block
        e.printStackTrace();
    }
     
    return mVold;
}
 
private static boolean checkMicroSDCard(String fileSystemName) {
    StatFs statFs = new StatFs(fileSystemName);
     
    long totalSize = (long)statFs.getBlockSize() * statFs.getBlockCount();
     
    if (totalSize < ONE_GIGABYTE) {
        return false;
    }
         
    return true;
}
 
private static boolean isAvailableFileSystem(String fileSystemName) {
    final String[]  unAvailableFileSystemList = {"/dev", "/mnt/asec", "/mnt/obb", "/system", "/data", "/cache", "/efs", "/firmware"};   // 알려진 File System List입니다.
     
    for (String name : unAvailableFileSystemList) {
        if (fileSystemName.contains(name) == true) {
            return false;
        }
    }
     
    if (Environment.getExternalStorageDirectory().getAbsolutePath().equals(fileSystemName) == true) {
        /** 안드로이드에서 제공되는 getExternalStorageDirectory() 경로와 같은 경로일 경우에는 추가로 삽입된 SDCard가 아니라고 판단하였습니다. **/
        return false;
    }
     
    return true;
Comments