清除手机缓存
工程目录如下:
需要的aidl文件:上面三个文件对应的文件内容(包名和内容必须一致)
package android.content.pm; /** API包数据变化相关的软件包管理器的回调。
*一些使用场景包括删除缓存目录,生成
*统计相关代码、数据缓存的使用(TODO) * {@hide} 代表在源码中是隐藏的 */ oneway interface IPackageDataObserver { void onRemoveCompleted(in String packageName, boolean succeeded); }
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); }
package android.content.pm; parcelable PackageStats;
主活动MainActivity.java
/* 清理缓存(getCacheDir();//data/data/包名/cache目录): IPackageStatsObserver.aidl与PackageStats.aidl用来获取缓存信息 IPackageDataObserver.aidl用来清理缓存 */ public class MainActivity extends Activity { private PackageManager pm; private TextView appInfo;//显示获取到的软件缓存的大小 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); appInfo = (TextView) findViewById(R.id.appInfo); getFilesDir();//data/data/包名/files/ getCacheDir();//data/data/包名/cache目录 scanCache();//扫描缓存 findViewById(R.id.btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //一键清除所有缓存的单击事件 clearAllCache(); } }); } /** * 扫描手机里所有应用程序的缓存信息 * 安卓源码中是通过pm.getPackageSizeInfo()方法得到缓存大小的,但是这个方法被隐藏了, * 我们不能直接调用这个方法,所以只能通过反射了 * 需要的权限:<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/> */ private void scanCache() { pm = getPackageManager(); new Thread(){ public void run() { Method getPackageSizeInfoMethod = null ; //获得这个类的所有方法 Method[] methods = PackageManager.class.getMethods(); for (Method method : methods) { //getPackageSizeInfo这个方法可以获取缓存大小(谷歌将这个方法隐藏了,不能直接调用) if("getPackageSizeInfo".equals(method.getName())){ getPackageSizeInfoMethod=method;//得到这个方法 } } //获取所有程序的包名 List<PackageInfo> packInfos = pm.getInstalledPackages(0); for (PackageInfo info : packInfos) { try { //使用通过反射得到的方法来获取缓存信息. 会执行MyDataObserver类中的onGetStatsCompleted方法 getPackageSizeInfoMethod.invoke(pm, info.packageName,new MyDataObserver()); Thread.sleep(300);//稍微睡下,这样才能看到界面上显示的扫描信息 } catch (Exception e) { e.printStackTrace(); } } }; }.start(); } /** * 继承远程接口 */ private class MyDataObserver extends IPackageStatsObserver.Stub{ @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { try { //注意:该方法是在子线程中运行的 final long cache = pStats.cacheSize;//缓存的大小 long code = pStats.codeSize;//该软件代码的大小 long data = pStats.dataSize;//数据的大小 String packname = pStats.packageName;//程序包名 final ApplicationInfo appInfo = pm.getApplicationInfo(packname, 0); runOnUiThread(new Runnable() { @Override public void run() { String appName = appInfo.loadLabel(pm).toString();//通过包名获取软件名 MainActivity.this.appInfo.setText("正在扫描:"+appName); if(cache > 0){//有些软件是没有缓存的 /* 这里可以在布局文件中创建一个布局,然后在这里创建一个布局(程序名,缓存大小,清除按钮)添加到这个布局中, ....让需要清理缓存的程序和缓存的大小显示出来,并为按钮设置单击事件 */ System.out.println(appName+"缓存的大小:"+Formatter.formatFileSize(getApplicationContext(), cache)); //清理缓存,这里我直接清理所有缓存,其实可以在上面添加的布局中为清除按钮设置单击事件,在单击事件中进行清除缓存 //clearCache(appInfo.packageName); } } }); } catch (NameNotFoundException e) { e.printStackTrace(); } } } /** * 通过包名清除缓存,清除缓存也需要利用反射才能得到清除缓存的方法 * 需要的权限:<uses-permission android:name="android.permission.DELETE_CACHE_FILES"/> * 但是很可惜,这个权限只有系统的app才能注册,所以不能直接去清除缓存了,如果想点击按钮单独清理某个程序的缓存, * 就只能跳转到系统清理软件缓存的页面了. * 但是,我们可以实现一键全部清除,这个也是利用安卓系统的bug,我们发送一个广播告诉安卓系统,我们需要200G的内存, * 安卓系统收到通知,发现现在可用的内存空间不足,所以就会去清除所有的缓存了,这样也就达到了我们的目的 */ private void clearCache(String packageName) { try { //通过反射指定方法名和参数得到清理缓存的方法 Method method = PackageManager.class.getMethod("deleteApplicationCacheFiles", String.class,IPackageDataObserver.class); //执行方法清除缓存,清楚后会执行MypackDataObserver类里的onRemoveCompleted方法 method.invoke(pm, packageName,new MypackDataObserver()); } catch (Exception e) { e.printStackTrace(); } } /** * 清除全部缓存,需要的权限: * <uses-permission android:name="android.permission.CLEAR_APP_CACHE"/> */ public void clearAllCache(){ try { Method[] methods = PackageManager.class.getMethods(); for (Method method : methods) { if("freeStorageAndNotify".equals(method.getName())){ //告诉系统,我需要Integer.MAX_VALUE这么大的内存空间,系统现在可用空间小于这么多就会去清除缓存 method.invoke(pm, Long.MAX_VALUE,new MypackDataObserver()); return; } } } catch (Exception e) { e.printStackTrace(); } } /** * 清除缓存的远程接口服务类 */ private class MypackDataObserver extends IPackageDataObserver.Stub{ @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { //String appName = pm.getApplicationInfo(packageName, 0).loadLabel(pm).toString(); if(succeeded){ System.out.println(packageName+"的缓存清除成功"); }else{ System.out.println(packageName+"的缓存清除失败"); } } } }
可以只有清除缓存,利用代码跳转到这个界面
效果图: