I want to get the size of free memory on internal/external storage of my device programmatically. I\'m using this piece of code :
StatFs stat = new StatFs(En
This is the way i did it..
internal Total memory
double totalSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getTotalSpace();
double totMb = totalSize / (1024 * 1024);
Internal free size
double availableSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
double freeMb = availableSize/ (1024 * 1024);
External free and total memory
long freeBytesExternal = new File(getExternalFilesDir(null).toString()).getFreeSpace();
int free = (int) (freeBytesExternal/ (1024 * 1024));
long totalSize = new File(getExternalFilesDir(null).toString()).getTotalSpace();
int total= (int) (totalSize/ (1024 * 1024));
String availableMb = free+"Mb out of "+total+"MB";
To get all available storage folders (including SD cards), you first get the storage files:
File internalStorageFile=getFilesDir();
File[] externalStorageFiles=ContextCompat.getExternalFilesDirs(this,null);
Then you can get the available size of each of those.
There are 3 ways to do it:
API 8 and below:
StatFs stat=new StatFs(file.getPath());
long availableSizeInBytes=stat.getBlockSize()*stat.getAvailableBlocks();
API 9 and above:
long availableSizeInBytes=file.getFreeSpace();
API 18 and above (not needed if previous one is ok) :
long availableSizeInBytes=new StatFs(file.getPath()).getAvailableBytes();
To get a nice formatted string of what you got now, you can use:
String formattedResult=android.text.format.Formatter.formatShortFileSize(this,availableSizeInBytes);
or you can use this in case you wish to see exact bytes number but nicely:
NumberFormat.getInstance().format(availableSizeInBytes);
Do note that I think the internal storage could be the same as the first external storage, since the first one is the emulated one.
EDIT: Using StorageVolume on Android Q and above, I think it's possible to get the free space of each, using something like:
val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
AsyncTask.execute {
for (storageVolume in storageVolumes) {
val uuid: UUID = storageVolume.uuid?.let { UUID.fromString(it) } ?: StorageManager.UUID_DEFAULT
val allocatableBytes = storageManager.getAllocatableBytes(uuid)
Log.d("AppLog", "allocatableBytes:${android.text.format.Formatter.formatShortFileSize(this,allocatableBytes)}")
}
}
I'm not sure if this is correct, and I can't find a way to get the total size of each, so I wrote about it here, and asked about it here.
Quick addition to External memory topic
Don't be confused by the method name externalMemoryAvailable()
in Dinesh Prajapati's answer.
Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
gives you the current state of the memory, if the media is present and mounted at its mount point with read/write access.
You will get true
even on devices with no SD-cards, like Nexus 5. But still it's a 'must-have' method before any operations with storage.
To check if there is an SD-card on your device you can use method ContextCompat.getExternalFilesDirs()
It doesn't show transient devices, such as USB flash drives.
Also be aware that ContextCompat.getExternalFilesDirs()
on Android 4.3 and lower will always return only 1 entry (SD-card if it's available, otherwise Internal). You can read more about it here.
public static boolean isSdCardOnDevice(Context context) {
File[] storages = ContextCompat.getExternalFilesDirs(context, null);
if (storages.length > 1 && storages[0] != null && storages[1] != null)
return true;
else
return false;
}
in my case it was enough, but don't forget that some of the Android devices might have 2 SD-cards, so if you need all of them - adjust the code above.
@Android-Droid - you are wrong Environment.getExternalStorageDirectory()
points to external storage which does not have to be SD card, it can also be mount of internal memory. See:
Find an external SD card location
About external menory ,there is another way:
File external = Environment.getExternalStorageDirectory();
free:external.getFreeSpace();
total:external.getTotalSpace();
It is very easy to find out the storage available if you get internal as well as external storage path. Also phone's external storage path really very easy to find out using
Environment.getExternalStorageDirectory().getPath();
So I am just concentrating on how to find out the paths of external removable storage like removable sdcard, USB OTG(not tested USB OTG as I have no USB OTG).
Below method will give a list of all possible external removable storage paths.
/**
* This method returns the list of removable storage and sdcard paths.
* I have no USB OTG so can not test it. Is anybody can test it, please let me know
* if working or not. Assume 0th index will be removable sdcard path if size is
* greater than 0.
* @return the list of removable storage paths.
*/
public static HashSet<String> getExternalPaths()
{
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try
{
final Process process = new ProcessBuilder().command("mount").redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1)
{
s = s + new String(buffer);
}
is.close();
}
catch (final Exception e)
{
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines)
{
if (!line.toLowerCase(Locale.US).contains("asec"))
{
if (line.matches(reg))
{
String[] parts = line.split(" ");
for (String part : parts)
{
if (part.startsWith("/"))
{
if (!part.toLowerCase(Locale.US).contains("vold"))
{
out.add(part.replace("/media_rw","").replace("mnt", "storage"));
}
}
}
}
}
}
//Phone's external storage path (Not removal SDCard path)
String phoneExternalPath = Environment.getExternalStorageDirectory().getPath();
//Remove it if already exist to filter all the paths of external removable storage devices
//like removable sdcard, USB OTG etc..
//When I tested it in ICE Tab(4.4.2), Swipe Tab(4.0.1) with removable sdcard, this method includes
//phone's external storage path, but when i test it in Moto X Play (6.0) with removable sdcard,
//this method does not include phone's external storage path. So I am going to remvoe the phone's
//external storage path to make behavior consistent in all the phone. Ans we already know and it easy
// to find out the phone's external storage path.
out.remove(phoneExternalPath);
return out;
}