I'm developing a file manager app in Kotlin and I need to retrieve the total size of the internal storage, including the space occupied by the system.
I've tried using the StatFs
class:
val stat = StatFs(path) // path = "/storage/emulated/0"
val totalBytes = stat.totalBytes
This method works correctly for retrieving the total size of the SD card. However, when used for the internal storage, it doesn't include the space used by the system and returns a lower value than the actual size:
Log.d("totalBytes", totalBytes.toString()) // Returns 109799354368
Adding the system-occupied space to the returned value gives the correct total internal storage size.
I've also researched potential solutions and found two main approaches:
- Using the df command in Linux (which Android is based on). However, I understand that this method has limitations, risks, and it's generally better to use official Android APIs.
- Using StorageStatsManager. This method requires the PACKAGE_USAGE_STATS permission, which is a sensitive permission. It's not requested through standard system permission dialogs (یا runtime permission prompts یا typical system permission dialogs) and the user needs to be directed to the settings to grant it. Also, the "Files by Google" app seems to be able to get the total internal storage size without requesting this permission.
I've searched online extensively but haven't found a suitable method. How can I retrieve the total internal storage size without requiring sensitive permissions, or at least with only external storage permissions (READ_EXTERNAL_STORAGE
or MANAGE_EXTERNAL_STORAGE
)?
I'm developing a file manager app in Kotlin and I need to retrieve the total size of the internal storage, including the space occupied by the system.
I've tried using the StatFs
class:
val stat = StatFs(path) // path = "/storage/emulated/0"
val totalBytes = stat.totalBytes
This method works correctly for retrieving the total size of the SD card. However, when used for the internal storage, it doesn't include the space used by the system and returns a lower value than the actual size:
Log.d("totalBytes", totalBytes.toString()) // Returns 109799354368
Adding the system-occupied space to the returned value gives the correct total internal storage size.
I've also researched potential solutions and found two main approaches:
- Using the df command in Linux (which Android is based on). However, I understand that this method has limitations, risks, and it's generally better to use official Android APIs.
- Using StorageStatsManager. This method requires the PACKAGE_USAGE_STATS permission, which is a sensitive permission. It's not requested through standard system permission dialogs (یا runtime permission prompts یا typical system permission dialogs) and the user needs to be directed to the settings to grant it. Also, the "Files by Google" app seems to be able to get the total internal storage size without requesting this permission.
I've searched online extensively but haven't found a suitable method. How can I retrieve the total internal storage size without requiring sensitive permissions, or at least with only external storage permissions (READ_EXTERNAL_STORAGE
or MANAGE_EXTERNAL_STORAGE
)?
1 Answer
Reset to default 0The size of the internal storage (eMMC) seemingly can only be obtained from the underlying Linux. For example, file /sys/class/mmc_host/mmc0/mmc0:0001/block/mmcblk0/size
returns the number of total blocks, to be multiplied by block size. The name of the volume and therefore the path might vary and should better be traversed instead of hardcoded ...it really depends, because it might be named and anized differently, from device to device. Usually it's mmcblk0
, eMMC block device at index 0
. The outcome may have limited portability, unless throughly testing it with all kind of storage configurations, which would all have to be considered.
While one doesn't even have to run any shell automation, but StatFs
(which wraps the statvfs
command) would provide the desired information per mount-point, alike /mnt/emmc
or whereever it may be mounted, which needs to be determined by file-system traversal.
/** Obtain the size of a partition by its mount-point. */
private fun getTotalSize(mountPoint: String): Long {
val stat = StatFs(mountPoint)
return stat.blockCountLong * stat.blockSizeLong
}
Please note, that the logical mount-point is not the actual physical block device. Usually the partition size should suffice, unless needing to know how large the eMMC really is. That's alike when formatting a HDD, which then also does not have the exact size of the physical drive. Internal and external storage might even be two partition on the very same eMMC, when there is no SD slot present. While from within Android, it is very difficult to determine, by which devices the storage API is really backed - and mmcblk0
might also hold an "external" storage partition.
MANAGE_EXTERNAL_STORAGE
permission. – Mohammad Commented Mar 10 at 11:30