如何在 android 中访问外部存储(可移动 SD 卡)?

How to get access to External Storage (The removable SD Card) in android?

我一直在尝试访问 android 中的内部和外部 SD 卡。我尝试了 Whosebug 中可用的许多代码,但不适用于大多数或所有 Android 版本。然后,我找到了两个解决方案。一种适用于 Kitkat 及更高版本,另一种适用于低于 Kitkat 的版本。我试图合并它们并且它有效!

如果有人有比这更好的解决方案,请分享。

我合并了这两个答案以使其正常工作。

  1. Find an external SD card location

这是解决方案,

AndroidManifest.xml中添加这行代码以获得Android读取外部存储的权限。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

现在,将此 class 添加到您的项目中。

public class StoragePath {
File[] getExternalFilesDirs;

/**
 * Constructor for KitKat & above
 * @param getExternalFilesDirs
 */
public StoragePath(File[] getExternalFilesDirs) {
    this.getExternalFilesDirs = getExternalFilesDirs;
}

/**
 * Constructor for lower than Kitkat
 *
 */
public StoragePath() {

}

public String[] getDeviceStorages() {
    List<String> results = new ArrayList<>();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //Method 1 for KitKat & above
        File[] externalDirs = getExternalFilesDirs;

        for (File file : externalDirs) {
            String path = file.getPath().split("/Android")[0];

            boolean addPath = false;

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                addPath = Environment.isExternalStorageRemovable(file);
            } else {
                addPath = Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(file));
            }

            if (addPath) {
                results.add(path);
            }
        }
    }

    if (results.isEmpty()) { //Method 2 for all versions
        final List<String> out = new ArrayList<>();
        String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
        String s = "";
        try {
            final Process process = new ProcessBuilder().command("mount")
                    .redirectErrorStream(true).start();
            process.waitFor();
            final InputStream is = process.getInputStream();
            final byte[] buffer = new byte[1024];
            while (is.read(buffer) != -1) {
                s = s + new String(buffer);
            }
            is.close();
        } catch (final Exception e) {
            e.printStackTrace();
        }

        // parse output
        final String[] lines = s.split("\n");
        for (String line : lines) {
            if (!line.toLowerCase(Locale.US).contains("asec")) {
                if (line.matches(reg)) {
                    String[] parts = line.split(" ");
                    for (String part : parts) {
                        if (part.startsWith("/"))
                            if (!part.toLowerCase(Locale.US).contains("vold"))
                                out.add(part);
                    }
                }
            }
        }
        results.addAll(out);
    }

    //Below few lines is to remove paths which may not be external memory card, like OTG (feel free to comment them out)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        for (int i = 0; i < results.size(); i++) {
            if (!results.get(i).toLowerCase().matches(".*[0-9a-f]{4}[-][0-9a-f]{4}")) {
                Log.d("Tag", results.get(i) + " might not be extSDcard");
                results.remove(i--);
            }
        }
    } else {
        for (int i = 0; i < results.size(); i++) {
            if (!results.get(i).toLowerCase().contains("ext") && !results.get(i).toLowerCase().contains("sdcard")) {
                Log.d("Tag", results.get(i) + " might not be extSDcard");
                results.remove(i--);
            }
        }
    }

    //Get path to the Internal Storage aka ExternalStorageDirectory
    final String internalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
    results.add(0, internalStoragePath);

    String[] storageDirectories = new String[results.size()];
    for (int i = 0; i < results.size(); ++i) storageDirectories[i] = results.get(i);

    return storageDirectories;

}
}

现在使用这个 class,

StoragePath storagePath;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        storagePath = new StoragePath(getExternalFilesDirs(null));
}else {
        storagePath = new StoragePath();
}

String[] storages;
storages = storagePath.getDeviceStorages();

字符串数组 storages 现在包含存储的路径。