有没有一种通用的方法来找到外置SD卡的位置?

请不要与外部存储混淆。

Environment.getExternalStorageState()返回内部SD挂载点的路径,例如/mnt/sdcard。但问题是关于外部SD的。我如何获得类似/mnt/sdcard/external_sd的路径(它可能因设备而异)?

我想我将以根据文件系统名称过滤mount命令的输出作为结束。但我不确定这种方式是否足够稳健。


当前回答

我不知道为什么,但我需要在使用它之前在公共存储目录中创建的文件上调用. createnewfile()。在框架中,该方法的注释说它没有用。这是一个样本……

String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS) + File. txt文件。separator +“我的目录”; final File myDir = new File(myypath); 尝试{ myDir.mkdirs (); } catch(异常ex) { 吐司。makeText(this, "error: " + ex.getMessage(), Toast.LENGTH_LONG).show(); }

        String fname = "whatever";
        File newFile = new File(myDir, fname);

        Log.i(TAG, "File exists --> " + newFile.exists()) //will be false  
    try {
            if (newFile.createNewFile()) {

                 //continue 

              } else {

                Log.e(TAG, "error creating file");

            }

        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

其他回答

有没有一种通用的方法来找到外置SD卡的位置?

通用方式,如果你指的是官方方式;是的,有一个。

在API级别19中,即在Android版本4.4 Kitkat中,他们在上下文类中添加了File[] getExternalFilesDirs(字符串类型),允许应用程序在micro SD卡中存储数据/文件。

Android 4.4是第一个允许应用程序使用SD卡存储的平台。API级别19之前对SD卡的任何访问都是通过私有的、不受支持的API。

getExternalFilesDirs(String类型)返回所有共享/外部存储设备上特定于应用程序目录的绝对路径。这意味着,它将返回内部和外部内存的路径。通常,第二个返回路径将是microSD卡的存储路径(如果有的话)。

但请注意,

共享存储可能并不总是可用的,因为可移动媒体可以 被用户弹出。媒体状态可以检查使用 getExternalStorageState(文件)。 这些文件没有安全措施。例如,任何 持有WRITE_EXTERNAL_STORAGE的应用程序可以写入这些文件。

根据谷歌/官方Android文档,内部和外部存储术语与我们想象的大不相同。

如果你看一下Android .os. environment的源代码,你会发现Android非常依赖环境变量作为路径。您可以使用“SECONDARY_STORAGE”环境变量来查找到可移动sd卡的路径。

/**
 * Get a file using an environmental variable.
 *
 * @param variableName
 *         The Environment variable name.
 * @param paths
 *         Any paths to the file if the Environment variable was not found.
 * @return the File or {@code null} if the File could not be located.
 */
private static File getDirectory(String variableName, String... paths) {
    String path = System.getenv(variableName);
    if (!TextUtils.isEmpty(path)) {
        if (path.contains(":")) {
            for (String _path : path.split(":")) {
                File file = new File(_path);
                if (file.exists()) {
                    return file;
                }
            }
        } else {
            File file = new File(path);
            if (file.exists()) {
                return file;
            }
        }
    }
    if (paths != null && paths.length > 0) {
        for (String _path : paths) {
            File file = new File(_path);
            if (file.exists()) {
                return file;
            }
        }
    }
    return null;
}

使用示例:

public static final File REMOVABLE_STORAGE = getDirectory("SECONDARY_STORAGE");

/sdcard =>内部存储(这是一个符号链接,但应该工作)

/mnt/extSdCard =>外部sd卡

这是三星Galaxy S3

你可以相信这对大多数人来说都是真的……但是要仔细检查!

这次我尝试了这个主题内的所有解决方案。但是,在有一个外置卡(可移动)和一个内置卡(不可移动)的设备上,所有这些设备都不能正常工作。外部卡的路径不可能从'mount'命令,从'proc/mounts'文件等。

我在Paulo Luan的基础上提出了自己的解决方案:

String sSDpath = null;
File   fileCur = null;
for( String sPathCur : Arrays.asList( "ext_card", "external_sd", "ext_sd", "external", "extSdCard",  "externalSdCard")) // external sdcard
{
   fileCur = new File( "/mnt/", sPathCur);
   if( fileCur.isDirectory() && fileCur.canWrite())
   {
     sSDpath = fileCur.getAbsolutePath();
     break;
   }
}
fileCur = null;
if( sSDpath == null)  sSDpath = Environment.getExternalStorageDirectory().getAbsolutePath();

为了检索所有外部存储(无论是SD卡还是内部不可移动存储),您可以使用以下代码:

final String state = Environment.getExternalStorageState();

if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) {  // we can read the External Storage...           
    //Retrieve the primary External Storage:
    final File primaryExternalStorage = Environment.getExternalStorageDirectory();

    //Retrieve the External Storages root directory:
    final String externalStorageRootDir;
    if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) {  // no parent...
        Log.d(TAG, "External Storage: " + primaryExternalStorage + "\n");
    }
    else {
        final File externalStorageRoot = new File( externalStorageRootDir );
        final File[] files = externalStorageRoot.listFiles();

        for ( final File file : files ) {
            if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) {  // it is a real directory (not a USB drive)...
                Log.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n");
            }
        }
    }
}

或者,您可以使用System.getenv("EXTERNAL_STORAGE")来检索主要的外部存储目录(例如:"/storage/sdcard0")和System.getenv("SECONDARY_STORAGE")来检索所有从目录的列表(例如:“/存储/ extSdCard: /存储/ UsbDriveA: /存储/ UsbDriveB”)。记住,同样在这种情况下,您可能想要过滤从目录列表以排除USB驱动器。

在任何情况下,请注意使用硬编码路径总是一种糟糕的方法(特别是当每个制造商都可以随心所欲地更改它时)。