58

My app is working for mobiles which have an SD card only. So programmatically I want to check if the SD card is available or not and how to find the SD card free space. Is it possible?

If yes, how do I do it?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
naresh
  • 10,332
  • 25
  • 81
  • 124
  • What does "SD card only" mean? Do you mean it has no internal memory? That's hard to imagine. – LarsH Nov 16 '18 at 08:58

12 Answers12

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

if(isSDSupportedDevice && isSDPresent)
{
  // yes SD-card is present
}
else
{
 // Sorry
}
Zubair Soomro
  • 180
  • 1
  • 12
Paresh Mayani
  • 127,700
  • 71
  • 241
  • 295
  • 3
    how to check the sdcard free memory? – naresh Sep 15 '11 at 10:26
  • 49
    but it return true if phone has inbuild storage..so not the correct answer – User10001 Mar 15 '14 at 21:05
  • 2
    On modern Android devices, external storage (known as "sdcard") can now be also internal storage, just separate. So yes, it is a good answer. – shkschneider Jan 26 '15 at 17:21
  • Also it's a good idea to check not only Environment.MEDIA_MOUNTED, but also Environment.MEDIA_MOUNTED_READ_ONLY – nickeyzzz Apr 03 '15 at 11:42
  • 22
    To determine if external storage is a SDCARD use the above in conjunction with: Environment.isExternalStorageRemovable() – user608578 Apr 30 '15 at 16:30
  • "External storage" is not necessarily an SD card. On many devices - most devices that I have seen recently - there is emulated "external" storage that is not an SD card (at least not a removable one). So this will give you a wrong answer. See http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory() "Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. ... it may also be implemented as built-in storage ..." – LarsH Jul 16 '15 at 15:27
  • 2
    This returns true for a device that has no SD card and only internal memory. – Tom Kincaid Oct 19 '16 at 16:48
  • check this if phone has inbuild storage http://stackoverflow.com/a/40282882/3758898 – Kishan Vaghela Oct 28 '16 at 10:06
  • 3
    This is clearly a wrong answer in case of emulated external storage. Ideally Environment.isExternalStorageRemovable() should be used. You can also see Environment.isExternalStorageEmulated(). @naresh you should not accept a partial answer. – atuljangra Nov 30 '16 at 21:28
  • even though emulator has a SD card available on it in android studio, this test condition didn't return true. – Brainwash Jul 08 '21 at 11:58
  • 1
    on samsung glaxy a52, after inserting sd card isSDPresent return true, but isSDSupportedDevice return false. – Abdur Rehman Nov 18 '21 at 04:46
24

Accepted answer doesn't work for me

Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

In case if device has a built-in storage, it returns true; My solution is that to check the external files directory count, if there is more than one, device has sdcard. It works and I tested it for several devices.

public static boolean hasRealRemovableSdCard(Context context) {
    return ContextCompat.getExternalFilesDirs(context, null).length >= 2;
}
Jemo Mgebrishvili
  • 5,187
  • 7
  • 38
  • 63
16

You can check if external removable sd card is available like this

public static boolean externalMemoryAvailable(Activity context) {
    File[] storages = ContextCompat.getExternalFilesDirs(context, null);
    if (storages.length > 1 && storages[0] != null && storages[1] != null)
        return true;
    else
        return false;

}

This works perfectly as i have tested it.

Jaura
  • 487
  • 5
  • 12
  • I have tested it on Samsung A70s, with and without an external(removable) SD card, and in both cases, it's working fine. I have tried all the suggested solutions by others but this one worked correctly. Hopefully will work also for all devices. Thank you very much. – Shailesh Sep 21 '20 at 14:59
15

Use Environment.getExternalStorageState() as described in "Using the External Storage".

To get available space on external storage, use StatFs:

// do this only *after* you have checked external storage state:
File extdir = Environment.getExternalStorageDirectory();
File stats = new StatFs(extdir.getAbsolutePath());
int availableBytes = stats.getAvailableBlocks() * stats.getBlockSize();
Philipp Reichart
  • 20,771
  • 6
  • 58
  • 65
5

I wrote a little class for that checking the storage state. Maybe it's of some use for you.

import android.os.Environment;

/**
 * Checks the state of the external storage of the device.
 * 
 * @author kaolick
 */
public class StorageHelper
{
// Storage states
private boolean externalStorageAvailable, externalStorageWriteable;

/**
 * Checks the external storage's state and saves it in member attributes.
 */
private void checkStorage()
{
// Get the external storage's state
String state = Environment.getExternalStorageState();

if (state.equals(Environment.MEDIA_MOUNTED))
{
    // Storage is available and writeable
    externalStorageAvailable = externalStorageWriteable = true;
}
else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY))
{
    // Storage is only readable
    externalStorageAvailable = true;
    externalStorageWriteable = false;
}
else
{
    // Storage is neither readable nor writeable
    externalStorageAvailable = externalStorageWriteable = false;
}
}

/**
 * Checks the state of the external storage.
 * 
 * @return True if the external storage is available, false otherwise.
 */
public boolean isExternalStorageAvailable()
{
checkStorage();

return externalStorageAvailable;
}

/**
 * Checks the state of the external storage.
 * 
 * @return True if the external storage is writeable, false otherwise.
 */
public boolean isExternalStorageWriteable()
{
checkStorage();

return externalStorageWriteable;
}

/**
 * Checks the state of the external storage.
 * 
 * @return True if the external storage is available and writeable, false
 *         otherwise.
 */    
public boolean isExternalStorageAvailableAndWriteable()
{
checkStorage();

if (!externalStorageAvailable)
{
    return false;
}
else if (!externalStorageWriteable)
{
    return false;
}
else
{
    return true;
}
}
}
kaolick
  • 4,817
  • 5
  • 42
  • 53
  • does this calss helps detect sd card availability ? – Pankaj Nimgade Aug 03 '15 at 08:53
  • @PankajNimgade This class helps you to check if external storage is available and/or writable. External storage can be an SD-card or built-in storage like in the nexus devices. – kaolick Aug 03 '15 at 09:03
  • is it possible to check specifically for the "sdcard" ?, Thanks in advance – Pankaj Nimgade Aug 03 '15 at 10:08
  • @PankajNimgade Not that I know of. I would recommend to read about Internal and External storage here: https://developer.android.com/guide/topics/data/data-storage.html – kaolick Aug 03 '15 at 10:17
  • been through that and several other documents, there is no specific difference made by google on "external storage available on device" and "sd card"....... :( – Pankaj Nimgade Aug 03 '15 at 10:37
4

I modified it such that if an SD card exists, it sets the path there. If not, it 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";
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ArdaA
  • 137
  • 5
3
 void updateExternalStorageState() {
     String state = Environment.getExternalStorageState();
     if (Environment.MEDIA_MOUNTED.equals(state)) {
        mExternalStorageAvailable = mExternalStorageWriteable = true;
     } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        mExternalStorageAvailable = true;
       mExternalStorageWriteable = false;
     } else {
       mExternalStorageAvailable = mExternalStorageWriteable = false;
}
handleExternalStorageState(mExternalStorageAvailable,
        mExternalStorageWriteable);
}
Umesh
  • 4,406
  • 2
  • 25
  • 37
2

This simple method is worked for me. Tested in all type of devices.

public boolean externalMemoryAvailable() {
    if (Environment.isExternalStorageRemovable()) {
      //device support sd card. We need to check sd card availability.
      String state = Environment.getExternalStorageState();
      return state.equals(Environment.MEDIA_MOUNTED) || state.equals(
          Environment.MEDIA_MOUNTED_READ_ONLY);
    } else {
      //device not support sd card. 
      return false;
    }
  }
Kishan Vaghela
  • 7,678
  • 5
  • 42
  • 67
2

Kotlin

fun Context.externalMemoryAvailable(): Boolean {
    val storages = ContextCompat.getExternalFilesDirs(this, null)
    return storages.size > 1 && storages[0] != null && storages[1] != null
}
SK Panchal
  • 47
  • 11
1
  public static boolean hasSdCard(Context context) {

    File[] dirs = context.getExternalFilesDirs("");        
    if(dirs.length >= 2 && dirs[1]!=null){
        if(Environment.isExternalStorageRemovable(dirs[1])){ // Extra Check
            return true;
        }
     }
    return false;
   }
Ashish Tyagi
  • 81
  • 1
  • 5
0

I created a class to check if the folder on the SD card is available or not:

public class GetFolderPath {

    static String folderPath;

    public static String getFolderPath(Context context) {
        if (isSdPresent() == true) {
            try {
                File sdPath = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/FolderName");
                if(!sdPath.exists()) {
                    sdPath.mkdirs();
                    folderPath = sdPath.getAbsolutePath();
                } else if (sdPath.exists()) {
                    folderPath = sdPath.getAbsolutePath();
                }
            }
            catch (Exception e) {

            }
            folderPath = Environment.getExternalStorageDirectory().getPath()+"/FolderName/";
        }
        else {
            try {
                File cacheDir=new File(context.getCacheDir(),"FolderName/");
                if(!cacheDir.exists()) {
                    cacheDir.mkdirs();
                    folderPath = cacheDir.getAbsolutePath();
                } else if (cacheDir.exists()) {
                    folderPath = cacheDir.getAbsolutePath();
                }
            }
            catch (Exception e){

            }
        }
        return folderPath;
    }

    public static boolean isSdPresent() {
        return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
UchihaSasuke
  • 363
  • 2
  • 23
0
** i fixed this with help of @Jemo Mgebrishvili answer** 

this works perfectly even if sd card is present and in the ejected state

 if (ContextCompat.getExternalFilesDirs(this, null).length >= 2) {
                File[] f = ContextCompat.getExternalFilesDirs(this, null);
                for (int i = 0; i < f.length; i++) {
                    File file = f[i];
                    if(file!=null && i ==1)
                    {
                        Log.d(TAG,file.getAbsolutePath()+ "external sd card  available");

                    }

                }
            } else {
                Log.d(TAG, " external sd card not available");

            }
Rajesh Wolf
  • 1,005
  • 8
  • 12