混淆的原理
其实不要混淆的主旨就在于混淆会改变方法的名字,类的名字,但是对于外部的一些引用是通过名字找到对应的方法,类,这些可能是通过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,第三方库都是这个原因),至于说枚举类型,我还暂时没懂 为什么,还望共同学习,一起成长。
文章是读了两篇博客写出来,也是自己总结,消化成自己的知识了,若有什么错误的地方,还望指出,相信读了这两篇文章之后你也会懂混淆,一个是如何混淆,一个是哪些该混淆,为什么不能混淆
网友评论