通过查看手机设置(setting)源代码,发现它里面获取应用大小和缓存大小是通过PackageManager里面的getPackageSizeInfo方法。然而此方法时私有的,因此通过反射调用此方法。里面要用到IPackageStatsObserver接口,它是一个aidl方式进行访问。
package cn.itcast.testclear; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import android.app.Activity; import android.app.ListActivity; import android.content.Intent; import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageStats; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.view.ViewGroup; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; public class DemoActivity extends ListActivity { private PackageManager pm; private ListView lv; private MyAdapter adapter; private Map<String, CacheInfo> maps; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); pm = getPackageManager(); maps = new HashMap<String, CacheInfo>(); lv = getListView(); // lv.setAdapter(adapter); // 1.获取所有的安装好的应用程序 List<PackageInfo> packageinfos = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES); for (PackageInfo info : packageinfos) { String name = info.applicationInfo.loadLabel(pm).toString(); String packname = info.packageName; CacheInfo cacheinfo = new CacheInfo(); cacheinfo.setName(name); cacheinfo.setPackname(packname); maps.put(packname, cacheinfo); getAppSize(packname); } adapter = new MyAdapter(); lv.setAdapter(adapter); lv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { /* * * <intent-filter> <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" /> <category * android:name="android.intent.category.DEFAULT" /> <data android:scheme="package" /> </intent-filter> */ /* * 2.2 <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" * /> <category android:name="android.intent.category.VOICE_LAUNCH" /> </intent-filter> */ System.out.println("haha"); Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); intent.addCategory("android.intent.category.DEFAULT"); intent.addCategory("android.intent.category.VOICE_LAUNCH"); CacheInfo info = (CacheInfo) lv.getItemAtPosition(position); intent.putExtra("pkg", info.getPackname());//传递所在包 startActivity(intent); } }); } /** * 根据包名获取应用程序的体积信息 注意: 这个方法是一个异步的方法 程序的体积要花一定时间才能获取到. * * @param packname */ private void getAppSize(final String packname) { try { Method method = PackageManager.class.getMethod("getPackageSizeInfo", new Class[]{String.class, IPackageStatsObserver.class}); method.invoke(pm, new Object[]{packname, new IPackageStatsObserver.Stub() { public void onGetStatsCompleted(PackageStats pStats,boolean succeeded) throws RemoteException { // 注意这个操作是一个异步的操作 long cachesize = pStats.cacheSize; long codesize = pStats.codeSize; long datasize = pStats.dataSize; CacheInfo info = maps.get(packname); info.setCache_size(TextFormater.getDataSize(cachesize)); info.setData_size(TextFormater.getDataSize(datasize)); info.setCode_size(TextFormater.getDataSize(codesize)); maps.put(packname, info); } }}); } catch (Exception e) { e.printStackTrace(); } } private class MyAdapter extends BaseAdapter { private Set<Entry<String, CacheInfo>> sets; private List<CacheInfo> cacheinfos; public MyAdapter() { sets = maps.entrySet(); cacheinfos = new ArrayList<CacheInfo>(); for (Entry<String, CacheInfo> entry : sets) { cacheinfos.add(entry.getValue()); } } public int getCount() { return cacheinfos.size(); } public Object getItem(int position) { return cacheinfos.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View view = null; CacheInfo info = cacheinfos.get(position); if (convertView == null) { view = View.inflate(DemoActivity.this, R.layout.item, null); } else { view = convertView; } TextView tv_cache_size = (TextView) view.findViewById(R.id.tv_cache_size); TextView tv_code_size = (TextView) view.findViewById(R.id.tv_code_size); TextView tv_data_size = (TextView) view.findViewById(R.id.tv_data_size); TextView tv_name = (TextView) view.findViewById(R.id.tv_name); tv_cache_size.setText(info.getCache_size()); tv_code_size.setText(info.getCode_size()); tv_data_size.setText(info.getData_size()); tv_name.setText(info.getName()); return view; } } }
package cn.itcast.testclear; public class CacheInfo { //应用名称 private String name; //应用所在包名 private String packname; // private String code_size; //数据大小 private String data_size; //缓存大小 private String cache_size; }
public class TextFormater { /** * 返回byte的数据大小对应的文本 * * @param size * @return */ public static String getDataSize(long size) { if (size < 0) { size = 0; } DecimalFormat formater = new DecimalFormat("####.00"); if (size < 1024) { return size + "bytes"; } else if (size < 1024 * 1024) { float kbsize = size / 1024f; return formater.format(kbsize) + "KB"; } else if (size < 1024 * 1024 * 1024) { float mbsize = size / 1024f / 1024f; return formater.format(mbsize) + "MB"; } else if (size < 1024 * 1024 * 1024 * 1024) { float gbsize = size / 1024f / 1024f / 1024f; return formater.format(gbsize) + "GB"; } else { return "size: error"; } } /** * 返回kb的数据大小对应的文本 * * @param size * @return */ public static String getKBDataSize(long size) { if (size < 0) { size = 0; } return getDataSize(size * 1024); } }
aidl文件:IPackageStatsObserver.aidl
/* ** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ 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); }
PackageStats.aidl
/* //device/java/android/android/view/WindowManager.aidl ** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ package android.content.pm; parcelable PackageStats;