欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > Android >内容正文

Android

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

发布时间:2024/8/1 Android 39 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Android获取安装应用Apk包大小 缓存大小 getPackageSizeInfo StorageManager 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

获取安装应用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; /*** API for package data change related callbacks from the Package Manager.* Some usage scenarios include deletion of cache directory, generate* statistics related to code, data, cache usage(TODO)* {@hide}*/ oneway interface IPackageStatsObserver {void onGetStatsCompleted(in PackageStats pStats, boolean succeeded); }
    • 创建文件 PackageStats.aidl
    package android.content.pm;parcelable PackageStats;

    注意包名路径创建正确

    如下图:

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

  • 在AndroidManifest.xml 中添加权限
  • <uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
  • 代码实现
  • 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);// 调用该函数,待调用完成后会回调MyPackageStatsObservergetPackageSizeInfo.invoke(mPackageManager, packageName, mSecurityPackageStatsObserver);} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {e.printStackTrace();}}}static class MyPackageStatsObserver extends IPackageStatsObserver.Stub {@Overridepublic 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 中添加权限
  • <uses-permissionandroid:name="android.permission.PACKAGE_USAGE_STATS"tools:ignore="ProtectedPermissions" />
  • 代码实现
  • @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 List<StorageVolume> 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 minList<UsageStats> 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() 了,具体操作可以搜一下

    总结

    以上是生活随笔为你收集整理的Android获取安装应用Apk包大小 缓存大小 getPackageSizeInfo StorageManager的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。