“混淆”——给代码披上一件冲锋衣,真不容易!

来源:互联网 发布:中国老龄人口数据 编辑:程序博客网 时间:2024/04/29 01:58
最近项目不紧,在学新技术。听说项目也快发布正式版本,就琢磨着写混淆配置文件打包发布,不想它吭我太久,今天终于解决,记录下。

问题:
问题1:debug运行程序正常跑,混淆后跑代码查看log显示类型转换异常的错误,程序跑欢迎界面白屏。
解决:由于有些不改混淆的类和接口被混淆了,所以需要特别写出来它不需要混淆。我把程序里所有的model都不混淆。
 #model-keep interface com.taisau.facerecoginition2..ui.user.login.LoginContract.Model{*;}-keep interface * extends com.mvpFrame.baseMvp.BaseModel-keep public class * implements com.mvpFrame.baseMvp.BaseModel-keep interface com..mvpFrame.baseMvp.BaseModel{*;}-keepclassmembers public class com..ui.user.login.LoginModel{      public protected *;    }
问题2:程序请求登录成功后,无法进入主页面。
解决:由于混淆时候所有的bean是不需要混淆的。但是我有一个baseRespose不小心没有放在bean包里,因为我将它移到bean包里就可以啦。 

-keep class com.bean.**{*;}

混淆错误甄别:可借助mapping.txt(表示混淆前后代码的对照表)和log定位混淆错误位置,快速解决问题。

混淆文件:
一:基本不动区域
#---------------------------------基本指令区----------------------------------#打印日志,保留异常,源文件行数信息。-printmapping proguardMapping.txt#-optimizations !code/simplification/cast,!field/*,!class/merging/*-keepattributes *Annotation*,InnerClasses-keepattributes Signature-keepattributes SourceFile,LineNumberTable-renamesourcefileattribute SourceFile-keepattributes Exceptions,SourceFile#Shrink Options#不缩减代码  shrink,测试后发现会将一些无效代码给移除,即没有被显示调用的代码#-dontshrink-ignorewarnings                   # 忽略警告,避免打包时某些警告出现-optimizationpasses 7           # 指定代码的压缩级别[0-7]-dontusemixedcaseclassnames          # 表示混淆时不使用大小写混合类名。-dontskipnonpubliclibraryclasses   # 是否混淆第三方jar 表示不跳过library中的非public的类。-dontskipnonpubliclibraryclassmembers#-dontpreverify                      # 混淆时是否做预校验 表示不进行预校验。这个预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度。-verbose                            # 混淆时是否记录日志 表示打印混淆的详细信息。-dontnote-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*        # 混淆时所采用的算法# 以下两个命令配合让类的路径给删除了-allowaccessmodification#优化 不优化输入的类文件  表示不进行优化,建议使用此选项,因为根据proguard-android-optimize.txt中的描述,优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行。-dontoptimize-repackageclasses #把执行后的类重新放在某一个目录下,后跟一个目录名#记录生成的日志数据,gradle build时在本项目根目录输出#apk 包内所有 class 的内部结构-dump class_files.txt#未混淆的类和成员-printseeds seeds.txt#列出从 apk 中删除的代码-printusage unused.txt
二:定制化区域
1.app下的所有的jar包是需要混淆的,只有把包名写入就可以。
  这样写:
-dontwarn me.zhanghai.android.materialprogressbar.**-keep class me.zhanghai.android.materialprogressbar.** {*;}
2.所有的bean类需要混淆。
   这样写:
-keep class com.taisau.facerecoginition2.bean.**{*;}
3.native
#表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致的-keepclasseswithmembernames class * {    native <methods>;}
二:保留区域:
1.枚举
#表示不混淆枚举中的values()valueOf()方法。-keepclassmembers enum * {    public static **[] values();    public static ** valueOf(java.lang.String);}
2.自定义控件
#表示不混淆任何一个View中的setXxx()getXxx()方法,因为属性动画需要有相应的settergetter的方法实现,#混淆了就无法工作了。-keep public class * extends android.view.View{# 保持自定义控件类不被混淆    *** get*();    void set*(***);    public <init>(android.content.Context);    public <init>(android.content.Context, android.util.AttributeSet);    public <init>(android.content.Context, android.util.AttributeSet, int);}-keepclasseswithmembers class * {    public <init>(android.content.Context, android.util.AttributeSet);    public <init>(android.content.Context, android.util.AttributeSet, int);}
3.Parcelable
#表示不混淆Parcelable实现类中的CREATOR字段,毫无疑问,CREATOR字段是绝对不能改变的,#包括大小写都不能变,不然整个Parcelable工作机制都会失败。-keep class * implements android.os.Parcelable {  public static final android.os.Parcelable$Creator *;}-keepclassmembers class * implements java.io.Serializable {    static final long serialVersionUID;    private static final java.io.ObjectStreamField[] serialPersistentFields;    private void writeObject(java.io.ObjectOutputStream);    private void readObject(java.io.ObjectInputStream);    java.lang.Object writeReplace();    java.lang.Object readResolve();}
 4.   R文件
#表示不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。-keep class **.R$* { *;}-keepclassmembers class * {    void *(**On*Event);}#表示不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。-keepclassmembers class **.R$* {    public static <fields>;}-keepclassmembers public class * extends android.view.View {  void set*(***);  *** get*();}
5.log
# Remove Logging-assumenosideeffects class android.util.Log {    public static *** d(...);    public static *** w(...);    public static *** v(...);    public static *** i(...);    public static *** e(...);}
6.Activity
#表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性,#当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了。-keepclassmembers class * extends android.app.Activity{#保持类成员    public void *(android.view.View);    public void onEventMainThread(**);}
7.其他
-keep public class * extends android.app.Activity-keep public class * extends android.app.Application-keep public class * extends android.app.Service-keep public class * extends android.content.BroadcastReceiver-keep public class * extends android.content.ContentProvider-keep public class * extends android.app.backup.BackupAgentHelper-keep public class * extends android.preference.Preference-keep public class * extends android.view.View#表示不混淆上述声明的两个类,这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。-keep public class com.android.vending.licensing.ILicensingService-keep public class com.google.vending.licensing.ILicensingService#表示对android.support包下的代码不警告,因为support包中有很多代码都是在高版本中使用的,#如果我们的项目指定的版本比较低在打包时就会给予警告。不过support包中所有的代码都在版本兼容性上做足了判断,#因此不用担心代码会出问题,所以直接忽略警告就可以了。# 51  52 53 54 56-dontwarn android.support.**-keep class android.support.** {*;}