通过反射和AIDI获取应用程序大小

来源:互联网 发布:手机五毛钱特效软件 编辑:程序博客网 时间:2024/06/05 10:14

     有的时候我们需要获取应该的大小或者应用的缓存信息,但是查看android API发现,并没有给我们提供这样的方法去操作。闲来无事,查看android的源代码发现,其实内部有这样的方法,只不过隐藏起来了,下面就绕过看源码的过程,直接说一下如何去使用和获取吧。

    1.首先,我们需要把android.content.pm.IPackageStatsObserver.aidl和android.content.pm.PackageStats.aidl拷贝到我们的项目中,注意包名一定要正确。看到这,相信很多就明白什么意思了,其实就是采用类似远程调用的方式,来获取应用信息。
    2.设计界面如下:

                                   


    3.通过包名、包管理器和反射技术来获取到应用的信息。(代码中都添加注释)

    主要代码:

    

package com.lds.getappsize;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import android.app.Activity;import android.content.pm.IPackageStatsObserver;import android.content.pm.PackageManager;import android.content.pm.PackageStats;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.os.RemoteException;import android.text.TextUtils;import android.text.format.Formatter;import android.util.Log;import android.view.View;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {private static final String TAG = "MainActivity";public static final int GET_APPSIZE_SUCCESS = 0;private EditText et_packname;//输入的包名private TextView tv_app_total_size;//应用程序总大小private TextView tv_app_size;//应用大小private TextView tv_app_data_size;//数据大小private TextView tv_app_cache_size;//缓存大小private long cacheSize;private long codeSize;private long dataSize;//消息处理器private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {tv_app_size.setText(Formatter.formatFileSize(getApplicationContext(), codeSize)+"");tv_app_cache_size.setText(Formatter.formatFileSize(getApplicationContext(), cacheSize)+"");tv_app_data_size.setText(Formatter.formatFileSize(getApplicationContext(), dataSize)+"");tv_app_total_size.setText(Formatter.formatFileSize(getApplicationContext(), codeSize+cacheSize+dataSize)+"");};};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                et_packname = (EditText) findViewById(R.id.et_packname);        tv_app_total_size = (TextView) findViewById(R.id.tv_app_total_size);        tv_app_size = (TextView) findViewById(R.id.tv_app_size);        tv_app_data_size = (TextView) findViewById(R.id.tv_app_data_size);        tv_app_cache_size = (TextView) findViewById(R.id.tv_app_cache_size);            }        public void click(View view){    String packageName = et_packname.getText().toString().trim();    if(TextUtils.isEmpty(packageName)){    Toast.makeText(this, "包名不能为空", 0).show();    return;    }    /**     * 查询包大小的方法     */    queryPackageSize(packageName);    }    /**     * 查询包大小     * @param packageName     */private void queryPackageSize(String packageName) {//查询包大小,使用的是packageManager中的getPackageSizeInfo方法,但是此方法被隐藏,我们可以通过反射的方法获取到PackageManager pm = getPackageManager();Method[] methods = pm.getClass().getDeclaredMethods();for(Method method : methods){//得到所有的方法Log.i(TAG, method.getName());if(method.getName().equals("getPackageSizeInfo")){try {method.invoke(pm, packageName,new MyObserver());break;} catch (Exception e) {e.printStackTrace();}}//第二种方法://通过反射机制获得该隐藏函数//Method method = pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class,IPackageStatsObserver.class);//调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数//method.invoke(pm, packageName,new PkgSizeObserver());}}/** * 根据aidl文件生成的Bindler机制服务类 * @author Administrator * */private class MyObserver extends IPackageStatsObserver.Stub{/** * 回调函数 * pStats 返回数据封装在对象中 * succeeded 代表返回是否成功 */@Overridepublic void onGetStatsCompleted(PackageStats pStats, boolean succeeded)throws RemoteException {cacheSize = pStats.cacheSize;codeSize = pStats.codeSize;dataSize = pStats.dataSize;Log.i(TAG, "缓存大小:"+cacheSize);Log.i(TAG, "应用大小:"+codeSize);Log.i(TAG, "数据大小:"+dataSize);Message msg = Message.obtain();handler.sendEmptyMessage(GET_APPSIZE_SUCCESS);}}}


 

    代码下载

0 0
原创粉丝点击