2014-02-25 60 views
0

我正在完成一個項目,這是我第一次使用Proguard。我有一個方法來設置活動本身的背景顏色以及一些按鈕。之前Proguard一切工作正常。 Proguard之後顏色未設置。在Proguard後,setBackgroundColor無效

前:

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

你試着編輯「After」代碼嗎? – Jorgesys

+0

不,後代碼是Proguard文件反編譯後的樣子。該代碼不再適用於該設備。 – Josh

回答

0

Proguard通過重命名類和方法來縮短代碼,以縮短名稱並刪除未引用的代碼。您的代碼不起作用,因爲Proguard重命名或刪除了ColorId方法black()white()red()。要使用反射,您需要添加Proguard keep指令以告訴它保留這些方法並保留其原始名稱。

我沒有解釋爲什麼「後」代碼的switch語句混亂了。你確定你正確地反編譯了嗎?

爲什麼「之前」的代碼如此錯綜複雜?它使用反射通過顏色名稱查找方法,然後調用它將顏色名稱轉換爲字符串,解析字符串以獲取整數代碼,將整數代碼框裝入整數,對其進行取消裝箱,使用switch語句選擇一個顏色值,然後設置背景顏色,在每個開關分支中複製調用(打破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是如果顏色將被傳遞作爲一個字符串名稱一個不錯的選擇。但是,如果你可以改變顏色的說法,一個enum會更類型安全,更簡單,更快:

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號查找它們。]

+0

謝謝你的所有信息。如果可能的話,我很想簡化原始代碼。然而,我使用相同的過程來設置一個按鈕背景,而不是setBackgroundColor()我必須使用:button.setBackground(getResources()。getDrawable(R.drawable.button_red_states))基於任何'case '被選中。這是抽出過程的原始故事。 – Josh

+0

這不會改變使用攜帶資源ID值的枚舉(如R.drawable.button_red_states)或將HashMap映射到資源ID的能力。我不明白你爲什麼使用反射或解析,裝箱和拆箱整數。但是如果你使用反射,它需要Proguard'keep'規則。 – Jerry101

+0

非常感謝您的幫助。雖然不是解決混淆問題的解決方案,但我可以通過使用您推薦的HashMap方法修復我的應用程序。 – Josh

0

您的proguard設置是什麼?發佈您的proguard-project.txt文件(如果您使用舊方法,則使用proguard.cfg)。我建議關閉混淆以更清楚地看到代碼是如何改變的。使用'-dontobfuscate'。

「後」代碼看起來很奇怪。你正在使用優化公共配置文件(proguard-android-optimize.txt)嗎?如果是這樣,嘗試使用沒有優化,以減少代碼被修改多少。