Android混淆
来源:互联网 发布:迅龙数据恢复免费版 编辑:程序博客网 时间:2024/05/16 16:08
Proguard特性
- 压缩:Java源代码通常被编译为字节码,虽然字节码比源代码更简洁,但它本身仍然会包含很多无用的代码。Proguard的压缩功能通过分析字节码,能够检测并移除没有使用的类,字段,方法和属性;
- 优化:优化Java字节码,同时移除没有使用到的指令;
- 混淆:使用无意义的简短字母组合对类名、字段名、方法名进行重命名;
- 预检验:对上述处理后的代码进行预检验;
混淆配置
buildTypes { release { minifyEnabled true //true表示使能Proguard proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
混淆文件的规则分类
- 公共的混淆规则:每个APP都通用的,主要是对Proguard的基本配置,以及Android SDK中API设置的规则,例如Activity、Parcelable等;
- App特有的混淆规则:根据APP自身的特点进行设置,例如某些类会被反射调用,如果被混淆,那么反射就找不到类了;
- 第三方函数库或者SDK的混淆规则:如果APP引入了第三方开源函数库或者SDK,那么需要查看这些函数库或者SDK的使用说明,将需要去混淆的地方加上去;
混淆文件编写
#代码迭代优化的次数,取值范围0 - 7,默认5-optimizationpasses 5#混淆时不使用大小写混合的方式,这样混淆后都是小写字母的组合-dontusemixedcaseclassnames#混淆时不做欲校验,欲校验是Proguard四大功能之一,在Android中一般不需要欲校验,这样可以加快混淆的速度-dontpreverify#混淆时记录日志,同时会生成映射文件,Android Studio中,生成的默认映射文件是 'build/outputs/mapping/release/mapping.txt'-verbose#生成指定的映射文件的路径和名称-printmapping build/outputs/mapping/release/mymapping.txt#混淆时所采用的算法,参数是Google官方推荐的过滤器算法-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*#如果项目中用到了注解,需要保留注解属性-keepattributes *Annotation*#不混淆泛型-keepattributes Signature#保留代码行号,这在混淆后代码运行中抛出异常信息时,有利于定位出问题的代码-keepattributes SourceFile,LineNumberTable#保持Android SDK相关API类不被混淆-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 com.android.vending.licensing.ILicensingService#保留R类-keep class **.R$*{ *;}#保留native方法不被混淆-keepclasseswithmembernames class * { native<methods>;}#保持自定义控件类不被混淆-keepclasseswithmembers class * { public <init>(android.content.Context,android.util.AttributeSet);}-keepclasseswithmembers class * { public <init>(android.content.Context,android.util.AttributeSet,int);}#保持Activity中参数是View类型的参数,保证在Layout XML文件配置的 onClick 属性的值能够正常调用到-keepclassmembers class * extends android.app.Activity{ public void *(android.view.View);}#保持枚举类不被混淆-keepclassmembers enum * { public static ** [] values(); public static ** valueOf(java.lang.String);}#保持Parcelable不被混淆-keep class * implements android.os.Parcelable{ public static final android.os.Parcelable$Creator *;}#保持Serializable序列化类相关方法和字段不被混淆-keepclassmembers class * implements java.io.Serializable{ static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; !static !transient <fields>; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve();}#保持自定义控件不被混淆-keep public class * extends android.view.View{ public <init>(android.content.Context); public <init>(android.content.Context,android.util.AttributeSet); public <init>(android.content.COntext,android.util.AttributeSet,int); public void set*(...); *** get*();}#引入各个开源库需要增加的混淆
针对App的量身定制
假设我们创建一个项目,包名和结构名如下:
1、保留实体类和成员不被混淆
对于实体类,要保留它们的set和get方法,对于boolean型get方法,有人喜欢命名为isXXX方式,所以不要遗漏。一种好的做法是把所有实体都放在一个包下管理,这样只写一次混淆就够了,避免在别的包中新增实体而忘记保留,代码在混淆后因为找不到实体类而崩溃。
-keep public class heyha.nj.com.heyha.entity.** { public void set*(***); public *** get*(); public *** is*();}
2、内嵌类
内嵌类经常被混淆,结果在调用的时候为空就崩溃了。最好的解决办法就是把这个内嵌类拿出来,单独成类。如果一定要内置,那这个类就必须在混淆时保留,例如保留heyha.nj.com.heyha.activity包下MainActivity的所有内嵌类,代码如下:$是用于分割内嵌类与其母体的标识。
-keep class com.heyha.nj.heyha.activity.MainActivity$* { *;}
3、对WebView的处理
如果用到了webview的复杂操作,需要添加如下代码:
-keepclassmembers class * extends android.webkit.webViewClient { public void *(android.webkit.WebView,java.lang.String,android.graphics.Bitmap); public boolean *(android.webkit.WebView,java.lang.String);}-keepclassmembers class * extends android.webkit.webViewClient { public void *(android.webkit.webView,java.lang.String);}
4、对JavaScript的处理
App与HTML5页面的JavaScript进行交互,如下所示:
class JSInteface1 { @JavascriptInterface public void callAndroidMethod(int a, float b, String c, boolean d){ if(d){ String strMessage = "-" + (a + 1) + "-" + (b + 1) + "-" + c + "-" + d; new AlertDialog.Builder(MainActivity.this).setTitle("title") .setMessage(strMessage).show(); } }}
JSInteface1是MainActivity的子类,所以保留指令写法如下,而且需要对所有使用的地方设置保留指令
-keepclassmembers class com.heyha.nj.heyha.activity.MainActivity$JSInteface1 { <methods>;}
5、处理反射
在混淆过程中,无论是Class.forName(“SomeClass”),还是SomeClass.class,SomeClass这个类的名称都会被混淆,因此,在混淆文件中,需要保留这个类。此外,还有如下方法:
SomeClass.class.getField("someField")SomeClass.class.getDeclaredField("someField")SomeClass.class.getMethod("someMethod",new Class[]{})SomeClass.class.getMethod("someMethod",new Class[]{A.class})SomeClass.class.getMethod("someMethod",new Class[]{A.class,B.class})SomeClass.class.getDeclaredMethod("someMethod",new Class[]{})SomeClass.class.getDeclaredMethod("someMethod",new Class[]{A.class})SomeClass.class.getDeclaredMethod("someMethod",new Class[]{A.class,B.class})AtomicIntegerFieldUpdater.newUpdater(SomeClass.class,"someField")AtomicLongFieldUpdater.newUpdater(SomeClass.class,"someField")AtomicReferenceFieldUpdater.newUpdater(SomeClass.class,SomeType.class,"someField")
6、自定义view的解决方案
凡是在layout目录中的xml布局文件中配置的自定义View,都不能进行混淆。为此要遍历layout下所有的xml布局文件,找到那些自定义view,然后确认其是否在proguard文件中保留了。
阅读全文
0 0
- Android混淆
- android 混淆
- Android 混淆
- Android-混淆
- Android 混淆
- android 混淆
- android 混淆
- android 混淆
- android混淆
- android混淆
- android混淆
- Android混淆
- android 混淆
- android混淆
- android混淆
- android混淆
- android混淆
- Android混淆
- 常用需求系列——字典和xml的互相转换
- Android 之 HttpClient 网络请求
- XmlDocument类
- python 时间库 time
- tomcat7和tomcat8的websocket区别
- Android混淆
- vue1.0和vue2.0的区别之路由
- C笔记 结构体
- 10分钟快速理解依赖注入
- PAT 1003. 我要通过!(20) —— java
- Android中MD5(16位或32位)加密工具类.
- list的三种循环方式
- http://www.importnew.com/15731.html
- Java基础第9讲--面向对象之继承