一个小需求:计算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(),             pkgName, new IPackageStatsObserver.Stub() {                @Override                public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {                    // 从pStats中提取各个所需数据                    Log.i(TAG, "缓存大小=" + Formatter.formatFileSize(context, pStats.cacheSize));                    Log.i(TAG, "数据大小=" + Formatter.formatFileSize(context, pStats.dataSize));                    Log.i(TAG, "程序大小=" + Formatter.formatFileSize(context, pStats.codeSize));                }            });    }

我是直接在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" />

更多相关文章

  1. Android获得当前正在显示的activity类名的方法
  2. Android实现获取SERIAL信息的方法
  3. Ubuntu 12.04下面设别无法识别android设备的解决方法
  4. Android的图形与图像处理之一 使用简单图片&绘图
  5. android基础知识06:intent和intentfilter
  6. android从fragment进入activity再返回实现刷新fragment的做法
  7. 20189200余超 2018-2019-2 移动平台应用开发实践第六周作业
  8. 在Android中实现RN的自定义Native Modeule
  9. android 指定打包资源文件的方法

随机推荐

  1. Monkey
  2. Android 屏幕常亮
  3. android indication
  4. Android中实现Gallery 点击放大
  5. Android UI开发第十七篇――Android Frag
  6. Android 深入研究LBS(基于位置的服务)
  7. AndroidManifest.xml 系统找不到指定的文
  8. Android Studio将so打包jar供其他项目引
  9. Android之Loader理解
  10. Android使用了ProGuard时注意的事项