Android清除所有应用的缓存(包括系统应用)的两种实现方法

今天在制作仿小米安全中心时,遇到一个棘手的功能,清除缓存,很简单啊,心头一想,马上就想到了直接删除其他应用的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();
	        }
	    }

然而, 这个做法是错误的 .逻辑是没问题的,就是找出所有应用的资料存储位置,然后删除cache文件夹里的内容,但经实践,这是不能执行的,要能这么轻松就能删除,那么很多应用都可以随意地删除其他应用的文件.实际上,是需要绕一些弯的,android是不允许擅自删除其他应用的文件的,不希望我们去调用它,最后我发现了:一个private的方法隐藏在源码里:那就是 PackageManager里的方法


 public abstract void getPackageSizeInfo(String packageName,
               IPackageStatsObserver observer);
//见两个参数,包名和远程调用,在这里有的同学没学过远程通讯吧?贴下代码:

Class 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的实现是:



package android.content.pm;
/**IPackageDataObserver 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;

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); 

是不是简单很多呢,就这样就完成了,但就少了很多扩展性,看你选那一样咯




你可能感兴趣的:(android,android,应用,缓存,清除缓存,远程调用)