1. 获取应用数据/缓存大小
其中pm为实例化的PackageManager,因为需要遍历所有的已安装的应用。因此需要开启子线程进行处理。
还有需要注意的是,在Android4.2之前getPackageSizeInfo方法参数是没有第二个int类型的参数的,贴出来的代码适合4.2以后的版本,在反射获取方法时,增加了userHandle的参数信息。至于增加的参数userHandle的解释是:The user whose size information should be retrieved。我们是通过系统类的UserHandle.myUserId()获取。
还有需要注意的是,因为调用了远程服务,需要在自己的工程里引入两个aidl文件,分别是IPackageStatsObserver.aidl以及PackageStats.aidl,放在新建的android.content.pm包下。
private void scanCache() { pm = getPackageManager(); new Thread(){ @Override public void run() { List<PackageInfo> installedPackages = pm.getInstalledPackages(0); for( PackageInfo info : installedPackages){ try { Method myUserId = UserHandle.class.getDeclaredMethod("myUserId"); int userID = (Integer) myUserId.invoke(pm,null); Method getPackageSizeInfo = pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class, int.class, IPackageStatsObserver.class); getPackageSizeInfo.invoke(pm, info.packageName, userID, new MyDataObserver()); } catch (Exception e) { e.printStackTrace(); } } runOnUiThread(new Runnable() { @Override public void run() { //扫描结束后的UI操作 } }); } }.start(); } private class MyDataObserver extends IPackageStatsObserver.Stub{ @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { final long cache = pStats.cacheSize; //应用缓存的大小 long code = pStats.codeSize; long data = pStats.dataSize;//这里便可以拿到应用数据的大小 String packageName = pStats.packageName; ApplicationInfo appinfo = null; try { appinfo = pm.getApplicationInfo(packageName,0); final ApplicationInfo finalAppinfo = appinfo; runOnUiThread(new Runnable() { @Override public void run() { //拿到cache,处理UI } } }); } catch (Exception e) { e.printStackTrace(); } } }
2. 清理缓存
据我所知,是不可以在应用里根据包名只清理一个应用的缓存的,除非是系统级别的应用才有DELETE_CACHE_FILES权限。但是可以通过PackageManager的freeStorageAndNotify方法,声称需要一个比较大的内存空间,从而达到清理所有应用的缓存文件的目的。
同样需要注意添加IPackageDataObserver.aidl接口声明,包位置依旧是android.content.pm。
private void deleteAllCache() { pm = getPackageManager(); Method[] methods = PackageManager.class.getMethods(); for(Method method : methods){ if( "freeStorageAndNotify".equals(method.getName()) ) { try { method.invoke(pm,Long.MAX_VALUE,new MyPackageDataObserver()); } catch (Exception e) { e.printStackTrace(); } return; } } }同时在清理完成时,会回调onRemoveCompleted方法。比较适合做清理完毕后的UI逻辑。
本例是弹出一个对话框提示用户清理完毕。
private class MyPackageDataObserver extends IPackageDataObserver.Stub{ @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { runOnUiThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(CleanCacheActivity.this); builder.setMessage("恭喜,已清理所有垃圾"); builder.setTitle("提示"); builder.setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); builder.create().show(); } }); } }