優雅的處理 Android 代碼混淆 Keep 問題 常規操作 簡化操作 優雅操作 總結

爲了源碼安全以及縮小 APK 體積,Android 應用發佈前是必須要進行混淆打包的。而混淆打包並不是全量打包,特定的類、方法、屬性是需要排除在混淆之外的,比如數據模型類,自定義 View 等在混淆時如果不通過規則排除在外可能存在運行時找不到資源的問題。

常規操作

常規操作有以下兩種方式:

  • 要保持的代碼規則逐條添加到 proguard-rules.pro 混淆規則文件中

    存在問題:隨着代碼量的不斷增大,混淆規則會爆炸式增長。還會經常忘記將資源加入到混淆規則中

  • 要保持的類方法統一的包中,再講整個包的保持規則加入到 proguard-rules.pro 混淆規則文件中

    存在問題
    1、keep 粒度是 Class ,如果只想 keep某個方法或者某個屬性就不行了
    2、會干預代碼的目錄,不利於工程內部代碼隔離

簡化操作

針對常規操作的問題,做出對應的處理就得到了簡約操作 —— Tag 標記法,要做到不干預代碼目錄,每個類都能標記,因此使用接口對 Class進行標記,Java 類多繼承的特性不會對代碼有其他的干擾。

  • 定義空接口,將接口保持規則加入到 proguard-rules.pro 混淆規則文件中,需要保持的類實現接口,使用接口標記身份
// 與項目包名路徑對應
-keep public interface com.company.project.KeepClass{public *;}
-keep class * implements com.company.project.KeepClass {
<methods>;
<fields>;
} 

存在問題
1、每個 keep 類都要繼承比較麻煩(當然比每個類寫 keep 要省事多了...)
2、依然不能只 keep 方法或者屬性,不 keep 整個類

優雅操作

同樣針對接口標記法中的存在的問題,進一步優化得到了註解標記法。因爲註解可以標記類、方法、屬性,因此可以將 keep 粒度降到屬性方法上。

  • 1、寫一個空註解類
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface ProguardKeep {

}
  • 2、混淆規則中添加如下規則
-keep @com.pandaq.appcore.framework.annotation.ProguardKeep class * {*;}
-keep class * {
    @com.pandaq.appcore.framework.annotation.ProguardKeep <fields>;
}
-keepclassmembers class * {
    @com.pandaq.appcore.framework.annotation.ProguardKeep <methods>;
}
  • 3、在需要 keep 的地方使用註解
// 示例需要,使用時不需要類、方法、屬性 全都給加上註解
@ProguardKeep
public class UserInfo {
    @ProguardKeep
    private String account;
    private String userName;
    private String token;

    @ProguardKeep
    public String getAccount() {
        return account;
    }
}

總結

使用註解標記,大大的減少了 keep 規則文件內容,開發時只需要記住在需要保持的地方加上 @ProguardKeep ,這也降低了忘記添加混淆規則的風險。當然這只是針對項目自寫代碼,三方庫三方框架的混淆規則還是需要 copy 進規則文件的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章