1. 程式人生 > >Proguard 部分類不混淆的技巧

Proguard 部分類不混淆的技巧

兩年前在 Proguard 語法及常用 proguard.cfg 程式碼 中介紹過一些 Proguard 的基礎知識,其中提到一些類不能混淆,比如實現了 Serializable 介面的,否則反序列化時會出錯。這種情況我們可以簡單的通過在 proguard-rules.pro 配置檔案中新增配置,對於較早 Android 專案預設配置檔案可能為 proguard.cfg,如下:

-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

表示所有實現了 Serializable 介面的類及其成員都不進行混淆。

但有時我們可能需要防止一些沒有明顯共同特徵的類被混淆,比如個別控制層類需要反射、個別實體類需要 JSON 化存本地,這時我們怎麼做呢,一個個新增到 proguard-rules.pro(或 proguard.cfg) 中嗎?
這樣會導致 proguard 配置檔案變得雜亂無章,同時需要團隊所有成員對其語法有所瞭解。

這裡分享個小技巧,通過給這些類、屬性、函式新增共同標識,然後統一過濾。

二、解決方法

package cn.trinea.android.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * NotProguard, Means not proguard something, like class, method, field<br/>
 *
 * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2015-08-07
 */
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface NotProguard {

}

NotProguard 是個編譯時註解,不會對執行時效能有任何影響。可修飾類、方法、建構函式、屬性。

2. 在 Proguard 配置檔案中過濾被這個註解修飾的元素

# keep annotated by NotProguard
-keep @cn.trinea.android.common.annotation.NotProguard class * {*;}
-keep class * {
    @cn.trinea.android.common.annotation.NotProguard <fields>;
}
-keepclassmembers class * {
    @cn.trinea.android.common.annotation.NotProguard <methods>;
}
表示不混淆被 NotProguard 修飾的類、屬性和方法。

3. 使用

(1) 整個類不混淆

Java
123@NotProguardpublicclassUser{}

(2) 單個屬性不混淆

Java
1 2 3 @NotProguard publicintid;

(3) 單個方法不混淆

Java
1 2 3 4 5 @NotProguard publicbooleanisValid(){}

這樣我們便解決了每個類都需要在 proguard 配置檔案中配置的問題。

三、關於混淆

混淆一般在 Release 模式生效,主要有三個作用:
(1) 壓縮、優化、刪除程式碼;
(2) 一定程度上提高反編譯後被讀懂的難度;
(3) 通過刪除程式碼功能實現的特殊作用。
比如在 Proguard 語法及常用 proguard.cfg 程式碼 中介紹的利用 Progurad 使得線上版本不列印 Log.d 和 Log.v 的技巧,防止除錯的敏感資訊被洩露。

一些應用的程式碼可能從來都沒混淆過,雖說這些程式碼實際價值可能不大,本身可能也是開原始碼湊起來的,再者該破解的還是能破解,但本著做事要專業的態度,還是混淆吧。