zoukankan      html  css  js  c++  java
  • [Android Pro] PackageManager#getPackageSizeInfo (hide)

     referce to : http://www.baidufe.com/item/8786bc2e95a042320bef.html

    计算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) +
                                "
    数据大小=" + Formatter.formatFileSize(context, pStats.dataSize) +
                                "
    程序大小=" + 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>

     

  • 相关阅读:
    关于开发 Web AI 的思考(kendryte K210)
    怪不得我说,这几个月的代码数据都跑哪里去了....
    在 Android 上使用蓝牙作为主机进行一对多从机传输数据的实测,理论 5
    写了一下 micropython 的文件系统单元测试
    mark 自己未来要写一下,蓝牙主机一对多从机和 K210 的网络通信优化过程。
    VUE实现Studio管理后台(五):手风琴式折叠组件(Accordion)
    VUE实现Studio管理后台(四):状态模式实现窗口停靠,灵动、自由
    VUE实现Studio管理后台(三):支持多语言国际化(vue-i18n)
    VUE实现Studio管理后台(二):Slot实现选项卡tab切换效果,可自由填装内容
    VUE实现Studio管理后台(一):鼠标拖放改变窗口大小
  • 原文地址:https://www.cnblogs.com/0616--ataozhijia/p/4673403.html
Copyright © 2011-2022 走看看