简体   繁体   English

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

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

I am looking for a way to detect and access removable sd cards on a variety of Android devices (Samsung, Motorola, LG, Sony, HTC). 我正在寻找一种方法来检测和访问各种Android设备(三星,摩托罗拉,LG,索尼,HTC)上的可移动SD卡。

I also need to be compatible with 2.2 so Environment.isExternalStorageRemovable() is unavailable for me. 我还需要与2.2兼容,因此我无法使用Environment.isExternalStorageRemovable()

Motorola has its own library, and for Samsung I can detect the existence of /external_sd/ 摩托罗拉有自己的库,对于三星我可以检测到/external_sd/的存在

I have no clue for the rest of them. 我对其余的人一无所知。 For example, I have seen a /_ExternalSD/ on some LG's but it the directory remains even when the SD is removed. 例如,我在某些LG上看到了/_ExternalSD/ ,但是当删除SD时,目录仍然存在。

A bonus question: will the ACTION_MEDIA_MOUNTED intent be broadcast for any of them 奖金问题: ACTION_MEDIA_MOUNTED意图是否会为其中任何一个广播

Any hint on this would be very helpful. 任何暗示都会非常有帮助。

Here's a class I use to find all sdcards on a device; 这是我用来查找设备上所有sdcards的类; built in and removable. 内置和可拆卸。 I've been using it on Ice Cream Sandwich, but it should work at 2x levels. 我一直在冰淇淋三明治上使用它,但它应该在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;
}

} }

The MyLog.d is a trace class that expands Log.d - it can be dropped. MyLog.d是一个扩展Log.d的跟踪类 - 它可以被删除。

The class reads /proc/mounts/ and: 该类读取/ proc / mounts /和:

  1. checks to see if the path name is the internal sdcard directory 检查路径名是否是内部sdcard目录
  2. checks to see if its a block device 检查它是否是一个块设备
  3. skips mtdblock devices 跳过mtdblock设备
  4. skips anything that is not mounted 跳过任何未安装的东西
  5. skips secure and asec directories 跳过安全和asec目录
  6. makes sure it exists, is a directory, and read/write accessible 确保它存在,是一个目录,并且可读/写访问

If all this is matched, it assumes that you have an sdcard and adds the path to the array list. 如果所有这些都匹配,则假定您有一个SD卡并将路径添加到数组列表中。 It returns a string array of path names. 它返回路径名的字符串数组。

To call the getDirectories function, code something similar to: 要调用getDirectories函数,请执行以下类似的代码:

String[] sdcardDirectories = GetRemoveableDevice.getDirectories();

The paths returned can be used to create a user selection list, scan for a file, or whatever. 返回的路径可用于创建用户选择列表,扫描文件或其他任何内容。

Finally, here's two lines of MyLog.d from an emulator test (second line is the emulator sdcard): 最后,这是来自模拟器测试的两行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 / 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 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

Based on Howards class I made some modifications to make it work on the Galaxy S3. 基于Howards类,我做了一些修改,使其适用于Galaxy S3。

  1. Environment.getExternalStorageDirectory() returns internal storage on the S3. Environment.getExternalStorageDirectory()返回S3上的内部存储。
  2. Removable storage is not necessarily mounted under /mnt 可移动存储不一定安装在/ mnt下
  3. Removable media must have vfat filesystem 可移动媒体必须具有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;
    }

Based on the 2 classes presented above I modified the class further on noticing that all of the external removable storage on several phones and tablets that I could find were mounted using vold, the volume mounting daemon. 基于上面提到的两个类,我进一步修改了类,注意到我可以找到的几个手机和平板电脑上的所有外部可移动存储都是使用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]);

These capabilities are available in all Android versions: 所有Android版本均提供以下功能:

  • To obtain the application's folder on the external storage, call Context.getExternalFilesDir . 要在外部存储上获取应用程序的文件夹,请调用Context.getExternalFilesDir

  • Keep in mind that your app needs explicit permission to access external storage, and that you should check if it is available via Environment.getExternalStorageState 请记住,您的应用需要显式访问外部存储的权限,并且您应该通过Environment.getExternalStorageState检查它是否可用

  • And yes, ACTION_MEDIA_MOUNTED will be broadcast whenever removable media becomes accessible (You should also listen for ACTION_MEDIA_EJECT and ACTION_MEDIA_REMOVED ) 是的,每当可移动媒体变得可访问时, ACTION_MEDIA_MOUNTED将被广播(您还应该收听ACTION_MEDIA_EJECTACTION_MEDIA_REMOVED

This is the method I created and am using. 这是我创建和使用的方法。 This has worked on Samsung Galaxy S4, Samsung Galaxy Note 3 and Sony Xperia Z2. 这适用于三星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.

相关问题 如何在 android 中访问外部存储(可移动 SD 卡)? - How to get access to External Storage (The removable SD Card) in android? 具有NDK API的Android中的可移动存储访问 - Removable Storage Access in Android with NDK API 如何以编程方式在android中识别可移动存储是OTG? - How to identify removable storage is OTG in android programmatically? 在Android中检测可移动外部存储 - Detect removable external storage in Android 如何在可移动存储Android上创建或使用应用专用目录 - How to create or use apps private directory on Removable storage android 如何获得对 Android 中可移动媒体上 DCIM 目录的写访问权限? - How gain write access to DCIM directory on removable media in Android? 如何在android中找到内部(默认手机存储)和外部存储(可移动SD卡)? - How to find Internal(Default Phone Storage ) and External Storage(Removable sd card) in android? 在android中链接和复制外部(可移动存储)文件 - Linking and copying an external (Removable storage) file in android 如何在java中从android的可移动存储(SD卡)获取所有pdf文件的链接? - How to get links to all pdf files from removable storage(SD Card) of android in java? 如何在Android模拟器中模拟真正的外部SD(更新:可移动存储)卡 - how to emulate a real external sd (update: removable storage) card in Android Emulator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM