在开发一键清缓存的功能时,缓存清除成功,当使用反射调用IPackageStatsObserver.class 这个类时,系统提示错误:
java.lang.NoSuchMethodException: getPackageSizeInfo [class java.lang.String, interface android.content.pm.IPackageStatsObserver]
W/System.err(12295): at java.lang.Class.getConstructorOrMethod(Class.java:460)
W/System.err(12295): at java.lang.Class.getDeclaredMethod(Class.java:685)
字面意思很简单没有找到该方法,但是查看我的源码,包导入正常,
只能查看自己的代码,找到出错的位置
/**
* 取得指定包名的程序的缓存大小
*/
private void queryPkgCacheSize(String pkgName) throws Exception {
if (!TextUtils.isEmpty(pkgName)) {// pkgName不能为空
// 使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
if (mPackageManager == null) {
mPackageManager = getContext().getPackageManager();// 得到被反射调用函数所在的类对象
}
try {
// the requested method's name.
String strGetPackageSizeInfo = "getPackageSizeInfo";
// 通过反射机制获得该隐藏函数
Method getPackageSizeInfo = mPackageManager.getClass()
.getDeclaredMethod(strGetPackageSizeInfo, String.class,// getPackageSizeInfo方法的参数类型
IPackageStatsObserver.class);// getPackageSizeInfo方法的参数类型
// 调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数
getPackageSizeInfo.invoke(mPackageManager,// 方法所在的类
pkgName, mStatsObserver);// 方法使用的参数
} catch (Exception ex) {
Log.wtf("tag", "queryPkgSize()-->NoSuchMethodException");
ex.printStackTrace();
throw ex; // 抛出异常
}
}
}是.getDeclaredMethod()方法报错的。
经查看,我调用反射类IPackageDataObserver.class;却没有报错,调用方法为
/**
* 执行清除缓存操作
*/
private void clearCache() {
totalCacheSize = 0l;// 初始化
queryToatalCache();// 给cacheSize赋值
try {
if (mPackageManager == null) {
mPackageManager = getContext().getPackageManager();// 得到被反射调用函数所在的类对象
}
String methodName = "freeStorageAndNotify";// 想通过反射机制调用的方法名
Class<?> parameterType1 = Long.TYPE;// 被反射的方法的第一个参数的类型
Class<?> parameterType2 = IPackageDataObserver.class;// 被反射的方法的第二个参数的类型
Method freeStorageAndNotify = mPackageManager.getClass().getMethod(
methodName, parameterType1, parameterType2);
/*
* freeStorageSize : The number of bytes of storage to be freed by
* the system. Say if freeStorageSize is XX, and the current free
* storage is YY, if XX is less than YY, just return. if not free
* XX-YY number of bytes if possible.
*/
Long freeStorageSize = Long.valueOf(getDataDirectorySize());
freeStorageAndNotify.invoke(mPackageManager, freeStorageSize,
new IPackageDataObserver.Stub() {
@Override
public void onRemoveCompleted(String packageName,
boolean succeeded) throws RemoteException {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}获取方法时用的是:
getMethod()
果断试试换种写法:
/**
* 取得指定包名的程序的缓存大小
*/
private void queryPkgCacheSize(String pkgName) throws Exception {
if (!TextUtils.isEmpty(pkgName)) {// pkgName不能为空
// 使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
if (mPackageManager == null) {
mPackageManager = getBaseContext().getPackageManager();// 得到被反射调用函数所在的类对象
}
try {
String methodName = "getPackageSizeInfo";// 想通过反射机制调用的方法名
Class<?> parameterType1 = String.class;// 被反射的方法的第一个参数的类型
Class<?> parameterType2 = IPackageStatsObserver.class;// 被反射的方法的第二个参数的类型
Method getPackageSizeInfo = mPackageManager.getClass().getMethod(
methodName, parameterType1, parameterType2);
getPackageSizeInfo.invoke(mPackageManager,// 方法所在的类
pkgName, mStatsObserver);// 方法使用的参数
} catch (Exception ex) {
Log.wtf("tag", "queryPkgSize()-->NoSuchMethodException");
ex.printStackTrace();
throw ex; // 抛出异常
}
}
}
/**
* 使用Android系统中的AIDL文件,获得指定程序的大小。AIDL文件形成的Binder机制
*/
private IPackageStatsObserver.Stub mStatsObserver = new IPackageStatsObserver.Stub() {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
long tmp = totalCacheSize;
totalCacheSize += pStats.cacheSize;// 累加
if (tmp != totalCacheSize) {// 总缓存大小有变化
mHandler.sendEmptyMessage(MSG_UPDATE_TOAST_TEXT);
}
}
};果然,
totalCacheSize就能获取到相对应的数值。
问题解决。不过,我也没发现这个
getMethod()和getDeclaredMethod()差异性在哪里?
getDeclaredMethod*()获取的是类自身声明的所有方法,包含public、protected和private方法。
getMethod*()获取的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法。
平常没留心,这时候很容易出错。这两个不是可以随意更换的。
上源码:http://download.csdn.net/detail/yql44137228/7676871
在实现一键清除缓存功能时,通过反射调用IPackageStatsObserver.class 出现java.lang.NoSuchMethodException: getPackageSizeInfo。错误源于使用了错误的方法获取类的构造器或方法。经过排查,问题出在getMethod()与getDeclaredMethod()的误用上。getDeclaredMethod()用于获取类自身声明的所有方法,而getMethod()则获取类的所有共有方法,包括继承和接口实现的public方法。正确使用方法解决了问题。

3613

被折叠的 条评论
为什么被折叠?



