如何访问Android设备上的可移动存储?

时间:2012-04-23 14:24:15

标签: android android-sdcard

我正在寻找一种方法来检测和访问各种Android设备(三星,摩托罗拉,LG,索尼,HTC)上的可移动SD卡。

我还需要与2.2兼容,因此我无法使用Environment.isExternalStorageRemovable()

摩托罗拉有自己的库,对于三星,我可以检测到/external_sd/

的存在

我对其余的人一无所知。例如,我在某些LG上看到/_ExternalSD/,但即使删除了SD,目录仍然存在。

奖励问题:ACTION_MEDIA_MOUNTED意图是否会为其中任何人播放

任何暗示都会非常有用。

5 个答案:

答案 0 :(得分:4)

这是我用来查找设备上所有sdcards的类;内置和可拆卸。我一直在冰淇淋三明治上使用它,但它应该在2倍的水平下工作。

public class GetRemovableDevice {

private final static String TAG = "GetRemoveableDevice";

public GetRemovableDevice() {
}

public static String[] getDirectories() {
    MyLog.d(TAG, "getStorageDirectories");
    File tempFile;
    String[] directories = null;
    String[] splits;
    ArrayList<String> arrayList = new ArrayList<String>();
    BufferedReader bufferedReader = null;
    String lineRead;

    try {
        arrayList.clear(); // redundant, but what the hey
        bufferedReader = new BufferedReader(new FileReader("/proc/mounts"));

        while ((lineRead = bufferedReader.readLine()) != null) {
            MyLog.d(TAG, "lineRead: " + lineRead);
            splits = lineRead.split(" ");

            // System external storage
            if (splits[1].equals(Environment.getExternalStorageDirectory()
                    .getPath())) {
                arrayList.add(splits[1]);
                MyLog.d(TAG, "gesd split 1: " + splits[1]);
                continue;
            }

            // skip if not external storage device
            if (!splits[0].contains("/dev/block/")) {
                continue;
            }

            // skip if mtdblock device

            if (splits[0].contains("/dev/block/mtdblock")) {
                continue;
            }

            // skip if not in /mnt node

            if (!splits[1].contains("/mnt")) {
                continue;
            }

            // skip these names

            if (splits[1].contains("/secure")) {
                continue;
            }

            if (splits[1].contains("/mnt/asec")) {
                continue;
            }

            // Eliminate if not a directory or fully accessible
            tempFile = new File(splits[1]);
            if (!tempFile.exists()) {
                continue;
            }
            if (!tempFile.isDirectory()) {
                continue;
            }
            if (!tempFile.canRead()) {
                continue;
            }
            if (!tempFile.canWrite()) {
                continue;
            }

            // Met all the criteria, assume sdcard
            arrayList.add(splits[1]);
        }

    } catch (FileNotFoundException e) {
    } catch (IOException e) {
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException e) {
            }
        }
    }

    // Send list back to caller

    if (arrayList.size() == 0) {
        arrayList.add("sdcard not found");
    }
    directories = new String[arrayList.size()];
    for (int i = 0; i < arrayList.size(); i++) {
        directories[i] = arrayList.get(i);
    }
    return directories;
}

}

MyLog.d是一个扩展Log.d的跟踪类 - 它可以被删除。

该类读取/ proc / mounts /和:

  1. 检查路径名是否为内部sdcard目录
  2. 检查其是否为阻止设备
  3. 跳过mtdblock devices
  4. 跳过任何未安装的内容
  5. 跳过安全和asec目录
  6. 确保它存在,是目录,可读/写
  7. 如果匹配所有这些,则假定您有一个sdcard并将路径添加到数组列表中。它返回路径名的字符串数组。

    要调用getDirectories函数,请编写类似于:

    的代码
    String[] sdcardDirectories = GetRemoveableDevice.getDirectories();
    

    返回的路径可用于创建用户选择列表,扫描文件或其他任何内容。

    最后,这是来自模拟器测试的两行MyLog.d(第二行是模拟器SD卡):

    09-19 15:57:12.511:D / GetRemoveableDevice(651):lineRead:/ dev / block / mtdblock2 / cache yaffs2 rw,nosuid,nodev 0 0

    09-19 15:57:12.511:D / GetRemoveableDevice(651):lineRead:/ dev / block / vold / 179:0 / mnt / sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid = 1000, gid = 1015,fmask = 0702,dmask = 0702,allow_utime = 0020,codepage = cp437,iocharset = iso8859-1,shortname = mixed,utf8,errors = remount-ro 0 0

答案 1 :(得分:2)

基于Howards类,我做了一些修改,使其适用于Galaxy S3。

  1. Environment.getExternalStorageDirectory()返回S3上的内部存储。
  2. 可移动存储不一定安装在/ mnt
  3. 可移动媒体必须具有vfat文件系统
  4. _

    public static String getDirectory() {
            Log.d(TAG, "getStorageDirectories");
            File tempFile;
            String[] splits;
            ArrayList<String> arrayList = new ArrayList<String>();
            BufferedReader bufferedReader = null;
            String lineRead;
    
            try {
                arrayList.clear(); // redundant, but what the hey
                bufferedReader = new BufferedReader(new FileReader("/proc/mounts"));
    
                while ((lineRead = bufferedReader.readLine()) != null) {
                    Log.d(TAG, "lineRead: " + lineRead);
                    splits = lineRead.split(" ");
    
                    // skip if not external storage device
                    if (!splits[0].contains("/dev/block/")) {
                        continue;
                    }
    
                    // skip if mtdblock device
                    if (splits[0].contains("/dev/block/mtdblock")) {
                        continue;
                    }
    
                    // skip if not in vfat node
                    if (!splits[2].contains("vfat")) {
                        continue;
                    }
    
                    // skip these names
                    if (splits[1].contains("/secure")) {
                        continue;
                    }
    
                    if (splits[1].contains("/mnt/asec")) {
                        continue;
                    }
    
                    // Eliminate if not a directory or fully accessible
                    tempFile = new File(splits[1]);
                    if (!tempFile.exists()) {
                        continue;
                    }
                    if (!tempFile.isDirectory()) {
                        continue;
                    }
                    if (!tempFile.canRead()) {
                        continue;
                    }
                    if (!tempFile.canWrite()) {
                        continue;
                    }
    
                    // Met all the criteria, assume sdcard
                    return splits[1];
                }
    
            } catch (FileNotFoundException e) {
            } catch (IOException e) {
            } finally {
                if (bufferedReader != null) {
                    try {
                        bufferedReader.close();
                    } catch (IOException e) {
                    }
                }
            }
    
            return null;
        }
    

答案 2 :(得分:2)

基于上面提到的两个类,我进一步修改了类,注意到我可以找到的几个手机和平板电脑上的所有外部可移动存储都是使用vold(卷安装守护程序)安装的。

            // skip if not external storage device
            if (!splits[0].contains("vold")) {
                continue;
            }

            if (splits[1].contains("/mnt/asec")) {
                continue;
            }

            // Eliminate if not a directory or fully accessible
            tempFile = new File(splits[1]);
            if (!tempFile.exists()) {
                continue;
            }
            if (!tempFile.isDirectory()) {
                continue;
            }
            if (!tempFile.canRead()) {
                continue;
            }
            if (!tempFile.canWrite()) {
                continue;
            }

            // Met all the criteria, assume sdcard
            arrayList.add(splits[1]);

答案 3 :(得分:1)

这些功能适用于所有Android版本:

  • 要获取外部存储设备上的应用程序文件夹,请致电Context.getExternalFilesDir

  • 请注意,您的应用需要获得外部存储空间的明确许可,并且您应该通过Environment.getExternalStorageState

  • 检查该应用是否可用
  • 是的,每当可移动媒体变得可访问时,ACTION_MEDIA_MOUNTED将被广播(您还应该听取ACTION_MEDIA_EJECTACTION_MEDIA_REMOVED

答案 4 :(得分:1)

这是我创建和使用的方法。这适用于三星Galaxy S4,三星Galaxy Note 3和索尼Xperia Z2。

private static String[] getRemovableStoragePaths() {
    String[] directories;
    String[] splits;
    ArrayList<String> pathList = new ArrayList<String>();
    BufferedReader bufferedReader = null;
    String lineRead;

    try {
        bufferedReader = new BufferedReader(new FileReader("/proc/mounts"));

        while ((lineRead = bufferedReader.readLine()) != null) {
            Log.d(TAG, "lineRead: " + lineRead);
            splits = lineRead.split(" ");
            Log.d(TAG, "Testing path: " + splits[1]);

            if (!splits[1].contains("/storage")) {
                continue;
            }

            if (splits[1].contains("/emulated")) {
                // emulated indicates an internal storage location, so skip it.
                continue;
            }

            // Eliminate if not a directory or fully accessible
            Log.d(TAG, "Path found: " + splits[1]);

            // Met all the criteria, assume sdcard
            pathList.add(splits[1]);
        }

    } catch (FileNotFoundException e) {
    } catch (IOException e) {
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException e) {
            }
        }
    }

    // Send list back to caller

    if (pathList.size() == 0) {
        pathList.add("sdcard not found");
    } else {
        Log.d(TAG, "Found potential removable storage locations: " + pathList);
    }
    directories = new String[pathList.size()];
    for (int i = 0; i < pathList.size(); i++) {
        directories[i] = pathList.get(i);
    }
    return directories;
}