我正在努力完成一个项目,这是我第一次使用Proguard
。我有一个方法来设置活动本身的背景颜色以及一些按钮。在Proguard
之前一切正常。 Proguard
后未设置颜色。
之前:
public void setBackgroundColor(String color, View background){
String id = "1";
try {
ColorId myObject = new ColorId();
Method method = ColorId.class.getMethod(color);
id = (String) method.invoke(myObject);
} catch (Exception e) {
e.printStackTrace();
id = "1";
}
int thisColor = Integer.valueOf(id);
switch(thisColor) {
case 0://black
background.setBackgroundColor(0xff000000);
break;
case 1://white
background.setBackgroundColor(0xffffffff);
break;
case 2://red
background.setBackgroundColor(0xffCC0000);
break;
...
default:
background.setBackgroundColor(0xff0099cc);
break;
}
}
后:
public void a(String paramString, View paramView){
try {
c localc = new c();
str = (String)c.class.getMethod(paramString, new Class[0]).invoke(localc, new Object[0]);
switch (Integer.valueOf(str).intValue()){
default:
paramView.setBackgroundColor(-16737844);
return;
}
}catch (Exception localException){
for (;;){
localException.printStackTrace();
String str = "1";
}
paramView.setBackgroundColor(-16777216);
return;
}
paramView.setBackgroundColor(-1);
return;
paramView.setBackgroundColor(-3407872);
return;
paramView.setBackgroundColor(-16737844);
return;
paramView.setBackgroundColor(-8355712);
return;
paramView.setBackgroundColor(-6697984);
return;
paramView.setBackgroundColor(-17613);
return;
paramView.setBackgroundColor(-5609780);
return;
paramView.setBackgroundColor(-35700);
}
任何人都可以帮助解释这里发生的事情,以及如何在混淆之后使这种方法(以及将来的其他方法)再次发挥作用?对我而言,Proguard
看起来正在重新安排关于交换机的事情。
答案 0 :(得分:0)
Proguard通过重命名类和方法以缩短名称并删除未引用的代码来缩短代码。您的代码无效,因为Proguard重命名或删除了ColorId
方法black()
,white()
和red()
。要使用反射,您需要添加Proguard keep
指令,以告知它保留这些方法并保留其原始名称。
我没有解释为什么“后”代码的switch语句搞砸了。你确定你正确反编译了吗?
为什么“之前”代码如此错综复杂?它使用反射按颜色名称查找方法,然后调用它将颜色名称转换为String,解析String以获取整数代码,将整数代码装入整数,取消装箱,使用switch语句选择一个颜色值,然后设置背景颜色,复制每个开关分支中的background.setBackgroundColor()
调用(打破DRY原则)。
反射是在动态加载代码等特殊情况下使用的极端工具。
在HashMap中查找颜色名称会更简单,更快速,更清晰:
static final int DEFAULT_COLOR = 0xff0099cc;
static final Map<String, Integer> colors = new HashMap<String, Integer>();
static {
colors.put("black", 0xff000000);
colors.put("white", 0xffffffff);
colors.put("red", 0xffCC0000);
}
public void setBackgroundColor(String color, View view) {
Integer colorInteger = colors.get(color);
int colorValue = colorInteger == null ? DEFAULT_COLOR : colorInteger.intValue();
view.setBackgroundColor(colorValue);
}
如果必须将颜色作为字符串名称传入,则此HashMap是一个不错的选择。但是如果你可以改变颜色参数,那么枚举将更安全,更简单,更快:
public enum Color {
BLACK(0xff000000), WHITE(0xffffffff), RED(0xffCC0000), DEFAULT(0xff0099cc);
final int value;
Color(int value) { this.value = value; }
}
public void setBackgroundColor(Color color, View view) {
view.setBackgroundColor(color.value);
}
[最好在Android资源文件(colors.xml)中定义所有颜色值。您可以按资源ID号查找它们。]
答案 1 :(得分:0)
您的proguard设置是什么?发布您的proguard-project.txt文件(如果您使用旧方法,则发布proguard.cfg)。我建议关闭混淆,以更清楚地看到代码是如何被更改的。使用'-dontobfuscate'。
'after'代码看起来很奇怪。您使用的是优化通用配置文件(proguard-android-optimize.txt)吗?如果是这样,请尝试在不进行优化的情况下使用,以减少修改代码的程度。