今天遇到个的问题,一个sdk 通过反射的方法查找资源id
public static int getIdByName(Context context, String className, String name) {
String packageName = context.getPackageName();
Class r = null;
int id = 0;
try {
r = Class.forName(packageName + ".R");
Class[] classes = r.getClasses();
Class desireClass = null;
for (int i = 0; i < classes.length; ++i) {
if (classes[i].getName().split("\\$")[1].equals(className)) {
desireClass = classes[i];
break;
}
}
if (desireClass != null)
id = desireClass.getField(name).getInt(desireClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return id;
}
发现正常debug的apk可以正常获取,混淆后的就不可以了。
到底为什么呢 。
现有个例子 一个包名为xxxx.xxxxx.games的debug包反编译后是可以xxxx.xxxxx.games文件夹下看到如下文件
可以正常看到对应的R文件
那么混淆后的呢
由于我代码里面没有在xxxx.xxxxx.games的类,所以混淆的apk反编译后就找不到上面的文件夹了,那么R文件去呗混淆到哪了呢
反编译后找到一点蛛丝马迹,看起来是被全部打乱了
也就导致了原来的代码不起作用了
加上如下方法不生效
-keepclassmembers class **.R$* {
public static <fields>;
}
加上下面的方法后就可以保证整个R文件不被混淆了
-keep class **.R$* { *; }
但是一开始的方法依然拿不到值。通过对比未混淆和混淆后的文件对比如下
方法通过反射R,查找R的子类,但是混淆后R文件是空的,子类被分割成了单个文件,不混淆的是有链接的(暂称为链接吧,猜测左侧代码是告诉dalvik,下面的文件都是我的子类,加载的时候加载到我的名下)。混淆后则没了链接,子类以单独类存在,不会放到R下,所以反射找不到了。
最终使用
getResources().getIdentifier("activity_main", "layout",getPackageName());
可以正常获取id