Android获取已安装应用大小---参考学习

来源:互联网 发布:windows 找不到aero 编辑:程序博客网 时间:2024/06/11 12:49

最近需要获取手机中已安装应用的大小,查阅了一些资料,这里做个总结:
1,在我们可见调用的类中没有提供直接的方法来获取应用的大小,应用的大小分为了缓存大小(cachesize),数据大小(datasize),应用程序大小(codesize),但是PackageManager类有个getPackageSizeInfo方法如下:
public abstract void getPackageSizeInfo(String packageName,
IPackageStatsObserver observer);
只是这个方法是hide的,我们并不可以直接调用,所以我们需要用到反射,且涉及到AIDL
2,安装包得大小信息封装在PackageStats类中,我们需要获得安装包所对应的PackageStats对象,才可以获取我们需要的大小信息
3,以下为获取应用大小信息步骤:
第一步:
加入Android系统形成的AIDL文件:两个aidl文件写在android.content.pm包中,如图
1)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);

}

2)PackageStats.aidl代码如下:

package android.content.pm;
parcelable PackageStats;

第二步:创建一个类继承IPackageStatsObserver.Stub,实际为aidl文件形成的Bindler机制服务类,当把该类的一个实例通过getPackageSizeInfo()调用时,该函数继而启动中间流程去获取相关包得信息大小,最后将查询信息回调至该类的onGetStatsCompleted(in PackageStats pStats, boolean succeeded)方法中,代码如下:
//aidl文件形成的Bindler机制服务类
public class PkgSizeObserver extends IPackageStatsObserver.Stub {
private String totalSize;
private String pakgeName;
private long cachesize;
private long datasize;
private long codesize;

    public PkgSizeObserver(String pakgeName) {        this.pakgeName = pakgeName;    }    /*** 回调函数,     * @param pStats ,返回数据封装在PackageStats对象中     * @param succeeded  代表回调成功     */    @Override    public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)            throws RemoteException {        //缓存大小        cachesize = pStats.cacheSize;        //数据大小        datasize = pStats.dataSize;        //应用程序大小        codesize = pStats.codeSize;        totalSize = formateFileSize(pStats.cacheSize + pStats.dataSize + pStats.codeSize);        L.e("总大小---" + totalSize + "---缓存大小-----" + cachesize + "--数据大小----" + datasize + "--应用程序大小---" + codesize);    }}

//系统函数,字符串转换 long -String (kb)
private String formateFileSize(long size){
return Formatter.formatFileSize(mActivity, size);
}
第三步:下面我们就用到反射,直接调用第二步写好的类,上代码

//得到大小
public void queryPacakgeSize(String pkgName) throws Exception {
if (pkgName != null) {
//使用反射机制得到PackageManager类的隐藏函数getPackageSizeInfo
PackageManager pm =context.getPackageManager(); //得到pm对象
try {
//通过反射机制获得该隐藏函数
Method getPackageSizeInfo = PackageManager.class.getDeclaredMethod(“getPackageSizeInfo”, String.class, IPackageStatsObserver.class);

            //调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数            getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver(pkgName));        } catch (Exception ex) {            Log.e(TAG, "NoSuchMethodException");            ex.printStackTrace();            throw ex;  // 抛出异常        }    }}

到此我们就可以得到应用的大小了
4,这里说个坑,我在应用过程中发现,得到缓存,数据,应用大小的回调函数是在子线程中的,所以并不能在onGetStatsCompleted方法中更新UI,且我获取的是很多应用列表,想在item中写入大小,这里因为线程抢占时间不同,item更新并不能同时进行,可以观察手机设置中应用程序获取大小也并不是同时进行,所以如果需要列表设置应用大小注意处理线程问题

原创粉丝点击