安卓系统存储空间情况读取

安卓系统分区大致可分为系统分区、用户分区,网上的常规方法如读取SD卡路径等方法其实都是不太准确的,这里使用系统api读取。

这里先上个代码

StorageManager sm = getSystemService(StorageManager.class);
StorageStatsManager ssm = getSystemService(StorageStatsManager.class);
long privateFreeBytes = 0;
long privateTotalBytes = 0;
List<VolumeInfo> volumes = ReflectUtils.reflect(sm).method("getVolumes").get();
for (VolumeInfo volume : volumes) {
    //note type==1为用户卷,type==2为系统卷,一般读取用户卷即可
    if (volume.getType() == 1) {
        privateTotalBytes += ssm.getTotalBytes(volume.getFsUuid());
        privateFreeBytes += ssm.getFreeBytes(volume.getFsUuid());
    }
    break;
}
LogUtils.i("设备空间读取",
           "可用空间--"+Formatter.formatFileSize(Utils.getApp(),privateFreeBytes),
           "闪存空间--"+Formatter.formatFileSize(Utils.getApp(),privateTotalBytes));
return new long[]{privateTotalBytes-privateFreeBytes, privateTotalBytes};

打印结果:跟原生系统设置看到的数据应该是一致的,图就不上了

┌──────────────────────────────
│ args[0] = 设备空间读取
│ args[1] = 可用空间--4.48 GB
│ args[2] = 闪存空间--8.00 GB
└──────────────────────────────

代码中使用了StorageManager、StorageStatsManager两个系统服务,其中StorageManager的getVolumes方法是隐藏的,需要使用反射获取,返回的是分区卷的相关信息。然后配合使用StorageStatsManager的相关方法即可实现对分区使用情况的读取。

注意事项

  1. 读取是个耗时操作,需要在子线程执行并做好兼容异常等处理。
  2. getTotalBytes(String uuid)在Api 28已经移除(也有可能更早),本文使用Api版本为26。
  3. getTotalBytes(UUID storageUuid)是更好的选择,只需要StorageManager.convert(uuid)做一下转换即可。