CountDownLatch与AIDL获取应用软件大小结合使用实例

最近做东西的时候,需要获取应用软件大小,看了很多人写的方法,大同小异。今天就参考别人的代码加一些自己的理解。整理一下,分享给大家。
下面是AIDL相关方法获取应用大小的例子,这个网上也有很多。

应用的场景:要采集多个app 的应用相关信息,其中包括应用大小,然后和其他软件信息(包名,应用名称,应用图标等信息)一起上报信息。
这中间就涉及到一个问题:如何保证分别采集多个应用的其他信息完成后再一起上传?因 为获取size的上述方法一次只能获取一个应用的大小,而且获取应用其他信息的方法和应用大小属于异步操作。软件大小是通过上述方法单独获取,其他信息是通过其他方法获取。多个软件信息都要获取完,最终再执行上传操作。

解决办法: 使用回调和CountDownLatch,就可以解决上述情景。

1.AIDL文件
AIDL结构
根据上图结构在src/main/aidl/android.content.pm/ 目录下添加IPackageStatsObserver.aidl 和 packageStats.aidl 2个文件。
下面是这2个文件的内容:


IPackageStatsObserver.aidl

package android.content.pm;

import  android.content.pm.PackageStats;

oneway interface IPackageStatsObserver {

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

packageStats.aidl

package  android.content.pm;

parcelable PackageStats;

2.size大小获取

public void queryPackageSize(CountDownLatch latch,IQueryPkgSizeCallback callBack, Context context, String pkgName) throws Exception{
        if ( pkgName != null){
            //使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
            PackageManager pm = context.getPackageManager();  //得到pm对象
            try {
                //通过反射机制获得该隐藏函数
                Method getPackageSizeInfo = pm.getClass().getMethod("getPackageSizeInfo", String.class,IPackageStatsObserver.class);
                //调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数
                getPackageSizeInfo.invoke(pm, pkgName,new PkgSizeObserver(latch,callBack));
            }
            catch(Exception ex){
                Log.e(TAG, "NoSuchMethodException") ;
                ex.printStackTrace() ;
                throw ex ;  // 抛出异常
            }
        }
    }
    //aidl文件形成的Bindler机制服务类
    public class PkgSizeObserver extends IPackageStatsObserver.Stub{

        private IQueryPkgSizeCallback callback;
        private CountDownLatch latch;
        PkgSizeObserver(CountDownLatch latch,IQueryPkgSizeCallback callback){
            this.latch = latch;
            this.callback = callback;
        }

        /*** 回调函数,
         * @param pStats ,返回数据封装在PackageStats对象中
         * @param succeeded  代表回调成功
         */
        @Override
        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
                throws RemoteException {
            // TODO Auto-generated method stub
            Log.i(TAG,"PkgSizeObserver succeeded="+succeeded);
            if(succeeded){
                cachesize = pStats.cacheSize  ; //缓存大小n
                datasize = pStats.dataSize  ;  //数据大小
                codesize =  pStats.codeSize  ;  //应用程序大小
                totalsize = cachesize + datasize + codesize ;
                Log.i(TAG, "cachesize--->"+cachesize+" datasize---->"+datasize+ " codeSize---->"+codesize);
                callback.queryPkgSize(true,totalsize);
            }else{
                Log.i(TAG,"get size fail------>");
            }
            latch.countDown();//每成功获取一个app的值,计数器减1,直到计数器为0时,不在阻塞,执行后续任务
        }
    }

3.回调接口

 public interface IQueryPkgSizeCallback{
        void queryPkgSize(boolean isSucceed,long pkgTotalSize);
    }

4.CountDownLatch使用

 CountDownLatch latch = new CountDownLatch(list.size);//要请求的多个app的list集合,计数器的大小为list的大小
            if (list != null) {
                final ArrayList<对象名> apps = new ArrayList<>();//作为保存多个应用信息的list,最后返回的list
                for(final Iterator<对象名> iterator = list.iterator(); iterator.hasNext();) {
                    final 对象名 info = iterator.next();
                    try {
                        mModule.queryPackageSize(latch,new 类名.IQueryPkgSizeCallback() {
                            @Override
                            public void queryPkgSize(boolean isSucceed, long pkgTotalSize) {
                                if(isSucceed){
                                    Log.i(TAG,"getAllUserApp mAppInfoItem pkgName="+info.getAppPackage()+"  system_flag="+info.getAppSystemFlag()+" app size="+mModule.formateFileSize(AEmmApplicaton.getContext(),pkgTotalSize));
                                    info.setAppTotalSize(mModule.formateFileSize(AEmmApplicaton.getContext(),pkgTotalSize));
                                    InstallApp.AppData app = new InstallApp.AppData(info.getAppPackage(), info.getAppName(),
                                            info.getAppFirstInstallTime(), info.getAppVersion(), info.getAppImageToString(), info.getAppSystemFlag(), info.getAppTotalSize());
                                    apps.add(app);//每获取一个完整的应用信息,存入list里面
                                    Log.i(TAG,"succ----->mLock.unlock()");
                                }else{
                                    Log.i(TAG,"getAllUserApp queryPkgSize fail");
                                }
                            }
                        }, context,info.getAppPackage());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                try {
                    latch.await();
                    data = new InstallApp(apps);//计数器为0时,执行此处任务
                    Log.i(TAG, "----> latch.await()"+" app.size="+apps.size());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

至于对CountDownLatch使用的详细使用我就不详细讲述,网上有很多,如下链接可以参考:
http://www.importnew.com/15731.html

以上是内容主要是针对实际项目中用到的例子,结合网上关于获取软件大小的文章,做了一个综合性的演示。如果大家有什么问题,欢迎交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值