android 混淆

作者: bogerLiu | 来源:发表于2016-12-16 11:40 被阅读737次

    混淆的原理

    其实不要混淆的主旨就在于混淆会改变方法的名字,类的名字,但是对于外部的一些引用是通过名字找到对应的方法,类,这些可能是通过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方法不会被混淆
    • 再者希望类的全部方法不会被混淆 可以使用如下方法<init>保证类的构造器不会被混淆
      -keep class com.ll.ui.activity { public <init>; }
    • 当然public 还可以换成是private protect等修饰
      <fields> 匹配所有域不会被混淆
      <methods> 匹配所有函数方法不会被混淆
      这些后面还可以加入参数
      -keep class com.ll.ui.activity { public <init>(com.android.Activity); }表示activity作为参数的构造函数不会被混淆
    • -keep 保证类和类的成员都不会被混淆
    • -keepclassmembers 保证成员不会被混淆但是类是会被混淆
    • -keepclasswithmembers 如果类拥有了某成员 保证类和成员不会被混淆

    注意事项

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

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

    • 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 混淆

        本文链接:https://www.haomeiwen.com/subject/bejnmttx.html