Android ProGuard 混淆 詳解

現在寫的app 基本都是經過混淆了的,如果不混淆, 發佈出去,別人一反編譯 就可以直接看你的源碼了
ok 來說一下混淆吧:

我現在用的AndroidStudio , 只需要在 build.grade 的配置文件中配置如下即可: 

  1. buildTypes {  
  2.     debug {  
  3.         versionNameSuffix ".dev"  
  4.     }  
  5.   
  6.     release {  
  7.         debuggable false  
  8.         minifyEnabled true  
  9.         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  
  10.         signingConfig signingConfigs.release  
  11.     }  
  12. }  

proguardFiles getDefaultProguardFile 就是制定 混淆規則的文件, AndroidStudio默認生成了proguard-rules.pro 文件 


混淆 ProGuard常用語法
  1. -libraryjars class_path 應用的依賴包,如android-support-v4  
  2. -keep [,modifier,...] class_specification 不混淆某些類  
  3. -keepclassmembers [,modifier,...] class_specification 不混淆類的成員  
  4. -keepclasseswithmembers [,modifier,...] class_specification 不混淆類及其成員  
  5. -keepnames class_specification 不混淆類及其成員名  
  6. -keepclassmembernames class_specification 不混淆類的成員名  
  7. -keepclasseswithmembernames class_specification 不混淆類及其成員名  
  8. -assumenosideeffects class_specification 假設調用不產生任何影響,在proguard代碼優化時會將該調用remove掉。如system.out.println和Log.v等等  
  9. -dontwarn [class_filter] 不提示warnning  

Android 混淆原則:

反射用到的類不混淆
JNI方法不混淆
AndroidMainfest中的類不混淆,四大組件和Application的子類和Framework層下所有的類默認不會進行混淆
Parcelable的子類和Creator靜態成員變量不混淆,否則會產生android.os.BadParcelableException異常
使用GSON、fastjson等框架時,所寫的JSON對象類不混淆,否則無法將JSON解析成對應的對象
使用第三方開源庫或者引用其他第三方的SDK包時,需要在混淆文件中加入對應的混淆規則
有用到WEBView的JS調用也需要保證寫的接口方法不混淆

先看看google默認混淆文件: \sdk\tools\proguard\proguard-android.txt 
  1. -keepattributes *Annotation*//使用註解需要添加  
  2. -keep public class com.google.vending.licensing.ILicensingService  
  3. -keep public class com.android.vending.licensing.ILicensingService  
  4.   
  5. # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native  
  6. -keepclasseswithmembernames class * {//指定不混淆所有的JNI方法  
  7.     native <methods>;  
  8. }  
  9.   
  10. # keep setters in Views so that animations can still work.  
  11. # see http://proguard.sourceforge.net/manual/examples.html#beans  
  12. -keepclassmembers public class * extends android.view.View {//所有View的子類及其子類的get、set方法都不進行混淆  
  13.    void set*(***);  
  14.    *** get*();  
  15. }  
  16.   
  17. # We want to keep methods in Activity that could be used in the XML attribute onClick  
  18. -keepclassmembers class * extends android.app.Activity {//不混淆Activity中參數類型爲View的所有方法  
  19.    public void *(android.view.View);  
  20. }  
  21.   
  22. # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations  
  23. -keepclassmembers enum * {//不混淆Enum類型的指定方法  
  24.     public static **[] values();  
  25.     public static ** valueOf(java.lang.String);  
  26. }  
  27. //不混淆Parcelable和它的子類,還有Creator成員變量  
  28. -keep class * implements android.os.Parcelable {  
  29.   public static final android.os.Parcelable$Creator *;  
  30. }  
  31. //不混淆R類裏及其所有內部static類中的所有static變量字段  
  32. -keepclassmembers class **.R$* {  
  33.     public static <fields>;  
  34. }  
  35.   
  36. # The support library contains references to newer platform versions.  
  37. # Don't warn about those in case this app is linking against an older  
  38. # platform version.  We know about them, and they are safe.  
  39. -dontwarn android.support.**//不提示兼容庫的錯誤警告  


如果加入一些自己的混淆規則 只需要在 proguard-rules.pro 中文件加入自己的混淆規則即可,
其實google以及給我提供很好的打包規則, 即proguard-rules.pro 啥也不寫, 我打出來的release包也是混淆好的
但是我們會遇到一些情況, 不得不 添加自己的混淆規則:
1. 代碼中使用了反射,如一些ORM框架的使用 
          需要保證類名 方法不變, 不然混淆後, 就反射不了
2. 使用GSON、fastjson等JSON解析框架所生成的對象類
          生成的bean實體對象,內部大多是通過反射來生成, 不能混淆
3. 引用了第三方開源框架或繼承第三方SDK,如開源的okhttp網絡訪問框架,百度定位SDK等
          在這些第三庫的文檔中 一班會給出 相應的 混淆規則, 複製過來即可
4. 有用到WEBView的JS調用接口
          沒真麼用過這塊, 不是很熟, 網上那個看到的
5. 繼承了Serializable接口的類
          在反序列畫的時候, 需要正確的類名等, 在Android 中大多是實現 Parcelable來序列化的

ok 其實自己加入的規則 一般都是說,某某類 不混淆等等

如果用到了反射需要加入 : 
  1. -keepattributes Signature  
  2. -keepattributes EnclosingMethod  

如果想讓一些bean 對象不混淆, 裏 com.czy.bean 包下面的全是 Json框架生成的bean對象, 那麼只需加入:
  1. -keep class czy.**{*;}//不混淆所有的com.czy.bean包下的類和這些類的所有成員變量  
繼承了Serializable接口的類,需要加上:

  1. //不混淆Serializable接口的子類中指定的某些成員變量和方法  
  2. -keepclassmembers class * implements java.io.Serializable {  
  3.     static final long serialVersionUID;  
  4.     private static final java.io.ObjectStreamField[] serialPersistentFields;  
  5.     private void writeObject(java.io.ObjectOutputStream);  
  6.     private void readObject(java.io.ObjectInputStream);  
  7.     java.lang.Object writeReplace();  
  8.     java.lang.Object readResolve();  
  9. }  

關於第三方的庫的, 一班都是看他們的官方文檔

有用到WEBView的JS調用接口,需加入如下規則: 
  1. -keepclassmembers class fqcn.of.javascript.interface.for.webview {  
  2.    public *;  
  3. }  
  4. -keep class com.xxx.xxx.** { *; }//保持WEB接口不被混淆 此處xxx.xxx是自己接口的包名  

不混淆某個類:

  1. -keep class com.czy.**//不混淆所有com.czy包下的類,** 換成具體的類名則表示不混淆某個具體的類  
不混淆某個類和成員變量:

  1. -keep class com.clock.**{*;}//不混淆所有com.clock包下的類和類中的所有成員變量,**可以換成具體類名,*可以換成具體的字段,可參照Serialzable的混淆  

移除一些log代碼:
移除Log類打印各個等級日誌的代碼,打正式包的時候可以做爲禁log使用,這裏可以作爲禁止log打印的功能使用,另外的一種實現方案是通過BuildConfig.DEBUG的變量來控制 
  1. -assumenosideeffects class android.util.Log {  
  2.     public static *** v(...);  
  3.     public static *** i(...);  
  4.     public static *** d(...);  
  5.     public static *** w(...);  
  6.     public static *** e(...);  

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