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:
fun getStorageVolumesAccessState(context: Context) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
val storageStatsManager = context.getSystemService(Context.STORAGE_STATS_SERVICE) as StorageStatsManager
for (storageVolume in storageVolumes) {
var freeSpace: Long = 0L
var totalSpace: Long = 0L
val path = getPath(context, storageVolume)
if (storageVolume.isPrimary) {
totalSpace = storageStatsManager.getTotalBytes(StorageManager.UUID_DEFAULT)
freeSpace = storageStatsManager.getFreeBytes(StorageManager.UUID_DEFAULT)
} else if (path != null) {
val file = File(path)
freeSpace = file.freeSpace
totalSpace = file.totalSpace
}
val usedSpace = totalSpace - freeSpace
val freeSpaceStr = Formatter.formatFileSize(context, freeSpace)
val totalSpaceStr = Formatter.formatFileSize(context, totalSpace)
val usedSpaceStr = Formatter.formatFileSize(context, usedSpace)
Log.d("AppLog", "${storageVolume.getDescription(context)} - path:$path total:$totalSpaceStr used:$usedSpaceStr free:$freeSpaceStr")
}
}
fun getPath(context: Context, storageVolume: StorageVolume): String? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
storageVolume.directory?.absolutePath?.let { return it }
try {
return storageVolume.javaClass.getMethod("getPath").invoke(storageVolume) as String
} catch (e: Exception) {
}
try {
return (storageVolume.javaClass.getMethod("getPathFile").invoke(storageVolume) as File).absolutePath
} catch (e: Exception) {
}
val extDirs = context.getExternalFilesDirs(null)
for (extDir in extDirs) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val fileStorageVolume: StorageVolume = storageManager.getStorageVolume(extDir)
?: continue
if (fileStorageVolume == storageVolume) {
var file = extDir
while (true) {
val parent = file.parentFile ?: return file.absolutePath
val parentStorageVolume = storageManager.getStorageVolume(parent)
?: return file.absolutePath
if (parentStorageVolume != storageVolume)
return file.absolutePath
file = parent
}
}
}
try {
val parcel = Parcel.obtain()
storageVolume.writeToParcel(parcel, 0)
parcel.setDataPosition(0)
parcel.readString()
return parcel.readString()
} catch (e: Exception) {
}
return null
}
Hopefully this can help.