50

How do I check to see how much space (in MB or GB) is left on the Android device? I am using Java and Android SDK 2.0.1.

Is there a system service that would expose something like this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zeus
  • 3,091
  • 6
  • 47
  • 60

9 Answers9

76

Yaroslav's answer will give the size of the SD card, not the available space. StatFs's getAvailableBlocks() will return the number of blocks that are still accessible to normal programs. Here is the function I am using:

public static float megabytesAvailable(File f) {
    StatFs stat = new StatFs(f.getPath());
    long bytesAvailable = (long)stat.getBlockSize() * (long)stat.getAvailableBlocks();
    return bytesAvailable / (1024.f * 1024.f);
}

The above code has reference to some deprecated functions as of August 13, 2014. I below reproduce an updated version:

public static float megabytesAvailable(File f) {
    StatFs stat = new StatFs(f.getPath());
    long bytesAvailable = 0;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
        bytesAvailable = (long) stat.getBlockSizeLong() * (long) stat.getAvailableBlocksLong();
    else
        bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks();
    return bytesAvailable / (1024.f * 1024.f);
}
Sayed Abolfazl Fatemi
  • 3,678
  • 3
  • 36
  • 48
  • 4
    Yes getBlockSize() is deprecate. We could also use Environment.getDataDirectory().getUsableSpace() for retrieving the free space available. – nous Dec 10 '14 at 00:48
56

Try this code:

StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());

long bytesAvailable = (long)stat.getBlockSize() *(long)stat.getBlockCount();
long megAvailable   = bytesAvailable / 1048576;

System.out.println("Megs: " + megAvailable);

Explanation

getBlockCount() - return size of SD card;

getAvailableBlocks() - return the number of blocks that are still accessible to normal programs (thanks Joe)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yaroslav Boichuk
  • 1,763
  • 20
  • 31
23

I have designed some ready-to-use functions to get the available space in different units. You can use these methods by simply copying any one of them into your project.

/**
 * @return Number of bytes available on External storage
 */
public static long getAvailableSpaceInBytes() {
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();

    return availableSpace;
}


/**
 * @return Number of kilo bytes available on External storage
 */
public static long getAvailableSpaceInKB() {
    final long SIZE_KB = 1024L;
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
    return availableSpace/SIZE_KB;
}


/**
 * @return Number of Mega bytes available on External storage
 */
public static long getAvailableSpaceInMB() {
    final long SIZE_KB = 1024L;
    final long SIZE_MB = SIZE_KB * SIZE_KB;
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
    return availableSpace/SIZE_MB;
}


/**
 * @return Number of gega bytes available on External storage
 */
public static long getAvailableSpaceInGB() {
    final long SIZE_KB = 1024L;
    final long SIZE_GB = SIZE_KB * SIZE_KB * SIZE_KB;
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
    return availableSpace/SIZE_GB;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Muhammad Nabeel Arif
  • 19,140
  • 8
  • 51
  • 70
6

Based on this answer, they added support to Android version < 18:

public static float megabytesAvailable(File file) {
    StatFs stat = new StatFs(file.getPath());
    long bytesAvailable;
    if(Build.VERSION.SDK_INT >= 18) {
        bytesAvailable = getAvailableBytes(stat);
    }
    else {
        // noinspection deprecation
        bytesAvailable = stat.getBlockSize() * stat.getAvailableBlocks();
    }

    return bytesAvailable / (1024.f * 1024.f);
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private static long getAvailableBytes(StatFs stat) {
    return stat.getBlockSizeLong() * stat.getAvailableBlocksLong();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
5

New methods was introduced since API version 18.

I used something like that for big disk cache size estimation (for Picasso OkHttp downloader cache). Helper method was like that:

private static final String BIG_CACHE_PATH = "my-cache-dir";
private static final float  MAX_AVAILABLE_SPACE_USE_FRACTION = 0.9f;
private static final float  MAX_TOTAL_SPACE_USE_FRACTION     = 0.25f;

static File createDefaultCacheDirExample(Context context) {
    File cache = new File(context.getApplicationContext().getCacheDir(), BIG_CACHE_PATH);
    if (!cache.exists()) {
        cache.mkdirs();
    }
    return cache;
}

/**
 * Calculates minimum of available or total fraction of disk space
 * 
 * @param dir
 * @return space in bytes
 */
@SuppressLint("NewApi")
static long calculateAvailableCacheSize(File dir) {
    long size = 0;
    try {
        StatFs statFs = new StatFs(dir.getAbsolutePath());
        int sdkInt = Build.VERSION.SDK_INT;
        long totalBytes;
        long availableBytes;
        if (sdkInt < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            int blockSize = statFs.getBlockSize();
            availableBytes = ((long) statFs.getAvailableBlocks()) * blockSize;
            totalBytes = ((long) statFs.getBlockCount()) * blockSize;
        } else {
            availableBytes = statFs.getAvailableBytes();
            totalBytes = statFs.getTotalBytes();
        }
        // Target at least 90% of available or 25% of total space
        size = (long) Math.min(availableBytes * MAX_AVAILABLE_SPACE_USE_FRACTION, totalBytes * MAX_TOTAL_SPACE_USE_FRACTION);
    } catch (IllegalArgumentException ignored) {
        // ignored
    }
    return size;
}
fada21
  • 3,188
  • 1
  • 22
  • 21
5

Also, if you want to check the available space on internal memory, use:

File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());

...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
android developer
  • 114,585
  • 152
  • 739
  • 1,270
2

Google has information on this on the getting started page - See Query Free Space. They say that you can either check the available space by getFreeSpace() but they state that this is inaccurate and you should expect a little less free space than this. They say:

If the number returned is a few MB more than the size of the data you want to save, or if the file system is less than 90% full, then it's probably safe to proceed. Otherwise, you probably shouldn't write to storage.

Also they give the advice that it's often more useful not the check the free space at all and just try catch for an error:

You aren't required to check the amount of available space before you save your file. You can instead try writing the file right away, then catch an IOException if one occurs. You may need to do this if you don't know exactly how much space you need. For example, if you change the file's encoding before you save it by converting a PNG image to JPEG, you won't know the file's size beforehand.

I would recommend that only for very large file sizes you should check the available storage beforehand so you don't lose time downloading or creating a file which if obviously too large to hold. In either cases you should always use try catch so I think that the only argument for checking the available free space beforehand if is either the unnecessary use of resources and time is too much.

Joop
  • 3,706
  • 34
  • 55
1

This code is tested and is working fine.

/**
 * Get the free disk available space in boolean to download requested file 
 * 
 * @return boolean value according to size availability
 */

protected static boolean isMemorySizeAvailableAndroid(long download_bytes, boolean isExternalMemory) {
    boolean isMemoryAvailable = false;
    long freeSpace = 0;
    
    // if isExternalMemory get true to calculate external SD card available size
    if(isExternalMemory){
        try {
            StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
            freeSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
            if(freeSpace > download_bytes){
                isMemoryAvailable = true;
            }else{
                isMemoryAvailable = false;
            }
        } catch (Exception e) {e.printStackTrace(); isMemoryAvailable = false;}
    }else{
        // find phone available size
        try {
            StatFs stat = new StatFs(Environment.getDataDirectory().getPath());
            freeSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
            if(freeSpace > download_bytes){
                isMemoryAvailable = true;
            }else{
                isMemoryAvailable = false;
            }
        } catch (Exception e) {e.printStackTrace(); isMemoryAvailable = false;}
    }
    
    return isMemoryAvailable;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
-3
public String TotalExtMemory()
{
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());   
    int Total = (statFs.getBlockCount() * statFs.getBlockSize()) / 1048576;

    String strI = Integer.toString(Total);
    return strI;
}

public String FreeExtMemory()
{
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
    int Free  = (statFs.getAvailableBlocks() * statFs.getBlockSize()) / 1048576;
    String strI = Integer.toString(Free);
    return strI;
}

public String BusyExtMemory()
{
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());   
    int Total = (statFs.getBlockCount() * statFs.getBlockSize()) / 1048576;
    int Free  = (statFs.getAvailableBlocks() * statFs.getBlockSize()) / 1048576;
    int Busy  = Total - Free;
    String strI = Integer.toString(Busy);
    return strI;
}
Daniel Rikowski
  • 71,375
  • 57
  • 251
  • 329