当前位置:   article > 正文

Android混淆研究

Android混淆研究

前言

混淆是上线前挺重要的一个环节。android使用的ProGuard,可以起到压缩,混淆,预检,优化的作用。但是很多童鞋还没有掌握正确的写混淆文件的姿势。我希望搞个模板化的东西,让大家轻松搞定混淆。那么,开始写一个项目的混淆吧。。。我是不是很直接。。。。

五步搞定

1

打开项目中的proguard-rules.pro,将下面的代码复制进去。我的思路是将混淆分为2个主要部分

  • 定制化区域。这里边的内容是我们主要需要补充的部分,大致分为4个小部分,我们接下来的步骤主要是补充这4个部分的东西。
  • 基本不用动区域。顾名思义,基本不用动。这块的内容我已经写好了,除非有特殊的需求,基本不用改动。。。请叫我雷锋。。。。。
  1. #-------------------------------------------定制化区域----------------------------------------------
  2. #---------------------------------1.实体类---------------------------------
  3. #-------------------------------------------------------------------------
  4. #---------------------------------2.第三方包-------------------------------
  5. #-------------------------------------------------------------------------
  6. #---------------------------------3.与js互相调用的类------------------------
  7. #-------------------------------------------------------------------------
  8. #---------------------------------4.反射相关的类和方法-----------------------
  9. #----------------------------------------------------------------------------
  10. #---------------------------------------------------------------------------------------------------
  11. #-------------------------------------------基本不用动区域--------------------------------------------
  12. #---------------------------------基本指令区----------------------------------
  13. -optimizationpasses 5
  14. -dontusemixedcaseclassnames
  15. -dontskipnonpubliclibraryclasses
  16. -dontskipnonpubliclibraryclassmembers
  17. -dontpreverify
  18. -verbose
  19. -printmapping proguardMapping.txt
  20. -optimizations !code/simplification/cast,!field/*,!class/merging/*
  21. -keepattributes *Annotation*,InnerClasses
  22. -keepattributes Signature
  23. -keepattributes SourceFile,LineNumberTable
  24. #----------------------------------------------------------------------------
  25. #---------------------------------默认保留区---------------------------------
  26. -keep public class * extends android.app.Activity
  27. -keep public class * extends android.app.Appliction
  28. -keep public class * extends android.app.Service
  29. -keep public class * extends android.content.BroadcastReceiver
  30. -keep public class * extends android.content.ContentProvider
  31. -keep public class * extends android.app.backup.BackupAgentHelper
  32. -keep public class * extends android.preference.Preference
  33. -keep public class * extends android.view.View
  34. -keep public class com.android.vending.licensing.ILicensingService
  35. -keep class android.support.** {*;}
  36. -keepclasseswithmembernames class * {
  37. native <methods>;
  38. }
  39. -keepclassmembers class * extends android.app.Activity{
  40. public void *(android.view.View);
  41. }
  42. -keepclassmembers enum * {
  43. public static **[] values();
  44. public static ** valueOf(java.lang.String);
  45. }
  46. -keep public class * extends android.view.View{
  47. *** get*();
  48. void set*(***);
  49. public <init>(android.content.Context);
  50. public <init>(android.content.Context, android.util.AttributeSet);
  51. public <init>(android.content.Context, android.util.AttributeSet, int);
  52. }
  53. -keepclasseswithmembers class * {
  54. public <init>(android.content.Context, android.util.AttributeSet);
  55. public <init>(android.content.Context, android.util.AttributeSet, int);
  56. }
  57. -keep class * implements android.os.Parcelable {
  58. public static final android.os.Parcelable$Creator *;
  59. }
  60. -keepclassmembers class * implements java.io.Serializable {
  61. static final long serialVersionUID;
  62. private static final java.io.ObjectStreamField[] serialPersistentFields;
  63. private void writeObject(java.io.ObjectOutputStream);
  64. private void readObject(java.io.ObjectInputStream);
  65. java.lang.Object writeReplace();
  66. java.lang.Object readResolve();
  67. }
  68. -keep class **.R$* {
  69. *;
  70. }
  71. -keepclassmembers class * {
  72. void *(**On*Event);
  73. }
  74. #----------------------------------------------------------------------------
  75. #---------------------------------webview------------------------------------
  76. -keepclassmembers class fqcn.of.javascript.interface.for.webview {
  77. public *;
  78. }
  79. -keepclassmembers class * extends android.webkit.webViewClient {
  80. public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
  81. public boolean *(android.webkit.WebView, java.lang.String);
  82. }
  83. -keepclassmembers class * extends android.webkit.webViewClient {
  84. public void *(android.webkit.webView, jav.lang.String);
  85. }
  86. #----------------------------------------------------------------------------
  87. #---------------------------------------------------------------------------------------------------

2

理解完战略级思想后,我们开始第一部分补充-实体类。实体类由于涉及到与服务端的交互,各种gson的交互如此等等,是要保留的。将你项目中实体类都拎出来,用以下语法进行保留。

-keep class 你的实体类所在的包.** { *; }

如我的项目下类User的完整路径为:com.demo.login.bean.User, 那我的混淆如下

  1. #---------------------------------1.实体类---------------------------------
  2. -keep class com.demo.login.bean.** { *; }
  3. #-------------------------------------------------------------------------

当然你的实体类肯定不止这一个,请用上边的方式一一添加,如果你的实体类都在一个包下,那你就幸福了。

3

第2部分是第三方包。打开你的build.gradle文件,查看你用了哪些第三方的包。

  1. dependencies {
  2. compile 'com.github.bumptech.glide:glide:3.7.0'
  3. compile 'org.greenrobot:eventbus:3.0.0'
  4. }

我这里用了glide,eventbus。我去他们的官网把已经写好的混淆copy下来。

  1. #---------------------------------2.第三方包-------------------------------
  2. #eventBus
  3. -keepattributes *Annotation*
  4. -keepclassmembers class ** {
  5. @org.greenrobot.eventbus.Subscribe <methods>;
  6. }
  7. -keep enum org.greenrobot.eventbus.ThreadMode { *; }
  8. -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
  9. <init>(java.lang.Throwable);
  10. }
  11. #glide
  12. -keep public class * implements com.bumptech.glide.module.GlideModule
  13. -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  14. **[] $VALUES;
  15. public *;
  16. }
  17. #-------------------------------------------------------------------------

一般官网都是有混淆的,没有的话就google,也没有的话自己按照上面的写法自己写,还不会的话。。。。。只能换个包。。。。。如果你是直接包含的jar包的话,你这样写

  1. #---------------------------------2.第三方包-------------------------------
  2. #log4j
  3. -libraryjars log4j-1.2.17.jar
  4. -dontwarn org.apache.log4j.**
  5. -keep class org.apache.log4j.** { *;}
  6. #-------------------------------------------------------------------------

大致意思就是不混淆,不报warn。如果gradle报错的话,可以考虑注释掉-libraryjars log4j-1.2.17.jar这句。

4

第三部分与js互调的类,工程中没有直接跳过。一般你可以这样写

-keep class 你的类所在的包.** { *; }

如果是内部类的话,你可以这样

-keepclasseswithmembers class 你的类所在的包.父类$子类 { <methods>; }

例如

  1. -keepclasseswithmembers class com.demo.login.bean.ui.MainActivity$JSInterface {
  2. <methods>;
  3. }

5

第四部分与反射有关的类,工程中没有直接跳过。类的话直接这样

-keep class 你的类所在的包.** { *; }

熟练后不用五分钟就能搞定。大家可以把自己写完混淆所用的时间写在评论里(0,0)

深入了解

先逐条介绍下基本指令区指令的含义

-optimizationpasses 5

代码混淆的压缩比例,值在0-7之间

-dontusemixedcaseclassnames

混淆后类名都为小写

-dontskipnonpubliclibraryclasses

指定不去忽略非公共的库的类

-dontskipnonpubliclibraryclassmembers

指定不去忽略非公共的库的类的成员

-dontpreverify

不做预校验的操作

  1. -verbose
  2. -printmapping proguardMapping.txt

生成原类名和混淆后的类名的映射文件

-optimizations !code/simplification/cast,!field/*,!class/merging/*

指定混淆是采用的算法

-keepattributes *Annotation*,InnerClasses

不混淆Annotation

-keepattributes Signature

不混淆泛型

-keepattributes SourceFile,LineNumberTable

抛出异常时保留代码行号

基本指令区基本介绍完了,说下2条用的最多的指令

-keep class XXXX

保留类名不变,也就是类名不混淆,而类中的成员名不保证。当然也可以是继承XXX类的所有类名不混淆,具体代码不贴了,重在理解。

-keepclasseswithmembers class XXXX

保留类名和成员名。当然也可以是类中特定方法,代码不贴了,理由同上。

附:完整的混淆

  1. #-------------------------------------------定制化区域----------------------------------------------
  2. #---------------------------------1.实体类---------------------------------
  3. -keep class com.demo.login.bean.** { *; }
  4. -keep class com.demo.main.bean.** { *; }
  5. #-------------------------------------------------------------------------
  6. #---------------------------------2.第三方包-------------------------------
  7. #eventBus
  8. -keepattributes *Annotation*
  9. -keepclassmembers class ** {
  10. @org.greenrobot.eventbus.Subscribe <methods>;
  11. }
  12. -keep enum org.greenrobot.eventbus.ThreadMode { *; }
  13. -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
  14. <init>(java.lang.Throwable);
  15. }
  16. #glide
  17. -keep public class * implements com.bumptech.glide.module.GlideModule
  18. -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  19. **[] $VALUES;
  20. public *;
  21. }
  22. #log4j
  23. -libraryjars log4j-1.2.17.jar
  24. -dontwarn org.apache.log4j.**
  25. -keep class org.apache.log4j.** { *;}
  26. #-------------------------------------------------------------------------
  27. #---------------------------------3.与js互相调用的类------------------------
  28. -keepclasseswithmembers class com.demo.login.bean.ui.MainActivity$JSInterface {
  29. <methods>;
  30. }
  31. #-------------------------------------------------------------------------
  32. #---------------------------------4.反射相关的类和方法-----------------------
  33. #TODO 我的工程里没有。。。
  34. #----------------------------------------------------------------------------
  35. #---------------------------------------------------------------------------------------------------
  36. #-------------------------------------------基本不用动区域--------------------------------------------
  37. #---------------------------------基本指令区----------------------------------
  38. -optimizationpasses 5
  39. -dontusemixedcaseclassnames
  40. -dontskipnonpubliclibraryclasses
  41. -dontskipnonpubliclibraryclassmembers
  42. -dontpreverify
  43. -verbose
  44. -printmapping proguardMapping.txt
  45. -optimizations !code/simplification/cast,!field/*,!class/merging/*
  46. -keepattributes *Annotation*,InnerClasses
  47. -keepattributes Signature
  48. -keepattributes SourceFile,LineNumberTable
  49. #----------------------------------------------------------------------------
  50. #---------------------------------默认保留区---------------------------------
  51. -keep public class * extends android.app.Activity
  52. -keep public class * extends android.app.Appliction
  53. -keep public class * extends android.app.Service
  54. -keep public class * extends android.content.BroadcastReceiver
  55. -keep public class * extends android.content.ContentProvider
  56. -keep public class * extends android.app.backup.BackupAgentHelper
  57. -keep public class * extends android.preference.Preference
  58. -keep public class * extends android.view.View
  59. -keep public class com.android.vending.licensing.ILicensingService
  60. -keep class android.support.** {*;}
  61. -keepclasseswithmembernames class * {
  62. native <methods>;
  63. }
  64. -keepclassmembers class * extends android.app.Activity{
  65. public void *(android.view.View);
  66. }
  67. -keepclassmembers enum * {
  68. public static **[] values();
  69. public static ** valueOf(java.lang.String);
  70. }
  71. -keep public class * extends android.view.View{
  72. *** get*();
  73. void set*(***);
  74. public <init>(android.content.Context);
  75. public <init>(android.content.Context, android.util.AttributeSet);
  76. public <init>(android.content.Context, android.util.AttributeSet, int);
  77. }
  78. -keepclasseswithmembers class * {
  79. public <init>(android.content.Context, android.util.AttributeSet);
  80. public <init>(android.content.Context, android.util.AttributeSet, int);
  81. }
  82. -keep class * implements android.os.Parcelable {
  83. public static final android.os.Parcelable$Creator *;
  84. }
  85. -keepclassmembers class * implements java.io.Serializable {
  86. static final long serialVersionUID;
  87. private static final java.io.ObjectStreamField[] serialPersistentFields;
  88. private void writeObject(java.io.ObjectOutputStream);
  89. private void readObject(java.io.ObjectInputStream);
  90. java.lang.Object writeReplace();
  91. java.lang.Object readResolve();
  92. }
  93. -keep class **.R$* {
  94. *;
  95. }
  96. -keepclassmembers class * {
  97. void *(**On*Event);
  98. }
  99. #----------------------------------------------------------------------------
  100. #---------------------------------webview------------------------------------
  101. -keepclassmembers class fqcn.of.javascript.interface.for.webview {
  102. public *;
  103. }
  104. -keepclassmembers class * extends android.webkit.webViewClient {
  105. public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
  106. public boolean *(android.webkit.WebView, java.lang.String);
  107. }
  108. -keepclassmembers class * extends android.webkit.webViewClient {
  109. public void *(android.webkit.webView, jav.lang.String);
  110. }
  111. #----------------------------------------------------------------------------
  112. #---------------------------------------------------------------------------------------------------

后言

将build.gradle中minifyEnabled设置为true打个包试试吧

  1. release {
  2. minifyEnabled true
  3. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  4. }

其他需求可以留言讨论。如果觉得有用请帮忙戳喜欢。。

感谢

包老师的《App研发录》



文/wolearn(简书作者)
原文链接:http://www.jianshu.com/p/f3455ecaa56e
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/982957
推荐阅读
相关标签
  

闽ICP备14008679号