计算Android App占用的各种空间大小

一个小需求:计算Android App所占用d的手机内存(RAM)大小、App所产生的数据(Data)大小、App本身所占用的磁盘空间(ROM)大小。当然,这个就必须用到PackageManager了。

1、查看Android中PackageManager源码,找到getPackageSizeInfo方法:

/**
  * Retrieve the size information for a package.
  * Since this may take a little while, the result will
  * be posted back to the given observer.  The calling context
  * should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission.
  *
  * @param packageName The name of the package whose size information is to be retrieved
  * @param observer An observer callback to get notified when the operation
  * is complete.
  * {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)}
  * The observer's callback is invoked with a PackageStats object(containing the
  * code, data and cache sizes of the package) and a boolean value representing
  * the status of the operation. observer may be null to indicate that
  * no callback is desired.
  *
  * @hide
  */
public  abstract  void  getPackageSizeInfo(String packageName,
   IPackageStatsObserver observer);

2、getPackageSizeInfo方法有两个参数,第一个是需要计算的App包名,第二个是一个回调。不过IPackageStatesObserver这个class在API里貌似找不到,找了点儿资料,需要通过Android AIDL的方式来搞。方法:

1)、在src目录下新建android.content.pm包

2)、在该包下新建PackageStats.aidl文件,内容如下:

package  android.content.pm;
   
parcelable PackageStats;

3)、在该包下新建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);
}

3、getPackageSizeInfo方法不能通过context.getPackageManager.getPackageSizeInfo的方式来调用,因为它其实是一个invoke受限的方法,所以必须通过反射实现:

/**
  * 获取Android Native App的缓存大小、数据大小、应用程序大小
  *
  * @param context
  *            Context对象
  * @param pkgName
  *            需要检测的Native App包名
  * @throws NoSuchMethodException
  * @throws InvocationTargetException
  * @throws IllegalAccessException
  */
public  static  void  getPkgSize( final  Context context, String pkgName)  throws  NoSuchMethodException,
         InvocationTargetException,
         IllegalAccessException {
     // getPackageSizeInfo是PackageManager中的一个private方法,所以需要通过反射的机制来调用
     Method method = PackageManager. class .getMethod( "getPackageSizeInfo" ,
             new  Class[] { String. class , IPackageStatsObserver. class  });
     // 调用 getPackageSizeInfo 方法,需要两个参数:1、需要检测的应用包名;2、回调
     method.invoke(context.getPackageManager(),  new  Object[] {
             pkgName,
             new  IPackageStatsObserver.Stub() {
                 @Override
                 public  void  onGetStatsCompleted(PackageStats pStats,  boolean  succeeded)  throws  RemoteException {
                     // 子线程中默认无法处理消息循环,自然也就不能显示Toast,所以需要手动Looper一下
                     Looper.prepare();
                     // 从pStats中提取各个所需数据
                     Toast.makeText(context,
                             "缓存大小="  + Formatter.formatFileSize(context, pStats.cacheSize) +
                             "\n数据大小="  + Formatter.formatFileSize(context, pStats.dataSize) +
                             "\n程序大小="  + Formatter.formatFileSize(context, pStats.codeSize),
                             Toast.LENGTH_LONG).show();
                     // 遍历一次消息队列,弹出Toast
                     Looper.loop();
                 }
             }
     });
}

我是直接在Observer回调中通过Toast的方式直接显示出来的,不过这个回调是在子线程中异步完成的,子线程中默认不处理消息循环,所以Toast.show无法被正确执行,需要手动将Toast显示部分的内容,加到Looper中,分别调用Looper.prepare和Looper.loop方法即可!

4、当然,根据PackageManager中getPackageSizeInfo注释中的提示,还需要在AndroidManifest.xml中加入permission:

< uses-permission  android:name = "android.permission.GET_PACKAGE_SIZE" ></ uses-permission >
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值