获取安装应用Apk包大小、缓存大小以及应用占用存储总大小
可以通过 PackageManager类的getPackageSizeInfo方法获取,但是这个方法被Google标记成隐藏方法,不能直接调用;
解决方法:可以通过反射调用,但在Android8.0及以上通过反射调用会报错,不过Android8.0及以上可以通过StorageManager 获取
Android8.0以下获取Apk大小方法:
通过反射调用getPackageSizeInfo获取
- 创建AIDL文件
- 创建文件 IPackageStatsObserver.aidl
package android.content.pm; import android.content.pm.PackageStats; oneway interface IPackageStatsObserver { void onGetStatsCompleted(in PackageStats pStats, boolean succeeded); }
- 创建文件 PackageStats.aidl
package android.content.pm; parcelable PackageStats;
注意包名路径创建正确
如下图:
创建完成后依次点击 Build --> Make Project 以生成AIDL文件
- 在AndroidManifest.xml 中添加权限
- 代码实现
public static void handlePackageSizeInfo(Context context, String packageName) { PackageManager mPackageManager = context.getPackageManager(); Method getPackageSizeInfo = null; try { getPackageSizeInfo = mPackageManager.getClass().getMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } MyPackageStatsObserver mSecurityPackageStatsObserver = new MyPackageStatsObserver(); if (getPackageSizeInfo != null) { try { getPackageSizeInfo.setAccessible(true); // 调用该函数,待调用完成后会回调MyPackageStatsObserver getPackageSizeInfo.invoke(mPackageManager, packageName, mSecurityPackageStatsObserver); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } } static class MyPackageStatsObserver extends IPackageStatsObserver.Stub { @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) { long mCacheSize = pStats.cacheSize; long mCodeSize = pStats.codeSize; long mDataSize = pStats.dataSize; long mTotalSize = mCacheSize + mCodeSize + mDataSize; Log.d("AppLog", succeeded+ " cacheSize = " + mCacheSize + "; appSize = " + mCodeSize + "; " + "dataSize = " + mDataSize + "; totalSize = " + mTotalSize); } }
Android8.0及以上获取Apk大小方法:
通过系统服务 StorageManager 获取Apk大小,需要申请权限 PACKAGE_USAGE_STATS
- 在AndroidManifest.xml 中添加权限
- 代码实现
@RequiresApi(api = Build.VERSION_CODES.O) public static void getAppSize(Context context, String packageName){ if (!hasUsageStatsPermission(context)){ requestAppUsagePermission(context); } else { new Thread(() -> { final StorageStatsManager storageStatsManager = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE); final StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); final ListstorageVolumes = storageManager.getStorageVolumes(); final UserHandle user = android.os.Process.myUserHandle(); try { for (StorageVolume storageVolume : storageVolumes) { final String uuidStr = storageVolume.getUuid(); final UUID uuid = uuidStr == null ? StorageManager.UUID_DEFAULT : UUID.fromString(uuidStr); Log.d("AppLog", "storage:" + uuid + " : " + storageVolume.getDescription(context) + " : " + storageVolume.getState()); Log.d("AppLog", "getFreeBytes:" + Formatter.formatShortFileSize(context, storageStatsManager.getFreeBytes(uuid))); Log.d("AppLog", "getTotalBytes:" + Formatter.formatShortFileSize(context, storageStatsManager.getTotalBytes(uuid))); StorageStats storageStats = storageStatsManager.queryStatsForPackage(uuid, packageName, user); Log.d("AppLog", "storage stats for app of package name:" + packageName + " : "); Log.d("AppLog", "getAppBytes:" + Formatter.formatShortFileSize(context, storageStats.getAppBytes()) + " getCacheBytes:" + Formatter.formatShortFileSize(context, storageStats.getCacheBytes()) + " getDataBytes:" + Formatter.formatShortFileSize(context, storageStats.getDataBytes())); } }catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }).start(); } } public static boolean hasUsageStatsPermission(Context context) { UsageStatsManager usageStatsManager = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) { usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE); } if (usageStatsManager == null) { return false; } long currentTime = System.currentTimeMillis(); // try to get app usage state in last 2 min List stats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, currentTime - 2 * 60 * 1000, currentTime); return stats != null && stats.size() > 0; } public static void requestAppUsagePermission(Context context) { Intent intent = new Intent(android.provider.Settings.ACTION_USAGE_ACCESS_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { context.startActivity(intent); } catch (ActivityNotFoundException e) { Log.e("AppLog", "Start usage access settings activity fail!", e); } }
总结
public static void getInstallApkSize(Context context, String packageName){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { getAppSize(context, packageName); } else { handlePackageSizeInfo(context, packageName); } }
Android8.0以下可以通过反射getPackageSizeInfo方法获取Apk大小;
Android8.0及以上可以通过申请权限 PACKAGE_USAGE_STATS 获取其他已安装应用的Apk大小
还有一种比较复杂方法是 编译一下的android2.3的framework框架,把jar包拷出来,再把框架导入到library,之后就可以直接调用已经hide 的方法 getPackageSizeInfo() 了,具体 *** 作可以搜一下
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)