制造商提供的可移动存储设备(外部)SD卡路径

32

我已经搜索了一番,但是很难找到哪些制造商/型号使用哪个路径来访问sdcard/外部存储。

  • 我不是在说可以通过以下方式找到的内部存储路径:

Environment.getExternalStorageDirectory()

我知道getExternalStorageDirectory()有时会指向某些设备上的外置sdcard。

以下是我发现的一些常见的外部存储路径(不确定哪些制造商使用哪些路径):

/emmc
/mnt/sdcard/external_sd
/mnt/external_sd
/sdcard/sd
/mnt/sdcard/bpemmctest
/mnt/sdcard/_ExternalSD
/mnt/sdcard-ext
/mnt/Removable/MicroSD
/Removable/MicroSD
/mnt/external1
/mnt/extSdCard
/mnt/extsd
/mnt/usb_storage  <-- usb flash mount
/mnt/extSdCard  <-- usb flash mount
/mnt/UsbDriveA  <-- usb flash mount
/mnt/UsbDriveB  <-- usb flash mount

这是我通过谷歌搜索找到的。

我需要扫描整个内部+外部存储+USB闪存驱动器来查找特定文件。如果我漏掉了任何路径,请将其添加到上述列表中。如果有人知道每个制造商使用的路径,请与我们分享。


请注意,getExternalStorageDirectory() 不返回“内部存储”,但它可能返回一个内部存储器,甚至是在内部存储器中实现的虚拟分区,但访问权限与外部存储概念相匹配。至于您的问题,您可以检查/proc/mounts,但请注意,在某些最近的设备上,其他系统可能已经写入的可移动介质的某些部分可能根本无法被应用程序访问。 - Chris Stratton
2
https://github.com/jow-ct/Environment2 代码有点德国风格,但它试图解析 /etc/vold.fstab 文件,该文件包含所有真实的外部存储设备。 - zapl
嗨,zapl,/etc/void.fstab或/etc/void.config是查找外部存储位置的真正好地方。谢谢。然而,Galaxy Nexus没有这两个文件,这很好,因为它没有外部micro-sd插槽。但我担心依赖void.fstab是否对每个设备都稳定。 - jclova
1
@jclova 我正在尝试弄清楚同样的问题,因为你似乎在这个主题上做了更多的研究,你认为Android媒体扫描器能否在这些路径上被调用?在我的情况下,只有提供getExternalStorage()才能让媒体扫描器进行扫描。 - Ahmed
@Ahmed,抱歉我没有研究媒体扫描器的行为。 - jclova
4个回答

13

好消息!在KitKat中,现在有一个公共API可以与这些次要的共享存储设备进行交互。

新的Context.getExternalFilesDirs()Context.getExternalCacheDirs()方法可以返回多个路径,包括主设备和次要设备。然后您可以遍历它们并检查Environment.getStorageState()File.getFreeSpace()来确定存储文件的最佳位置。这些方法也可在支持v4库中的ContextCompat上使用。

还要注意,如果您只对使用Context返回的目录感兴趣,则不再需要READ_WRITE_EXTERNAL_STORAGE权限。从现在开始,您将始终具有对这些目录的读/写访问权限,无需其他权限。

应用程序还可以通过结束其权限请求来继续在旧设备上工作,如下所示:

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />

11

我也从某个地方开始使用像你这样的列表(对不起,找不到原始来源),并继续添加一些从用户反馈中收集到的路径。 有些与上面的列表重复。

    /storage/sdcard1 //!< Motorola Xoom
    /storage/extsdcard  //!< Samsung SGS3
    /storage/sdcard0/external_sdcard  // user request
    /mnt/extsdcard
    /mnt/sdcard/external_sd  //!< Samsung galaxy family
    /mnt/external_sd
    /mnt/media_rw/sdcard1   //!< 4.4.2 on CyanogenMod S3
    /removable/microsd              //!< Asus transformer prime
    /mnt/emmc
    /storage/external_SD            //!< LG
    /storage/ext_sd                 //!< HTC One Max
    /storage/removable/sdcard1      //!< Sony Xperia Z1
    /data/sdext
    /data/sdext2
    /data/sdext3
    /data/sdext4
    /sdcard1                       //Sony Xperia Z
    /sdcard2                       //HTC One M8s
    /storage/microsd               //ASUS ZenFone 2

针对你想要实现的目标(扫描所有可能的路径以查找某些文件),我认为这种方式(使用已知路径列表)几乎是不可能的。甚至在同一设备上,有些路径在 Android 升级后也会发生变化。


谢谢您提供的解决方案,我已将其添加到我的应用程序中。不幸的是,这种行为引起了问题:在升级到Android 4.4.2后,Sony Xperia Z1上的路径/storage/removable/sdcard1变成了只读!更多信息请参见:http://www.androidpolice.com/2014/02/17/external-blues-google-has-brought-big-changes-to-sd-cards-in-kitkat-and-even-samsung-may-be-implementing-them/因此,我将使用Context#getExternalFilesDir()。 - Martin Vysny
1
从4.4版本开始,有“官方”的方法可以获取外部存储目录(通过context.getExternalFilesDirs("external"))。因此,这样的解决方法仅适用于Android的较低版本。 - Jörg Eisfeld
1
@JörgEisfeld 但是 context.getExternalFileDirs 只能获取应用程序特定的路径,而不能获取根目录。 - HendraWD
@JörgEisfeld:有官方方法可以获取外部存储目录,但是OP要求SD卡路径(尽管问题有点混乱)。它们通常不是同一件事。因此,您必须过滤外部存储目录,检查哪些是可移动的。从5.0开始,Environment.isExternalStorageRemovable()可以接受一个目录参数。 - LarsH
@HendraWD:你找到使用那个路径的例子了吗? - LarsH
显示剩余3条评论

0
根据oceanuz提供的路径,我编写了一个方法,它可以定位外部存储路径(忽略大小写)并将其作为字符串返回。
注意:我在我的方法中使用了StreamSupport库,所以为了使其正常工作,您需要下载jar文件并将其添加到项目的libs文件夹中,就这样。
  public static String getExternalSdPath(Context context) {
    List<String> listOfFoldersToSearch = Arrays.asList("/storage/", "/mnt/", "/removable/", "/data/");
    List<String> listOf2DepthFolders = Arrays.asList("sdcard0", "media_rw", "removable");
    List<String> listOfExtFolders = Arrays.asList("sdcard1", "extsdcard", "external_sd", "microsd", "emmc", "ext_sd", "sdext",
            "sdext1", "sdext2", "sdext3", "sdext4");
    final String[] thePath = {""};
    Optional<File> optional = StreamSupport.stream(listOfFoldersToSearch)
            .filter(s -> {
                File folder = new File(s);
                return folder.exists() && folder.isDirectory();
            }) //I got the ones that exist and are directories
            .flatMap(s -> {
                try {
                    List<File> files = Arrays.asList(new File(s).listFiles());
                    return StreamSupport.stream(files);
                } catch (NullPointerException e) {
                    return StreamSupport.stream(Collections.emptyList());
                }
            }) //I got all sub-dirs of the main folders
            .flatMap(file1 -> {
                if (listOf2DepthFolders.contains(file1.getName().toLowerCase())) {
                    try {
                        List<File> files = Arrays.asList(file1.listFiles());
                        return StreamSupport.stream(files);
                    } catch (NullPointerException e) {
                        return StreamSupport.stream(Collections.singletonList(file1));
                    }
                } else
                    return StreamSupport.stream(Collections.singletonList(file1));
            }) //Here I got all the 2 depth and 3 depth folders
            .filter(o -> listOfExtFolders.contains(o.getName().toLowerCase()))
            .findFirst();

    optional.ifPresent(file -> thePath[0] = file.getAbsolutePath());

    Log.i("Path", thePath[0]);

    return thePath[0];
}

如果没有找到SD卡路径,此方法将返回一个空字符串。


0
我试图找到索尼Xperia XA外部SD卡的路径。然后,我安装了ES文件浏览器,它在其特性窗口中清楚地显示了任何文件夹(内部或外部)的路径。我发现外部SD的路径为/storage/C4EE-F3A3。我试图将Python3的输出文件保存到外部SD卡,但它没有权限保存到内部SD卡以外的任何地方。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接