21

In my splash screen, I want to check if the phone has a SDCard. The Boolean statement is beneath:

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

So, if I have the SDCard in the slot on my phone, this boolean will return true, so far so good. When I go to the "Unmount SDCard" from the settings menu, and removes the SDCard, then kill the app and launching it again, the boolean will also be true..

And if I launches the Astro File Manager after unmounting and removing the sdcard, I can still access the /mnt/sdcard path, why?

How can I manage to accomplish this?

Thanks in advance!

EDIT

Testing with the following code:

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

When the SDCard is in the slot, the pathS contains mnt/sdcard, but when I removes the SDCard the pathS is still /mnt/sdcard ...

Coral Doe
  • 1,925
  • 3
  • 19
  • 36
Tobias Moe Thorstensen
  • 8,861
  • 16
  • 75
  • 143

7 Answers7

13

I've found that phones, like the Galaxy phones from Samsung, have /mnt/sdcard point to internal memory and not the external SD card as expected.

You can know if the path returned by Environment.getExternalStorageDirectory() is actually the external SD card with a call to Environment.isExternalStorageRemovable()

Just wanted to add from the docs for getExternalStorageDirectory() this important note:

Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). Traditionally this is an SD card, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer.

brianestey
  • 8,202
  • 5
  • 33
  • 48
  • I am testing this on a Samsung Galaxy S3, this is wierd. Pretty weird! – Tobias Moe Thorstensen Aug 23 '12 at 08:23
  • For S3, I have found that there is a directory called `external_sd` on /mnt/sdcard which points to the SD card itself. Actually, I just checked my code and S3 might also have the external sd in the path `/mnt/extSdCard`. – brianestey Aug 23 '12 at 08:24
  • On Samsung devices `/mnt/sdcard` points to the built-in 'external' (non-removable) storage. The actual removable external storage (SD-Card) is located at `/mnt/sdcard/external_sd`. See my answer for how to deal with it. – jenzz Aug 23 '12 at 08:59
2

Shouldn't it be:

boolean isPresent = Environment.getExternalStorageState().equals(
   Environment.MEDIA_MOUNTED
);

As the documentation states for Environment.getExternalStorageState():

Gets the current state of the primary "external" storage device.

And for the Environment.MEDIA_MOUNTED-constant:

getExternalStorageState() returns MEDIA_MOUNTED if the media is present and mounted at its mount point with read/write access.

And this will work from API Level 1+

Lukas Knuth
  • 25,449
  • 15
  • 83
  • 111
  • See the note in my answer. Galaxy phones have internal memory that it uses as the "external" storage. – brianestey Aug 23 '12 at 08:33
  • @brianestey the methods should still apply the same. The word "external" is relative for every of the documented methods. I haven't tested it but it should work just fine. – Lukas Knuth Aug 23 '12 at 08:34
  • 1
    For Galaxy phones, the externalStorageState is always mounted because what is referred to as "external" is actually built into the phone. – brianestey Aug 23 '12 at 08:36
  • @brianestey that's fine. The documentation states that this will identify the "primary" storage device. Weather it's full or not is on another piece of paper. – Lukas Knuth Aug 23 '12 at 08:41
  • Ok, I agree with the docs. But the question was related to the SD card, which is not always the primary external storage device. – brianestey Aug 23 '12 at 08:50
2

I modificated that if sd card exists, sets the path there if not sets it at the internal directory

    Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
    if(isSDPresent)
    {
      path = theAct.getExternalCacheDir().getAbsolutePath() + "/GrammarFolder";
    }
    else
    {
        path = theAct.getFilesDir() + "/GrammarFolder";
    }
ArdaA
  • 137
  • 5
1

If you want to show whether sdcard is inserted or not then just copy-paste this code its working 100% for all Devices, code is here:

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();
         }
Pir Fahim Shah
  • 10,505
  • 1
  • 82
  • 81
  • Thanks! This seems to be more accurate than the **Environment.isExternalStorageRemovable()** OR checking the **Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)**. I tested all three of these methods on some devices while inserting/ejecting and SDCard. – cking24343 Jan 04 '17 at 14:32
1

We have two memory status. One is Internal memory card and other is external sd card. It depends upon device manufactures how they have manufactured the memory card path. So if you are checking for sd card availability then it may return true in both cases due to internal memory. So go for this method:

File[] listOfInternalAndExternalStorage=context.getExternalFilesDirs(null); 
   if(listOfInternalAndExternalStorage.length>=2){
     // it contains sd card
   }

above code will check if listOfInternalAndExternalStorage is more than one then it has external storage, otherwise it does not contain sd card.

Kundan
  • 99
  • 2
  • 4
0

//Try this if you prefer to save external...

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

This code snippet might be of use for you to detect and deal with the exception of Samsung devices:

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;
    }
}
jenzz
  • 7,239
  • 6
  • 49
  • 69
  • 2
    This unfortunately is not working for newest phones, because they doesn't have external_sd but ExtSdCard – Waypoint Oct 22 '12 at 05:57