检查SD卡是否存在,布尔值始终为真。

21

在我的启动屏幕中,我想要检查手机是否有SD卡。以下是布尔语句:

    Boolean isSDPresent = android.os.Environment.getExternalStorageState()
            .equals(android.os.Environment.MEDIA_MOUNTED );

如果我在手机上的插槽中放置SD卡,那么这个布尔值将返回true,目前为止一切正常。当我从设置菜单中选择“卸载SD卡”,并移除SD卡后,再杀掉应用程序并重新启动它,布尔值也将是true。

如果我在卸载并移除SD卡后启动,我仍然可以访问路径,为什么?

我该如何实现这一点?

提前致谢!

编辑

使用以下代码进行测试:

File path = Environment.getExternalStorageDirectory(); 
String pathS = path.getPath();

当SD卡插入时,pathS包含mnt/sdcard,但是当我拔掉SD卡后,pathS仍然是/mnt/sdcard...


brianestey的回答可能是正确的。你能记录一下Environment.getExternalStorageDirectory()的输出并让我们知道吗? - Raghav Sood
使用文件管理器进入/mnt目录。列出所有的文件夹。 - Raghav Sood
7个回答

13

我发现像三星的Galaxy手机这样的手机,/mnt/sdcard指向的是内部存储而不是外置SD卡,这与预期的不同。

您可以通过调用Environment.isExternalStorageRemovable()来确定由Environment.getExternalStorageDirectory()返回的路径是否实际为外部SD卡。

只是想从getExternalStorageDirectory()文档中添加这个重要的注释:

  

注意:不要被这里的“外部”一词所迷惑。该目录更好地被视为媒体/共享存储。它是一个可以容纳相对大量数据并跨所有应用程序共享(不强制执行权限)的文件系统。传统上,这是SD卡,但它也可以作为独立于受保护的内部存储的设备上的内置存储器实现,并且可以作为计算机上的文件系统挂载。


我正在三星Galaxy S3上进行测试,这很奇怪。相当奇怪! - Tobias Moe Thorstensen
对于S3,我发现在/mnt/sdcard上有一个名为external_sd的目录,它指向SD卡本身。实际上,我刚刚检查了我的代码,发现S3也可能在路径/mnt/extSdCard中拥有外部SD卡。 - brianestey
在三星设备上,/mnt/sdcard 指向内置的“外部”(不可移除)存储。实际的可移除式外部存储(SD 卡)位于 /mnt/sdcard/external_sd。请参考我的答案来处理它。 - jenzz

2
这句话应该翻译为:“难道不应该是:”
boolean isPresent = Environment.getExternalStorageState().equals(
   Environment.MEDIA_MOUNTED
);

根据文档,Environment.getExternalStorageState()的说明如下:

获取“外部”主存储设备的当前状态

Environment.MEDIA_MOUNTED-constant的说明如下:

getExternalStorageState()返回MEDIA_MOUNTED,如果媒体存在并且已挂载到其挂载点以具有读/写访问权限。

这将适用于API Level 1+。

Galaxy手机具有内部存储器,它用作“外部”存储器。注意:这句话中的“external”在英语中有一定的歧义,但是由于缺少上下文,我无法确定作者的意思。我的翻译保留了原文中的引号以示区别。 - brianestey
@brianestey 这些方法仍然适用。单词“external”对于每个记录的方法都是相对的。我还没有测试过,但应该可以正常工作。 - Lukas Knuth
1
对于Galaxy手机而言,externalStorageState始终处于已挂载状态,因为所谓的“外部”存储实际上是内置在手机中的。 - brianestey
@brianestey 没问题。文档说明这将识别“主要”存储设备。无论它是否已满,都在另一张纸上。 - Lukas Knuth
好的,我同意文档中的内容。但问题与SD卡有关,它并不总是主要的外部存储设备。 - brianestey

2
我修改了代码,如果SD卡存在,则将路径设置在SD卡上,否则将其设置在内部目录中。
    Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
    if(isSDPresent)
    {
      path = theAct.getExternalCacheDir().getAbsolutePath() + "/GrammarFolder";
    }
    else
    {
        path = theAct.getFilesDir() + "/GrammarFolder";
    }

1
我们有两种内存状态,一种是内部存储卡,另一种是外部SD卡。这取决于设备制造商如何制造存储卡路径。因此,如果您正在检查SD卡的可用性,则由于内部存储器,两种情况下都可能返回true。因此,请使用以下方法:
File[] listOfInternalAndExternalStorage=context.getExternalFilesDirs(null); 
   if(listOfInternalAndExternalStorage.length>=2){
     // it contains sd card
   }

以上代码将检查listOfInternalAndExternalStorage是否大于1,如果是,则表示有外部存储器,否则不包含SD卡。

1
如果你想显示SD卡是否插入,只需复制粘贴以下代码即可,该代码适用于所有设备,代码如下:
File file = new File("/mnt/extSdCard");
         try
         {
         File list[] = file.listFiles();
         Toast.makeText(getApplicationContext(), "Yes sdcard is mounted, file count "+list.length, Toast.LENGTH_LONG).show();
         }
         catch(NullPointerException o)
         {
         Toast.makeText(getApplicationContext(), "Sorry no sdcard is mounted:", Toast.LENGTH_LONG).show();
         }

谢谢!这似乎比 Environment.isExternalStorageRemovable() 或检查 Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 更准确。我在一些设备上测试了这三种方法,插入/弹出SD卡。 - cking24343

0

//如果你喜欢保存外部文件,可以尝试这个...

public  String preferextstorage(Context con){
    int version = Build.VERSION.SDK_INT;
    String result=con.getFilesDir().getPath();
    if (version>=19) {
    File[] listOfInternalAndExternalStorage = con.getExternalFilesDirs(null);
    if (listOfInternalAndExternalStorage.length >= 2) {
            // it contains sd card
            if (listOfInternalAndExternalStorage[1]==null){
                result=listOfInternalAndExternalStorage[0].getPath();
            }else
            {
                result=listOfInternalAndExternalStorage[1].getPath();
            }
            return result;
        }
    }
    return result;
}

-2

这段代码片段可能对您检测和处理三星设备的异常有所帮助:

public static String getExternalStorage() {

    String str = Environment.getExternalStorageDirectory().getAbsolutePath();
    if ( isSamsungDevice() ) {
        if ( isSamsungExternalSDMounted() ) {
            str += "/external_sd";
        }
    }
    return str;
}

private static boolean isSamsungDevice() {

    return new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/external_sd" ).exists();
}

private static boolean isSamsungExternalSDMounted() {

    return exec( "mount" ).indexOf( "external_sd" ) >= 0;
}

public static String exec( String paramString ) {

    try {
        String str = "";
        InputStream localInputStream = Runtime.getRuntime().exec( paramString ).getInputStream();
        byte[] arrayOfByte = new byte[1024];
        StringBuilder localStringBuilder = new StringBuilder();
        while ( true ) {

            int i = localInputStream.read( arrayOfByte, 0, arrayOfByte.length );
            if ( i == -1 ) {
                str = localStringBuilder.toString();
                break;
            }

            localStringBuilder.append( new String( arrayOfByte, 0, i ) );
        }

        return str;
    } catch ( IOException e ) {
        e.printStackTrace();
        return null;
    }
}

2
很不幸,这对于最新的手机不起作用,因为它们没有外部SD卡,而是有ExtSdCard。 - Waypoint

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