天天看點

Android 代碼混淆心得!代碼混淆 忽略混淆的檔案(規則):心得:混淆例子:

原創位址:http://blog.csdn.net/tl792814781/article/details/51447255

原創作者:迷途開發者的部落格

代碼混淆

代碼混淆(Obfuscated code)亦稱花指令,是将計算機程式的代碼,轉換成一種功能上等價,但是難于閱讀和了解的形式的行為。

将代碼中的各種元素,如變量,函數,類的名字改寫成無意義的名字。比如改寫成單個字母,或是簡短的無意義字母組合,

甚至改寫成“__”這樣的符号,使得閱讀的人無法根據名字猜測其用途。 對于支援反射的語言,代碼混淆有可能與反射發生沖突。代碼混淆并不能真正阻止反向工程,隻能增大其難度。

是以,對于對安全性要求很高的場合,僅僅使用代碼混淆并不能保證源代碼的安全。但是可以在一定程度上保護自己的勞動成果。

Android 代碼混淆心得!代碼混淆 忽略混淆的檔案(規則):心得:混淆例子:

(例子在末尾)

忽略混淆的檔案(規則):

  • Android系統元件,系統元件有固定的方法被系統調用。
  • 被Android Resource 檔案引用到的。名字已經固定,也不能混淆,比如自定義的View 。
  • Android Parcelable ,需要使用android 序列化的。
  • 其他Anroid 官方建議 不混淆的,如
  • android.app.backup.BackupAgentHelper
  • android.preference.Preference
  • com.android.vending.licensing.ILicensingService
  • Java序列化方法,系統序列化需要固定的方法。
  • 枚舉 ,系統需要處理枚舉的固定方法。
  • 本地方法,不能修改本地方法名
  • annotations 注釋
  • 資料庫驅動
  • 有些resource 檔案
  • 用到反射的地方

心得:

  1.grade建構必須沒有warn和error,不然刷入的版本依舊是上一個版本,這裡要特别注意warn!

2.ClassNotFoundException,NoSuchMethodError

     原因:這種異常會在好多情況下出現,比如:本地代碼通過反射調用其他的類,但是經過了混淆之後,就會出現如上異常;調用了JNI之後,C或者C++和java代碼進行互動的時候找不到java的類或者方法,導緻發生了異常......等等,還有好多。

     解決辦法:隻需要将被調用的java類标注為不混淆即可。 -keep class package.classname{*;}

     3.ExceptionInInitializerError

     原因:這是由于類初始化的時候發生了異常。

     解決辦法:找到具體是哪裡的類哪個方法哪個類初始化的時候發生的異常,然後解決問題。

     注:遇到這個錯誤,首先要确認是不是因為第三方的jar包導緻的。如果不是的話,就找本地代碼,看是不是寫的有問題。如果确實是因為第三方jar包的代碼導緻的,盡量找到源碼或者反編譯,檢視問題到底是什麼引起的,然後找到相應的配置在proguard裡面配置。

     例如:我們項目中碰到過一個問題,就是因為第三方的jar包裡面有一個字段初始化的時候報了空指針,然後導緻我們的代碼報了上面的錯。當時很奇怪,為什麼第三方的jar包還能報錯,最後調查了之後才發現,是因為人家用到了類的注解,而proguard在混淆優化的時候把注解去掉了,是以報了空指針,隻需要在proguard裡面加上保護注解就可以了-keepattributes *Annotation*

4.ClassCastException

     原因:類強制轉換的時候出錯。

     解決辦法:找到代碼,看是代碼寫的問題,還是混淆後的問題。如果沒有混淆正常運作的話,一般都是因為混淆後遇到了各種問題才報的錯。我們項目中遇到的問題是因為沒有讓proguard保持泛型,是以強轉的時候報錯。隻需要在proguard檔案裡面加上泛型即可-keepattributes Signature

5.Resources$NotFoundException(resource not found)

資源沒有找到,是因為第三方jar包或者自己的代碼是通過反射獲得R檔案中的資源,是以需要将R檔案屏蔽掉

    原因:代碼進行了混淆,R檔案沒有了,是以通過反射擷取的R檔案找不到

    解決辦法:在proguard檔案裡設定不混淆R檔案    -keep class **.R$* { *; }

6. Missing type parameter. or java.lang.ExceptionInInitializerError

可能是泛型混淆了 泛型即可-keepattributes Signature

混淆例子:

[java] view plain copy

  1. <span style="font-family:FangSong_GB2312;font-size:12px;color:#333333;">#指定代碼的壓縮級别  
  2. -optimizationpasses 5  
  3. #包明不混合大小寫  
  4. -dontusemixedcaseclassnames  
  5. #不去忽略非公共的庫類  
  6. -dontskipnonpubliclibraryclasses  
  7.  #優化  不優化輸入的類檔案  
  8. -dontoptimize  
  9.  #預校驗  
  10. -dontpreverify  
  11.  # 混淆時所采用的算法  
  12. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*  
  13. #保護注解  
  14. -keepattributes *Annotation*  
  15. # 保持哪些類不被混淆  
  16. -keep public class * extends android.app.Fragment  
  17. -keep public class * extends android.app.Activity  
  18. -keep public class * extends android.app.Application  
  19. -keep public class * extends android.app.Service  
  20. -keep public class * extends android.content.BroadcastReceiver  
  21. -keep public class * extends android.content.ContentProvider  
  22. -keep public class * extends android.app.backup.BackupAgentHelper  
  23. -keep public class * extends android.preference.Preference  
  24. -keep public class com.android.vending.licensing.ILicensingService  
  25. #如果有引用v4包可以添加下面這行  
  26. #-keep public class * extends android.support.v4.app.Fragment  
  27. -keep public class * extends android.support.** { *; }  
  28. #如果引用了v4或者v7包  
  29. -dontwarn android.support.*  
  30. #忽略警告  
  31. -ignorewarning  
  32. #####################記錄生成的日志資料,gradle build時在本項目根目錄輸出################  
  33.  #混淆時是否記錄日志  
  34. -verbose  
  35. #apk 包内所有 class 的内部結構  
  36. -dump class_files.txt  
  37. #未混淆的類和成員  
  38. -printseeds seeds.txt  
  39. #列出從 apk 中删除的代碼  
  40. -printusage unused.txt  
  41. #混淆前後的映射  
  42. -printmapping mapping.txt  
  43. #####################記錄生成的日志資料,gradle build時 在本項目根目錄輸出-end################  
  44. #####混淆保護自己項目的部分代碼以及引用的第三方jar包library - start #######  
  45. #如果不想混淆 keep 掉  保留一個完整的包  
  46. #-keep class com.lippi.recorder.iirfilterdesigner.** {*; }  
  47. #項目特殊處理代碼  
  48. #忽略警告  
  49. #-dontwarn com.lippi.recorder.utils**  
  50. #如果用用到Gson解析包的,直接添加下面這幾行就能成功混淆,不然會報錯。  
  51. #//原因分析,可能是高版本的 sdk 通過 proguard 混淆代碼時預設已經将 lib目錄中的 jar 都已經添加到打包腳本中,是以不需要再次手動添加  
  52. # 混淆jar  
  53. #-libraryjars libs/gson-2.2.4.jar  
  54. # 混淆類  
  55. #-keep class sun.misc.Unsafe { *; }  
  56. # 混淆包  
  57. #-keep class com.google.gson.examples.android.model.** { *; }  
  58. #dialog  
  59. -keep class me.drakeet.materialdialog.** { *; }  
  60. #加載框  
  61. -keep class com.kaopiz.kprogresshud.** { *; }  
  62. #下拉重新整理  
  63. -keep class in.srain.cube.views.ptr.** { *; }  
  64. #實體類不混淆  
  65. -keep class com.ousrslook.shimao.commen.ioc.** { *; } #不能混淆 否則注解無效  
  66. -keep class com.ousrslook.shimao.model.** { *; } #不能混淆  
  67. -keep class com.ousrslook.shimao.net.XaResult{ *; }#統一傳回的實體類泛型不能混淆  
  68. #-keep class com.ousrslook.shimao.net.** { *; }  
  69. ####混淆保護自己項目的部分代碼以及引用的第三方jar包library-end####  
  70. -keep public class * extends android.view.View {  
  71.     public <init>(android.content.Context);  
  72.     public <init>(android.content.Context, android.util.AttributeSet);  
  73.     public <init>(android.content.Context, android.util.AttributeSet, int);  
  74.     public void set*(...);  
  75. }  
  76. #保持 native 方法不被混淆  
  77. -keepclasseswithmembernames class * {  
  78.     native <methods>;  
  79. }  
  80. #保持自定義控件類不被混淆  
  81. -keepclasseswithmembers class * {  
  82.     public <init>(android.content.Context, android.util.AttributeSet);  
  83. }  
  84. #保持自定義控件類不被混淆  
  85. -keepclassmembers class * extends android.app.Activity {  
  86.    public void *(android.view.View);  
  87. }  
  88. #保持 Parcelable 不被混淆  
  89. -keep class * implements android.os.Parcelable {  
  90.   public static final android.os.Parcelable$Creator *;  
  91. }  
  92. #保持 Serializable 不被混淆  
  93. -keepnames class * implements java.io.Serializable  
  94. #保持 Serializable 不被混淆并且enum 類也不被混淆  
  95. -keepclassmembers class * implements java.io.Serializable {  
  96.     static final long serialVersionUID;  
  97.     private static final java.io.ObjectStreamField[] serialPersistentFields;  
  98.     !static !transient <fields>;  
  99.     !private <fields>;  
  100.     !private <methods>;  
  101.     private void writeObject(java.io.ObjectOutputStream);  
  102.     private void readObject(java.io.ObjectInputStream);  
  103.     java.lang.Object writeReplace();  
  104.     java.lang.Object readResolve();  
  105. }  
  106. #保持枚舉 enum 類不被混淆 如果混淆報錯,建議直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可  
  107. -keepclassmembers enum * {  
  108.   public static **[] values();  
  109.   public static ** valueOf(java.lang.String);  
  110. }  
  111. -keepclassmembers class * {  
  112.     public void *ButtonClicked(android.view.View);  
  113. }  
  114. #不混淆資源類  
  115. -keepclassmembers class **.R$* {  
  116.     public static <fields>;  
  117. }  
  118.  -keep class **.R$* { *; }  
  119. #避免混淆泛型 如果混淆報錯建議關掉  
  120. -keepattributes Signature</span>  

以上是在項目中的一些心得,謝謝。