Proguard學習及App混淆

proguard-android.txt與proguard-android-optimize.txt

當我們打Release的時候,Google會默認對我們的release包進行優化,這個優化是通過在modeule中build.gradle中的minifyEnabled來開啓的。

android {
    buildTypes {
        release {
            minifyEnabled true  //開啓代碼混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
}

但是如果我們將minifyEnabled置爲false的話,那麼在我們打release包的時候將不會對代碼進行混淆,實際上這也是一種比較危險的做法,我們的代碼經過反編譯之後就會被別人清晰地看到。

我們還可以看到下面的這段代碼

proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'

其中的proguard-android.txt是默認的配置文件,Google已經爲我們做好的最基本的配置,同時,如果我們想要進一步的對混淆配置進行優化的話,可以使用另一個配置,proguard-android-optimize.txt

proguard-android-optimize.txt可以說是proguard-android.txt中的擴展版,它不僅僅包含了proguard-android.txt中已有的部分,也多了其他的優化部分,它會對字節碼也進行分析優化,進一步縮小APK的體積,提高應用運行速度。

能編過的情況下,,這兩個文件已經能夠滿足我們對混淆的要求,但是如果我們引入了其他的一些庫,需要對混淆配置進行改動的話,則需要自定義proguard-rules.pro這個文件,實際上,我們也可以自已創建文件,並替換掉proguard-rules.pro,只要和proguard-rules.pro文件在一個目錄下就行。

proguard-rules.pro與Proguard規則

引入proguard-rules.pro的原因主要是,google爲我們配置了默認的混淆規則,但是在項目龐大,系統默認的規則還不夠時,需要我們在給他增加一些規則,否則會產生錯誤,造成編譯錯誤。

當因爲混淆規則而發生錯誤時,我們可以通過gradle的輸出文件來查看到底是哪裏發生了錯誤。這個文件就是/build/outputs/mapping/release/目錄下的usage.txt文件,我們可以通過查看它來確定移除了哪些我們需要用到的代碼。

造成我們所需要的代碼被移除的原因主要是以下三點。

  1. 當應用引用的類只來自 AndroidManifest.xml 文件時
  2. 當應用調用的方法來自 Java 原生接口 (JNI) 時
  3. 當應用在運行時(例如使用反射或自檢)操作代碼時

保留代碼的規則主要有以下幾種:

  • 通過指定類的名稱保留指定的類文件和類的成員
-keep {Modiffier} {class_specification}

例子如下

-keep public class com.google.vending.licensing.ILicensingService
  • 通過指定類的成員名稱保留指定類的成員
-keepclassmembers {modifier} {class_specification}

例子如下

-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}
  • 通過指定類成員名保留指定的類和類的成員
-keepclasseswithmembers {class_specification}

例子如下

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}
  • 通過指定類保留指定的類的成員名稱
-keepnames {class_specification}
  • 通過指定類成員保護指定的類的成員名稱
-keepclasseswithmembernames {class_specification}
  • 通過指定類成員保護指定的類和類的成員名稱(這裏類成員條件必須完全滿足)
-keepclasseswithmembernames {class_specification}

看過這些規則可能就會暈了,因爲記起來十分的繁瑣,但實際上,google也爲我們提供了另一個方法來保留代碼,就是使用註釋的方式,我們可以看到在proguard-android.txtproguard-android-optimize.txt中都寫有這樣的規則

-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

也就是說,遇到我們想保存的類或者類對象的時候,只添加註釋即可。

但是,這樣用我們需要用到註解支持庫,需要在gradle里加上。

 dependencies { compile 'com.android.support:support-annotations:24.2.0' } 

資源壓縮

上面講的都是代碼的混淆,但實際上如果已經實現了代碼混淆,我們也可以對資源進行壓縮,只需要再加上一句shrinkResources true即可。

buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章