20

大多数新的 android 设备都有一个内部 sdcard 和一个外部 sdcard。我想制作一个文件资源管理器应用程序,但我不知道如何获取在我的应用程序中使用的路径,因为

File file = Environment.getExternalStorageDirectory();

只是在大多数设备中返回,/mnt/sdcard 但其他外部 SD 卡还有另一条路径,例如/storage1 or /storage2 . 任何帮助表示赞赏。

4

9 回答 9

12

如何在android中获取内部和外部sdcard路径

存储在内部存储中的方法:

File getDir (String name, int mode)

File getFilesDir () 

以上方法存在于Context类中

存储在手机内存中的方法:

File getExternalStorageDirectory ()

File getExternalFilesDir (String type)

File getExternalStoragePublicDirectory (String type)

一开始大家都用Environment.getExternalStorageDirectory(),指向手机内存的根。结果,根目录充满了随机内容。

后来又增加了这两个方法:

Context课堂上,他们添加了getExternalFilesDir(),指向手机内存中的特定应用目录。卸载应用程序时,该目录及其内容将被删除。

Environment.getExternalStoragePublicDirectory()用于存储知名文件类型(如照片和电影)的集中位置。卸载应用程序时,该目录及其内容不会被删除。

存储在可移动存储(即微型 SD 卡)中的方法

在 API 级别 19 之前,没有官方的方式存储在 SD 卡中。但是许多人可以使用非官方的 API 来做到这一点。

正式地,在API 级别 19(Android 版本 4.4 - Kitkat)的Context类中引入了一种方法。

File[] getExternalFilesDirs (String type)

它返回所有共享/外部存储设备上应用程序特定目录的绝对路径,应用程序可以在其中放置其拥有的持久文件。这些文件是应用程序内部的,通常不会作为媒体对用户可见。

这意味着,它将返回到 Micro SD 卡和内部存储器的路径。通常,第二个返回路径是 micro SD 卡的存储路径。

根据 Google/官方 Android 文档的内部和外部存储术语与我们的想法有很大不同。

于 2016-08-04T06:34:13.847 回答
2

是的。不同的制造商使用不同的 SD 卡名称,如三星 Tab 3 它的 extsd,而其他三星设备使用不同的 SD 卡,不同的制造商使用不同的名称。

我和你有同样的要求。所以我从我的项目中为您创建了一个示例示例转到此链接Android 目录选择器示例,该示例使用 android-dirchooser 库。此示例检测 SD 卡并列出所有子文件夹,它还检测设备是否有多个 SD 卡。

部分代码如下所示完整示例转到链接Android 目录选择器

/**
* Returns the path to internal storage ex:- /storage/emulated/0
 *
* @return
 */
private String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
 }

/**
 * Returns the SDcard storage path for samsung ex:- /storage/extSdCard
 *
 * @return
 */
    private String getSDcardDirectoryPath() {
    return System.getenv("SECONDARY_STORAGE");
}


 mSdcardLayout.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        String sdCardPath;
        /***
         * Null check because user may click on already selected buton before selecting the folder
         * And mSelectedDir may contain some wrong path like when user confirm dialog and swith back again
         */

        if (mSelectedDir != null && !mSelectedDir.getAbsolutePath().contains(System.getenv("SECONDARY_STORAGE"))) {
            mCurrentInternalPath = mSelectedDir.getAbsolutePath();
        } else {
            mCurrentInternalPath = getInternalDirectoryPath();
        }
        if (mCurrentSDcardPath != null) {
            sdCardPath = mCurrentSDcardPath;
        } else {
            sdCardPath = getSDcardDirectoryPath();
        }
        //When there is only one SDcard
        if (sdCardPath != null) {
            if (!sdCardPath.contains(":")) {
                updateButtonColor(STORAGE_EXTERNAL);
                File dir = new File(sdCardPath);
                changeDirectory(dir);
            } else if (sdCardPath.contains(":")) {
                //Multiple Sdcards show root folder and remove the Internal storage from that.
                updateButtonColor(STORAGE_EXTERNAL);
                File dir = new File("/storage");
                changeDirectory(dir);
            }
        } else {
            //In some unknown scenario at least we can list the root folder
            updateButtonColor(STORAGE_EXTERNAL);
            File dir = new File("/storage");
            changeDirectory(dir);
        }


    }
});
于 2014-09-06T07:29:09.640 回答
1

由于没有直接获取路径的方法,解决方案可能是扫描 /system/etc/vold.fstab 文件并查找如下行:dev_mount sdcard /mnt/sdcard 1 /devices/platform/s3c-sdhci.0/ mmc_host/mmc0

找到一个后,将其拆分为其元素,然后拉出该挂载点的路径并将其添加到 arraylist

强调文本一些设备完全缺少vold文件,所以我们在这里添加一个路径以确保列表始终包含第一个sdcard的路径,无论是真实的还是模拟的。

    sVold.add("/mnt/sdcard");

    try {
        Scanner scanner = new Scanner(new File("/system/etc/vold.fstab"));
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
            if (line.startsWith("dev_mount")) {
                String[] lineElements = line.split(" ");
                String element = lineElements[2];

                if (element.contains(":"))
                    element = element.substring(0, element.indexOf(":"));

                if (element.contains("usb"))
                    continue;

                // don't add the default vold path
                // it's already in the list.
                if (!sVold.contains(element))
                    sVold.add(element);
            }
        }
    } catch (Exception e) {
        // swallow - don't care
        e.printStackTrace();
    }
}

现在我们已经有了一个干净的挂载路径列表,测试每个路径以确保它是有效且可用的路径。如果不是,请将其从列表中删除。

private static void testAndCleanList() 
{
    for (int i = 0; i < sVold.size(); i++) {
        String voldPath = sVold.get(i);
        File path = new File(voldPath);
        if (!path.exists() || !path.isDirectory() || !path.canWrite())
            sVold.remove(i--);
    }
}
于 2014-08-18T12:50:31.670 回答
1

我不确定这个答案有多普遍,但我在装有 Android 4.4 的摩托罗拉 XT830C 和 Nexus 7 android 6.0.1 上对其进行了测试。在三星 SM-T530NU Android 5.0.2 上。我用System.getenv("SECONDARY_STORAGE")Environment.getExternalStorageDirectory().getAbsolutePath()
没有第二张 SD 卡的 NexusSystem.getenv返回 null 并Envirnoment.getExterna...给出 /storage/emulated/0。
具有外部 SD 卡的摩托罗拉设备为 /storage/sdcard1System.getenv("SECONDARY_STORAGE")提供Envirnoment.getExterna.../storage/emulated/0。
samsumg 为外部 SD 返回 /storage/extSdCard。
就我而言,我正在外部位置创建一个子目录并使用

 appDirectory = (System.getenv("SECONDARY_STORAGE") == null)
       ? Environment.getExternalStorageDirectory().getAbsolutePath()
       : System.getenv("SECONDARY_STORAGE");

找到SD卡。在这个目录中创建一个子目录是有效的。
当然,我必须在清单文件中设置访问外部存储器的权限。
我还有一个 Nook 8" 彩色平板电脑。当我有机会对其进行测试时,如果我对这种方法有任何问题,我会发布。

于 2016-06-19T06:21:33.113 回答
0

但其他外部 sdcard 有另一条路径,如 /storage1 或 /storage2

Android SDK 中没有任何东西——至少通过 Android 4.1——可以让您访问这些路径。无论如何,您的应用程序可能无法读取或写入它们。此类存储位置的行为及其用途取决于设备制造商。

于 2012-11-13T13:04:28.437 回答
0

对于所有 Android 版本,

权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />

使用 Android 10 的 requestLegacyExternalStorage(添加到 AndroidManifest > application 标签):

android:requestLegacyExternalStorage="true"

获取内部目录路径:

@Nullable
public static String getInternalStorageDirectoryPath(Context context) {
    String storageDirectoryPath;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        if(storageManager == null) {
            storageDirectoryPath = null; //you can replace it with the Environment.getExternalStorageDirectory().getAbsolutePath()
        } else {
            storageDirectoryPath = storageManager.getPrimaryStorageVolume().getDirectory().getAbsolutePath();
        }
    } else {
        storageDirectoryPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    }

    return storageDirectoryPath;
}

获取外部目录:

@NonNull
public static List<String> getExternalStorageDirectoryPaths(Context context) {
    List<String> externalPaths = new ArrayList<>();
    String internalStoragePath = getInternalStorageDirectoryPath(context);

    File[] allExternalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
    for(File filesDir : allExternalFilesDirs) {
        if(filesDir != null) {
            int nameSubPos = filesDir.getAbsolutePath().lastIndexOf("/Android/data");
            if(nameSubPos > 0) {
                String filesDirName = filesDir.getAbsolutePath().substring(0, nameSubPos);
                if(!filesDirName.equals(internalStoragePath)) {
                    externalPaths.add(filesDirName);
                }
            }
        }
    }

    return externalPaths;
}
于 2022-01-27T13:05:20.237 回答
0
File main=new File(String.valueOf(Environment.getExternalStorageDirectory().getAbsolutePath()));
File[]t=main.getParentFile().listFiles();

for(File dir:t)
{
    Log.e("Main",dir.getAbsolutePath());
}

输出:

E/Main: /storage/sdcard1
E/Main: /storage/sdcard0

我有一张 SD 卡和内置内存。

于 2017-09-08T03:54:34.753 回答
-1

试试这个代码,它会有所帮助

Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File sdCard = externalLocations.get(ExternalStorage.SD_CARD);
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
于 2014-08-18T05:33:13.357 回答
-1

没有用于获取内部/外部 sdcard 路径的公共 api。

但是在 android.os.storage 包中有一个叫做 StorageManager 的平台 api。见http://goo.gl/QJj1eu

有列表存储、挂载/卸载存储、获取挂载状态、获取存储路径等功能。

但它是隐藏的 api,它应该在下一个 android 版本中被弃用或破坏。

并且有些方法需要特别许可,而且大多数都没有记录在案。

于 2014-07-08T00:47:53.803 回答