Skip to main content

StorageStatsManager

Android Oreo (API Level 26) introduced StorageStatsManager class that we can use to access storage statistics of our application.

Storage Volume UUID​

Notice that all StorageStatsManager class methods requires the storage volume UUID as parameter. Learn how to retrieve your application's storage volume UUID here.

Basic Usages​

Once you retrieve your app's storage volume UUID, you can do these basic operations with StorageStatsManager.

Getting Storage Volume Free Space​

We can retrieve the free space of the requested storage volume by using getFreeBytes() method:

import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.util.Log

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val freeBytes = storageStatsManager.getFreeBytes(applicationInfo.storageUuid)
Log.i("TAG", freeBytes.toString())
}

This value is best suited for visual display to end users, since it's designed to reflect both unused space and cached space that could be reclaimed by the system.

Getting Storage Volume Total Space​

We can retrieve the total size of the underlying physical media that is hosting the requested storage volume by using getTotalBytes() method:

import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.util.Log

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val totalBytes = storageStatsManager.getTotalBytes(applicationInfo.storageUuid)
Log.i("TAG", totalBytes.toString())
}

This value is best suited for visual display to end users, since it's designed to reflect the total storage size advertised in a retail environment.

Getting the Size of Application​

This method summarizes the installed size of an app as a single number of bytes, which is a sum of the APK size, the size of files extracted from the APK, and files that were generated on the device such as ahead-of-time (AOT) compiled code.

We can retrieve the size of our application by using getAppBytes() method. This includes:

  • APK files,
  • optimized compiler output, and
  • unpacked native libraries.

If the primary external/shared storage is hosted on this storage device, then this includes files under Context.getObbDir().

import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.util.Log

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val storageStats = storageStatsManager.queryStatsForPackage(
applicationInfo.storageUuid,
context.packageName,
android.os.Process.myUserHandle(),
)
Log.i("TAG", storageStats.appBytes.toString())
}

Getting the Size of Application by Data Type​

Android 15 (API Level 35) introduced a new method called getAppBytesByDataType() that allows to get more insight into how our application is using all the space specified by getAppBytes() method.

We can specify which data type that we want to gain insight into. Currently there are 6 data types that we can use:

Data TypeDescription
APP_DATA_TYPE_FILE_TYPE_DEXOPT_ARTIFACTRepresents all nonstale dexopt and runtime artifacts of application. This includes AOT-compiled code and other data that can speed up app execution. For more detailed information, read the JIT compiler guide. Dexopt artifacts become stale when one of their dependencies has changed. They may be cleaned up or replaced by ART Services at any time. For a preload app, this type includes dexopt artifacts on readonly partitions if they are up-to-date. The sum might include the size of data that is part of appBytes, dataBytes or cacheBytes.
APP_DATA_TYPE_FILE_TYPE_REFERENCE_PROFILERepresents reference profile of application. Reference profiles are the ones used during the last profile-guided dexopt. If the last dexopt wasn't profile-guided, then these profiles were not used.
APP_DATA_TYPE_FILE_TYPE_CURRENT_PROFILERepresents current profile of application. Current profiles may or may not be used during the next profile-guided dexopt. This size fluctuates regularly, it goes up when the user uses more and more classes/methods and comes down when a deamon merges this into the ref profile and does profile-guided dexopt.
APP_DATA_TYPE_FILE_TYPE_APKRepresents all .apk files in application code path.
APP_DATA_TYPE_FILE_TYPE_DMRepresents all .dm files in application code path.
APP_DATA_TYPE_LIBRepresents lib/ in application code path.
import android.app.usage.StorageStats
import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.util.Log

val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val storageStats = storageStatsManager.queryStatsForPackage(
applicationInfo.storageUuid,
context.packageName,
android.os.Process.myUserHandle(),
)
Log.i("TAG", storageStats.getAppBytesByDataType(StorageStats.APP_DATA_TYPE_FILE_TYPE_APK).toString())

Getting the Size of Application's Cache Data​

We can retrieve the size of our application's cache data by using getCacheBytes() method. This includes files stored under:

If the primary external/shared storage is hosted on this storage device, then this includes files under Context.getExternalCacheDir().

import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.util.Log

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val storageStats = storageStatsManager.queryStatsForPackage(
applicationInfo.storageUuid,
context.packageName,
android.os.Process.myUserHandle(),
)
Log.i("TAG", storageStats.cacheBytes.toString())
}

Getting the Size of Application's Data​

We can retrieve the size of our application's data by using getDataBytes() method. This includes files stored under:

If the primary external/shared storage is hosted on this storage device, then this includes files under:

import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.util.Log

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val storageStats = storageStatsManager.queryStatsForPackage(
applicationInfo.storageUuid,
context.packageName,
android.os.Process.myUserHandle(),
)
Log.i("TAG", storageStats.dataBytes.toString())
}

Getting the Size of Application's External Cache Data​

We can retrieve the size of our application's cache data in the primary external/shared storage by using getExternalCacheBytes() method. This includes files stored under Context.getExternalCacheDir().

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val applicationInfo = context.packageManager.getApplicationInfo(
context.packageName,
0,
)
val storageStatsManager = context.getSystemService(StorageStatsManager::class.java)
val storageStats = storageStatsManager.queryStatsForPackage(
applicationInfo.storageUuid,
context.packageName,
android.os.Process.myUserHandle(),
)
Log.i("TAG", storageStats.externalCacheBytes.toString())
}

References​