android 混淆

混淆的原理

其实不要混淆的主旨就在于混淆会改变方法的名字,类的名字,但是对于外部的一些引用是通过名字找到对应的方法,类,这些可能是通过string找到方法,类,但是string里的字段是不会进行混淆,所以还是会保留原来的名字,这样混淆过后通过原来的名字去找混淆后的名字,是肯定找不到,所以就会报出nosuchfileException,(对于gson,反射,jsbridge,第三方库都是这个原因),至于说枚举类型,我还暂时没懂 为什么,还望共同学习,一起成长。
文章是读了两篇博客写出来,也是自己总结,消化成自己的知识了,若有什么错误的地方,还望指出,相信读了这两篇文章之后你也会懂混淆,一个是如何混淆,一个是哪些该混淆,为什么不能混淆

  • -keep class com.ll.ui.* 保证包名下的类不被混淆 但是子包名下的类还是会被混淆
  • -keep calss com.ll.ui.** 保证包名下的类以及子类都不会被混淆
    以上两种只是保证类名不会被混淆,但是类的内容还是会被混淆
  • -keep class com.ll.ui.*{*;} 这样就保证了类以及类的内容不会被混淆
    在此基础上 java的规则也是可以使用,extends,implement
  • -keep class * extends Activity 继承了activity的类是不会被混淆的
    保证内部类不会被混淆 使用$这个符号
  • -keepclassmembers class com.ll.ui.baseactivity$innerclass{ public *; } 这样就保证了baseActivity的内部类innerclass的所有public方法不会被混淆
  • 再者希望类的全部方法不会被混淆 可以使用如下方法保证类的构造器不会被混淆
    -keep class com.ll.ui.activity { public ; }
  • 当然public 还可以换成是private protect等修饰
    匹配所有域不会被混淆
    匹配所有函数方法不会被混淆
    这些后面还可以加入参数
    -keep class com.ll.ui.activity { public (com.android.Activity); }表示activity作为参数的构造函数不会被混淆
  • -keep 保证类和类的成员都不会被混淆
  • -keepclassmembers 保证成员不会被混淆但是类是会被混淆
  • -keepclasswithmembers 如果类拥有了某成员 保证类和成员不会被混淆

注意事项

  • 1,jni方法不可混淆,因为这个方法需要和native方法保持一致;

-keepclasseswithmembernames class * { # 保持native方法不被混淆 native ; }

  • 2,反射用到的类不混淆(否则反射可能出现问题);

  • 3,AndroidMainfest中的类不混淆,所以四大组件和Application的子类和Framework层下所有的类默认不会进行混淆。自定义的View默认也不会被混淆;所以像网上贴的很多排除自定义View,或四大组件被混淆的规则在Android Studio中是无需加入的;

  • 4,与服务端交互时,使用GSON、fastjson等框架解析服务端数据时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象;

  • 5,使用第三方开源库或者引用其他第三方的SDK包时,如果有特别要求,也需要在混淆文件中加入对应的混淆规则;

  • 6,有用到WebView的JS调用也需要保证写的接口方法不混淆,原因和第一条一样;

  • 7,Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常;

-keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆 public static final Android.os.Parcelable$Creator *; }

  • 8,使用enum类型时需要注意避免以下两个方法混淆,因为enum类的特殊性,以下两个方法会被反射调用,见第二条规则。
    -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }

写在最后

发布一款应用除了设minifyEnabled为ture,你也应该设置zipAlignEnabled为true,像Google Play强制要求开发者上传的应用必须是经过zipAlign的,zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。

文/CPPAlien(作者)
原文链接:http://www.jianshu.com/p/7436a1a32891
著作权归作者所有,转载请联系作者获得授权,并标注“作者”。

  • -dontwarn 关闭sdk发出的警告
    例如有些时候在build的时候某些sdk会发出警告导致build停止 这时候就可以使用dontwarn来停止sdk的警告

为什么不能被混淆

  • 对于使用反射的类不能进行混淆,因为会把里面的成员变量进行混淆,但是string的内容不会混淆,所以到时候会报出nosuchfileException

  • 需要gson序列化的model,也不推荐混淆,混淆后,会导致类里面的属性名字改变,然后gson反序列化就会找不到对应的属性名,所以说:要么不要混淆,要么推荐使用@serializedName来注释,这样当混淆后,反序列化通过注释来找到对应的字段

  • 对枚举类型也不需要混淆 固定格式如下
    #For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }

  • 四大组件不要混淆 这样 在manifest文件注册了 到时候会找不到名字

  • 注释不能混淆 -keepattributes Annotation

其他不该混淆的

  • 1 jni调用的java方法
  • 2 java的native的方法
  • 3 js调用的java方法
  • 4 第三方库不建议混淆

原文:http://droidyue.com/blog/2016/07/10/understanding-android-obfuscated-code-by-proguard/

总结

其实不要混淆的主旨就在于混淆会改变方法的名字,类的名字,但是对于外部的一些引用是通过名字找到对应的方法,类,这些可能是通过string找到方法,类,但是string里的字段是不会进行混淆,所以还是会保留原来的名字,这样混淆过后通过原来的名字去找混淆后的名字,是肯定找不到,所以就会报出nosuchfileException,(对于gson,反射,jsbridge,第三方库都是这个原因),至于说枚举类型,我还暂时没懂 为什么,还望共同学习,一起成长。
文章是读了两篇博客写出来,也是自己总结,消化成自己的知识了,若有什么错误的地方,还望指出,相信读了这两篇文章之后你也会懂混淆,一个是如何混淆,一个是哪些该混淆,为什么不能混淆

你可能感兴趣的:(android 混淆)