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