繁体   English   中英

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

[英]How to access removable storage on Android devices?

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

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

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

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

奖金问题: ACTION_MEDIA_MOUNTED意图是否会为其中任何一个广播

任何暗示都会非常有帮助。

这是我用来查找设备上所有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设备
  4. 跳过任何未安装的东西
  5. 跳过安全和asec目录
  6. 确保它存在,是一个目录,并且可读/写访问

如果所有这些都匹配,则假定您有一个SD卡并将路径添加到数组列表中。 它返回路径名的字符串数组。

要调用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

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

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

_

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;
    }

基于上面提到的两个类,我进一步修改了类,注意到我可以找到的几个手机和平板电脑上的所有外部可移动存储都是使用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]);

所有Android版本均提供以下功能:

  • 要在外部存储上获取应用程序的文件夹,请调用Context.getExternalFilesDir

  • 请记住,您的应用需要显式访问外部存储的权限,并且您应该通过Environment.getExternalStorageState检查它是否可用

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

这是我创建和使用的方法。 这适用于三星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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM