import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import android.app.Activity; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageStats; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.text.format.Formatter; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class CleanCacheActivity extends Activity { private TextView tv_scan_status; private ProgressBar pb; private PackageManager pm; private LinearLayout ll_container; private boolean flag = false; private long totalCleanSize = 0; private long tempCache; private View romoveview; private boolean isExitsCache = true; private Method getPackageSizeInfoMethod = null; //API隐藏的方法 private String cleanPackgename ; //要清理缓存的包名 private Toast toast; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_clean_cache); tv_scan_status = (TextView) findViewById(R.id.tv_scan_status); pb = (ProgressBar) findViewById(R.id.pb); ll_container = (LinearLayout) findViewById(R.id.ll_container); scanCache(); } /** * 扫描手机里面全部应用程序的缓存信息 */ private void scanCache() { pm = getPackageManager(); new Thread(){ public void run() { //1.先找到获取缓存的方法(这种方法是被API隐藏起来的。所以要先获取类的字节码。再反射) Method[] methods = PackageManager.class.getMethods(); for(Method method : methods){ if("getPackageSizeInfo".equals(method.getName())){ getPackageSizeInfoMethod = method; break; } } //2.在每个应用程序中使用该方法获取全部的缓存文件 List<PackageInfo> packInfos = pm.getInstalledPackages(0); pb.setMax(packInfos.size()); int progress = 0; for(PackageInfo packInfo : packInfos){ try { getPackageSizeInfoMethod.invoke(pm, packInfo.packageName, new MyDataObserver()); //子线程中运行 Thread.sleep(200); progress++; pb.setProgress(progress); } catch (Exception e) { e.printStackTrace(); } } if(progress >= packInfos.size()){ runOnUiThread(new Runnable() { @Override public void run() { tv_scan_status.setText("扫描完成..."); } }); } //所有扫描完成没有发现一个缓存 if(flag == false){ runOnUiThread( new Runnable() { public void run() { String text = "恭喜您手机非常干净。没有缓存须要清理"; showToast(text); tv_scan_status.setText("扫描完成。没发现缓存"); } }); } }; }.start(); } //请注意,这个父类的方法是在子线程中运行的,所以要更新UI界面的话,要在主线程 private class MyDataObserver extends IPackageStatsObserver.Stub{ @Override public void onGetStatsCompleted(final PackageStats pStats, boolean succeeded) throws RemoteException { final long cache = pStats.cacheSize; final ApplicationInfo appInfo; try { appInfo = pm.getApplicationInfo(pStats.packageName, 0); //更新界面 runOnUiThread(new Runnable() { @Override public void run() { tv_scan_status.setText("正在扫描"+appInfo.loadLabel(pm).toString()); if(cache > 0){ //有缓存信息的应用 flag = true;//存在缓存文件 totalCleanSize += cache; final View view = View.inflate(getApplicationContext(), R.layout.list_item_cacheinfo, null); TextView tv_cache_size = (TextView) view.findViewById(R.id.tv_cache_size); tv_cache_size.setText("缓存大小: "+ Formatter.formatFileSize(getApplicationContext(), cache)); TextView tv_name = (TextView) view.findViewById(R.id.tv_app_name); tv_name.setText(appInfo.loadLabel(pm).toString()); ImageView iv_icon = (ImageView) view.findViewById(R.id.iv_app_icon); iv_icon.setImageDrawable(appInfo.loadIcon(pm)); ImageView iv_clean = (ImageView) view.findViewById(R.id.iv_clean); iv_clean.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { tempCache = cache; cleanPackgename = appInfo.packageName; romoveview = view; Intent intent = new Intent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.addCategory("android.intent.category.DEFAULT"); intent.setData(Uri.parse("package:" + cleanPackgename)); startActivityForResult(intent, 0); } }); ll_container.addView(view, 0); } } }); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //请注意。这个父类的方法是在子线程中运行的。所以要更新UI界面的话,要在主线程 private class MyDataObserver2 extends IPackageStatsObserver.Stub{ @Override public void onGetStatsCompleted(final PackageStats pStats, boolean succeeded) throws RemoteException { isExitsCache = false; System.out.println(pStats.cacheSize); if(pStats.cacheSize > 0){ //还存在缓存 isExitsCache = true; } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //又一次查询一次看是否缓存已被清理 try { getPackageSizeInfoMethod.invoke(pm, cleanPackgename, new MyDataObserver2()); //子线程中运行 Thread.sleep(200); } catch (Exception e) { e.printStackTrace(); } if(isExitsCache){ }else{ //此缓存已经不存在了,更新界面 String text = "释放了"+Formatter.formatFileSize(getApplicationContext(), tempCache)+"的内存空间"; showToast(text); ll_container.removeView(romoveview); } super.onActivityResult(requestCode, resultCode, data); } //请注意。这个父类的方法是在子线程中运行的,所以要更新UI界面的话,要在主线程 private class MypackDataObserver extends IPackageDataObserver.Stub{ @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { runOnUiThread(new Runnable() { @Override public void run() { ll_container.removeAllViews(); String text = "释放了"+ Formatter.formatFileSize(getApplicationContext(), totalCleanSize)+ "的内存空间\n恭喜您手机非常干净,没有缓存须要清理"; showToast(text); totalCleanSize = 0; tv_scan_status.setText("缓存清理完成"); } }); } } /** * 清理手机的所有缓存 * freeStorageAndNotify() 为系统隐藏的API,所以要用反射把它找出来 * @param view */ public void cleanAll(View view){ Method[] methods = PackageManager.class.getMethods(); for(Method method : methods){ if("freeStorageAndNotify".equals(method.getName())){ try { method.invoke(pm, Integer.MAX_VALUE, new MypackDataObserver()); } catch (Exception e) { e.printStackTrace(); } } } } private void showToast(String text) { if(toast == null){ toast = Toast.makeText(getApplicationContext(), text, 0); }else{ toast.setText(text); toast.setDuration(0); } toast.show(); } }