Android中PackageStats返回值始终为0,低版本如何计算应用目录大小?
解决Android Oreo以下计算应用存储大小的问题
嘿,我完全懂你的困扰!针对你提到的两个核心问题——Oreo以下设备如何计算/Android/data/myapplicationpackage目录大小,以及PackageStats返回0的正确用法,我来一步步给你梳理清楚:
一、PackageStats返回0?你大概率踩了这两个坑
PackageStats本身是靠谱的API,但很多开发者会在权限声明和异步调用逻辑上出错,导致返回0,具体要注意:
1. 必须在清单中声明权限
在AndroidManifest.xml里添加这个正常权限(无需动态申请,但必须声明):
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
2. 必须用异步回调获取结果
PackageManager的getPackageSizeInfo是异步方法,不能同步直接拿值,必须通过IPackageStatsObserver回调接收结果。以下是完整可运行的示例:
import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageManager; import android.content.pm.PackageStats; import android.os.RemoteException; // 调用这个方法获取应用存储大小 public void fetchAppTotalStorage(String packageName) { PackageManager pm = getPackageManager(); try { pm.getPackageSizeInfo(packageName, new IPackageStatsObserver.Stub() { @Override public void onGetStatsCompleted(PackageStats stats, boolean succeeded) throws RemoteException { if (succeeded) { // 计算总占用:内部数据+外部数据+缓存+外部缓存 long totalBytes = stats.dataSize + stats.externalDataSize + stats.cacheSize + stats.externalCacheSize; // 注意:更新UI要切回主线程 runOnUiThread(() -> { long totalMB = totalBytes / (1024 * 1024); // 这里可以把结果展示给用户 }); } else { // 处理获取失败的情况 } } }); } catch (RemoteException e) { e.printStackTrace(); } }
如果之前返回0,大概率是没使用异步回调,或者漏加了权限。
二、直接遍历/Android/data/你的包名目录计算大小
如果你只需要特定目录的大小,直接遍历目录累加是更灵活的方案,不受系统版本限制:
1. 权限准备
- Android 6.0(API 23)及以上:需要动态申请
READ_EXTERNAL_STORAGE权限(因为该目录属于外部存储) - Android 5.1及以下:仅需在清单中声明
READ_EXTERNAL_STORAGE即可
2. 递归计算目录大小的代码
import java.io.File; // 递归计算目录总大小 public long calculateDirSize(File targetDir) { if (!targetDir.exists() || !targetDir.isDirectory()) { return 0; } long totalSize = 0; File[] files = targetDir.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory()) { totalSize += calculateDirSize(file); } else { totalSize += file.length(); } } } return totalSize; } // 使用示例 File appExternalDataDir = new File(Environment.getExternalStorageDirectory(), "Android/data/" + getPackageName()); // 注意:大目录计算耗时,要放在子线程执行 new Thread(() -> { long dirSize = calculateDirSize(appExternalDataDir); long dirSizeMB = dirSize / (1024 * 1024); // 切回主线程更新UI runOnUiThread(() -> { // 展示计算结果 }); }).start();
两种方案对比
- PackageStats:适合获取应用的全量存储占用(内部数据、缓存、外部数据等),但依赖系统API,需处理异步逻辑。
- 直接遍历目录:适合只需要特定目录的大小,逻辑简单兼容性强,但要注意权限和线程阻塞问题。
内容的提问来源于stack exchange,提问作者sam_k
相关产品推荐
相关产品推荐

