一、反射获得缓存大小:
获得各个应用程序缓存大小,需要使用getPackageSizeInfo方法(可以成系统app setting中查到),它是PackageManager的公共方法,但它被隐藏了。所有要用反射调用该方法。
* @hide
*/
public abstract void getPackageSizeInfo(String packageName, int userHandle,
IPackageStatsObserver observer);
1.在IPackageStatsObserver接口的子类中获得各种数据:
IPackageStatsObserver.Stub是android.content.pm由aidl文件自动生成的.具体文件如下图:
private class MyPackageStatsObserver extends IPackageStatsObserver.Stub {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
if (pStats.cacheSize > 0) {
try {
CacheInfo info = new CacheInfo();
info.packName = pStats.packageName;
info.cacheSize = pStats.cacheSize;
info.codeSize = pStats.codeSize;
info.dataSize = pStats.dataSize;
PackageInfo pinfo = pm
.getPackageInfo(pStats.packageName, 0);
info.appName = pinfo.applicationInfo.loadLabel(pm)
.toString();
info.icon = pinfo.applicationInfo.loadIcon(pm);
cacheInfos.add(info);
System.out.println("应用名称: " + info.appName + ", codesize: "
+ info.codeSize);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.反射找到getPackageSizeInfo()方法,并调用该方法:
Method method = PackageManager.class.getMethod("getPackageSizeInfo", String.class,
IPackageStatsObserver.class);method.invoke(pm, info.packageName, new MyPackageStatsObserver());
二、清除所有应用的缓存
也利用PackageManager中隐藏的公共方法
记得加权限:<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer);
1 定义IPackageDataObserver 接口子类:
private class MyPackageDataObserver extends IPackageDataObserver.Stub {
@Override
public void onRemoveCompleted(String packageName, boolean succeeded)
throws RemoteException {
System.out.println("清理完成!");
handler.sendEmptyMessage(RESCAN);
}
}
2. 反射获得freeStorageAndNotify方法,并调用
Method method = PackageManager.class.getMethod(
"freeStorageAndNotify", long.class,
IPackageDataObserver.class);
method.invoke(pm, Long.MAX_VALUE, new MyPackageDataObserver()); //这个值要大于你手机的可用内存。
三、清除cache低层实现(cache是私有的,怎么能被其他应用清除?)
在PackageManagerService的freeStorageAndNotify的方法中:
retCode = mInstaller.freeCache(freeStorageSize);
mInstaller定义:final Installer mInstaller;在PackageManagerService的构造函数中会new出来。
Installer:里面是使用LocalSocket实现的。
大致过程如下:mInstaller通过LocalSocket与本地的Socket服务器进行连接,并把intfreeStorageSize转换成字节数组,前两个字节为命令长度,后面是内容。最后把字节数组写进socket的输出流中。
但服务器怎么具体工作的不是很清楚。
LocalSocketImpl 类中
private native void connectLocal(FileDescriptor fd, String name,
int namespace) throws IOException;
四、清除缓存在真机上测试不通过,只能在模拟器上运行。
{
try
{
Class localClass = this.B.getClass();
Class[] arrayOfClass = new Class[2];
arrayOfClass[0] = Long.TYPE;
arrayOfClass[1] = IPackageDataObserver.class;
Method localMethod = localClass.getMethod("freeStorageAndNotify", arrayOfClass);
StatFs localStatFs = new StatFs(Environment.getDataDirectory().getPath());
Long localLong = Long.valueOf(localStatFs.getBlockSize() * localStatFs.getBlockCount() - 1L);
PackageManager localPackageManager = this.B;
Object[] arrayOfObject = new Object[2];
arrayOfObject[0] = localLong;
arrayOfObject[1] = new h(this);
localMethod.invoke(localPackageManager, arrayOfObject);
return;
}
<uses-permission android:name="android.permission.PERMISSION_NAME" />
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
最后查出原因了:是我手机内存大了(10G的内存没用),我设置的值太小(Integer.MAX_VALUE)。换成Long.MAX_VALUE就好了。
如下图所示:Integer.MAX_VALU= 2147483647(2E10),而现在还有10E11的可用,所有不会清除。