【问题标题】:How to get access to External Storage (The removable SD Card) in android?如何在 android 中访问外部存储(可移动 SD 卡)?
【发布时间】:2017-01-15 11:07:14
【问题描述】:

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

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

【问题讨论】:

  • 分享这个以帮助其他想要获得外部SD卡路径的人
  • 您的问题应该包含合并的代码。您的问题是“替代方法是什么”。此外,您需要清单权限
  • @cricket_007 我忘了在答案中添加清单权限。我将合并的代码放在答案中,因为它可以工作,因为 StackOverFlow 可以选择回答您自己的问题,我认为这是最好的。
  • 当然,您下面的第一个链接答案是针对棉花糖的,无论如何,不​​是奇巧。 Marshmallow 需要运行时权限检查
  • @cricket_007 我给出这个解决方案只是为了获取外部存储的路径,任何将使用该解决方案的人都应该事先检查权限:)

标签: android file storage


【解决方案1】:

这两个答案是我为了让它工作而合并的。

  1. How to get SD_Card path in android6.0 programmatically

  2. Find an external SD card location

解决办法,

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

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

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

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;

}
}

现在使用这个类,

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 现在包含存储路径。

【讨论】:

  • 如果你真的要投反对票,那么至少评论一下为什么会这样:) 你遇到了什么问题?答案有什么问题?也许那时我可以改进缺少的东西
猜你喜欢
  • 2018-04-17
  • 2015-08-30
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-20
相关资源
最近更新 更多