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

来源:互联网 发布:淘宝卖aj鞋子的好店 编辑:程序博客网 时间:2024/06/16 19:03

最近做东西的时候,需要获取应用软件大小,看了很多人写的方法,大同小异。今天就参考别人的代码加一些自己的理解。整理一下,分享给大家。
下面是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
原创粉丝点击