今天在制作仿小米安全中心时,遇到一个棘手的功能,清除缓存,很简单啊,心头一想,马上就想到了直接删除其他应用的cache dir.
public static long getSize(File file) throws Exception {
/**
*获取本包有没有缓存,没有就跳过
*@param file 传入的cache address,sdcard里为"/mnt/sdcard/packageName包名/cache/" 内部存储:"/data/data/包名/cache/"
**/
//删除指定包名的cache文件夹
static boolean delete(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
int size = 0;
if (children != null) {
size = children.length;
for (int i = 0; i < size; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
}
if (dir == null) {
return true;
} else {
return dir.delete();
}
}
然而, 这个做法是错误的
public abstract void getPackageSizeInfo(String packageName,
IPackageStatsObserver observer);
//见两个参数,包名和远程调用,在这里有的同学没学过远程通讯吧?贴下代码:
Class<? extends PackageManager> class1=mManager.getClass();//packagemanager mManager
Method method = null;
try {
method = class1.getMethod("getPackageSizeInfo",
String.class,IPackageStatsObserver.class);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
method.invoke(mManager,ai.packageName, new ClearPackageOvserver(ai));
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
首先创建一个包,名称是android.content.pm,必须是这个名字,IPackageStatsObserver是不关联代码的,在源码里找不到的,必须手动写
三个aidl的实现是:
* * 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 IPackageDataObserver { void onRemoveCompleted(in String packageName, boolean succeeded);}package android.content.pm; /**IPackageDataObserver aidl
package android.content.pm; import android.content.pm.PackageStats; /**IPackageStatsObserver aidl * 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); }
package android.content.pm; /**PackageStats
*/parcelable PackageStats;
getPackageSizeInfo的远程实现是:
/** * *getPackageSizeInfo(String packageName, *IPackageStatsObserver observer); 当调用了这个方法后,就会回调里面的 *onGetStatsCompleted方法并在pStats存储了相关的信息 **/ private class MyPackageOvserver extends IPackageStatsObserver.Stub{ @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { Log.i(pStats.packageName, pStats.cacheSize+" "+pStats.codeSize+" "+pStats.dataSize+" "+pStats.externalCacheSize); if(pStats.cacheSize!=0){ //有缓存 } } } //上面是获得了缓存的相关信息,那么下面就进行清理缓存的操作 try { Class clazz = mManager.getClass(); Method method = clazz.getMethod("freeStorageAndNotify", long.class,IPackageDataObserver.class); method.invoke(mManager, Long.MAX_VALUE,dataObserver); } catch (Exception e) { e.printStackTrace(); } //远程调用IpackageDataObserver的实现是: private IPackageDataObserver observer = new IPackageDataObserver.Stub() { @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { //删除完后的回调 } };
这个是第一种方法,下面进行第二种方法:
Context context = createPackageContext("你要获取的应用包名", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); //Class classz = context.getClassLoader().loadClass("com.example.MainActivity"); //Object object = classz.newInstance(); File file1=clazz.getMethod("getCacheDir").invoke(object); File file2=clazz.getMethod("getExternalCacheDir").invoke(object);
是不是简单很多呢,就这样就完成了,但就少了很多扩展性,看你选那一样咯