Proguard之后setBackgroundColor不起作用

时间:2014-02-25 16:56:34

标签: android obfuscation proguard

我正在努力完成一个项目,这是我第一次使用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看起来正在重新安排关于交换机的事情。

2 个答案:

答案 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)吗?如果是这样,请尝试在不进行优化的情况下使用,以减少修改代码的程度。