Android获取安装应用Apk包大小 缓存大小 getPackage

家电维修 2023-07-16 19:17www.caominkang.com家电维修技术

获取安装应用Apk包大小、缓存大小以及应用占用存储总大小
可以通过 PackageManager类的getPackageSizeInfo方法获取,这个方法被Google标记成隐藏方法,不能直接调用;
解决方法可以通过反射调用,但在Android8.0及以上通过反射调用会报错,不过Android8.0及以上可以通过StorageManager 获取

Android8.0以下获取Apk大小方法
通过反射调用getPackageSizeInfo获取

  1. 创建AIDL文件
  • 创建文件 IPackageStatsObserver.aidl
package android.content.pm;

import android.content.pm.PackageStats;

oneay interface IPackageStatsObserver {

 void onGetStatsCompleted(in PackageStats pStats, boolean sueeded);
}

  • 创建文件 PackageStats.aidl
package android.content.pm;

parcelable PackageStats;

注意包名路径创建正确

如下图

创建完成后依次点击 Build --> Make Project 以生成AIDL文件

  1. 在AndroidManifest.xml 中添加权限

  1. 代码实现
 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 = ne MyPackageStatsObserver();
  if (getPackageSizeInfo != null) {
   try {
    getPackageSizeInfo.setAessible(true);
    // 调用该函数,待调用完成后会回调MyPackageStatsObserver
    getPackageSizeInfo.invoke(mPackageManager, packageName, mSecurityPackageStatsObserver);
   } catch (IllegalAessException | IllegalArgumentException | InvocationTargetException e) {
    e.printStackTrace();
   }
  }
 }

 static class MyPackageStatsObserver extends IPackageStatsObserver.Stub {

  @Override
  public void onGetStatsCompleted(PackageStats pStats, boolean sueeded) {
   long mCacheSize = pStats.cacheSize;
   long mCodeSize = pStats.codeSize;
   long mDataSize = pStats.dataSize;
   long mTotalSize = mCacheSize + mCodeSize + mDataSize;
   Log.d("AppLog", sueeded+ " cacheSize = " + mCacheSize + "; appSize = " + mCodeSize + "; " + "dataSize = " + mDataSize + "; totalSize = " + mTotalSize);
  }
 }

Android8.0及以上获取Apk大小方法
通过系统服务 StorageManager 获取Apk大小,需要申请权限 PACKAGE_USAGE_STATS

  1. 在AndroidManifest.xml 中添加权限

  1. 代码实现
	@RequiresApi(api = Build.VERSION_CODES.O)
 public static void getAppSize(Context context, String packageName){
  if (!hasUsageStatsPermission(context)){
   requestAppUsagePermission(context);
  } else {
   ne Thread(() -> {
    final StorageStatsManager storageStatsManager = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);
    final StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    final List storageVolumes = 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 = ne 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 aess 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的frameork框架,把jar包拷出来,再把框架导入到library,之后就可以直接调用已经hide 的方法 getPackageSizeInfo() 了,具体操作可以搜一下

Copyright © 2016-2025 www.jianfeikang.com 建飞家电维修 版权所有 Power by