Android Proguard混淆详解
2014-10-30 19:12
309 查看
介绍
Proguard是一款Java工具,具有收缩,优化,混淆,预验证功能。当构建版本时会连续执行这四个步骤:1.收缩(shrinker): 检测并删除无用的类,函数,属性,和域,以达到减小包体积的目的。2.优化(optimizer):优化字节码和删除无用的指令。3.混淆(obfuscator):把1和2处理后的包,再把类名和方法名以及域名换成无意义的且简短的字母来代替,如a,b。4.预验证(preverifier):预先验证经过1,2,3处理后的代码是否符合JAVA 6和Java Micro Edition的规则要求。以上四个步骤主要体现在配置文件上,首先在project.properties文件中添加一句proguard.config=proguard.cfg,并新建proguard.cfg文件,接着在proguard.cfg中写配置就可以了。实例
下面介绍Android工程proguard官方配置写法。-injars bin/classes #输入jars -injars libs #输入jars -outjars bin/classes-processed.jar #输出jars
#指明Android包位置,不过有可能已经指明,会混淆报错,报错就注释掉 #-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar
#打印混淆日志,方便以后跟踪
-printmapping bin/classes-processed.map
-dontpreverify #不要预检验 -repackageclasses '' #把因混淆重命名的类重新打包,放到同一个包下 -allowaccessmodification #允许在处理过程中扩大类的访问权限 -optimizations !code/simplification/arithmetic #优化的算法
#保持固定的资源文件,行号以及签名,方便后续问题跟踪和包验证
-renamesourcefileattribute SourceFile -keepattributes SourceFile,LineNumberTable,Signature
#保证注解不会被混淆,因为可能会在[code]RemoteViews中用到[/code]
-keepattributes *Annotation*
#保证Activity,Application,Service,BroadcastReceiver,ContentProvider不会被混淆,因为他们会在AndroidManifest.xml中用到,
#AndroidManifest.xml不会被混淆,所以他们也不能被混淆。后则混淆后的名称都是无意义的,AndroidManifest.xml会找不到这些类的。
-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.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*(...);}
#保持所有Context构造函数
-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet);}-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet, int);}
#保持onClick处理
-keepclassmembers class * extends android.content.Context { public void *(android.view.View); public void *(android.view.MenuItem);}
#R文件不能混淆,要靠它来取ID,下面的是官方的写法,但这样写会有问题,如果引用的jar包中包含布局文件,他们会通过反射取R文件,所以R文件的类名不能被混淆#-keepclassmembers class **.R$* {# public static <fields>;#}
-keep class **.R$* {public static <fields>;}
#保持Javascript接口
-keepclassmembers class * { @android.webkit.JavascriptInterface <methods>;}
#如果你用到了Google的证书校验,请把以下加上,如果没用到加上也行
-keep public interface com.android.vending.licensing.ILicensingService-dontnote com.android.vending.licensing.ILicensingService
#不让android-support-v*.jar警告
-dontwarn android.support.**
#保护本地代码
-keepclasseswithmembernames,includedescriptorclasses class * { native <methods>;}
#保持所有枚举类都要用到的静态方法,下面是官方写法
#-keepclassmembers,allowoptimization enum * {# public static **[] values();# public static ** valueOf(java.lang.String);#}
#但是这样,如果枚举用作序列化传递,会出现问题,所以枚举最好不要混淆
-keep enum * {*;}
4000
#Parcelable 的静态构造因为外界可能通过反射取值,下面是官方写法#-keepclassmembers class * implements android.os.Parcelable {# static android.os.Parcelable$Creator CREATOR;#}#为了防止奇奇怪怪的问题,最好也不要混淆
-keep class * implements android.os.Parcelable{*;}
#序列化保持,下面是官方写法
#-keepclassmembers class * implements java.io.Serializable {# static final long serialVersionUID;# 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();#}
#同Parcelable,应当不混淆
-keep class * implements java.io.Serializable {*;}以上的混淆配置已经基本上可以满足项目需要,如果没有引用第三方包的话。那么问题来了,如果引用第三方包怎么办(挖掘机技术哪家强)?答案是——不怎么办,根据情况而定。接下来要说对于jar包特殊处理,不过要提前了解一些东西, 也是前面看着晕晕乎乎东西的解释:
详解
1.keep
1.1 keep简介
Keep | 收缩时不被移出,混淆时不被重命名 | 混淆时不被重命名 |
---|---|---|
保持类和类的成员 | -keep | -keepnames |
仅保持类的成员 | -keepclassmembers | -keepclassmembernames |
保持类和类的成员,如果类的成员被展现出来的话 | -keepclasseswithmembers | -keepclasseswithmembernames |
1.2 keep保留
这里的keep,是指这些keep的代码不会经过收缩,优化和混淆步骤,当然如果你想保留某一步骤(比如你只想不混淆,还想收缩),可以额外加上allowshrinking(允许收缩),allowoptimization(允许优化),allowobfuscation(允许混淆)1.3 keep参数介绍
如果想keep特定的类或方法,可用下面这个模版匹配[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname[extends|implements [@annotationtype] classname][{[@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> |(fieldtype fieldname);[@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |<init>(argumenttype,...) |classname(argumenttype,...) |(returntype methodname(argumenttype,...));[@annotationtype] [[!]public|private|protected|static ... ] *;...}]是不是看晕了?再和上面的实例结合看一看,是不是又有点明白?下面解释一下
1.3.1 字段
@annotationtype 注解,注解是什么,就不在这里说了
public|private|protected|static|volatile|transient 修饰符,这个也不说了~~
interface|class|enum 类型
1.3.2 符号
[ ] 选项,可有可无| 或,比如interface|class|enum 只能在这个三个中选一个!取反,-keep class 就是保持class,如果-keep !class就是保持class之外的类型匹配符:? 匹配任意单个字符,包的分隔符除外,如"mypackage.Test?" 可以匹配 "
mypackage.Test1" 和 "
mypackage.Test2", 但不能匹配 "
mypackage.Test12".** 除包分隔符之外的任意多的字符串,例如, "
mypackage.*Test*" 匹配 "
mypackage.Test" 和"
mypackage.YourTestApplication", 但是不能匹配 "
mypackage.mysubpackage.MyTest"。总的来讲, "
mypackage.*" 匹配 "
mypackage"包中的所有类, 但是不能匹配它子包中的类。** 匹配所有任意数量字符,如"
mypackage.**" 匹配mypackage的所有子包和子类
1.3.3 方法
<init> | 匹配所有构造函数 |
<fields> | 匹配所有域 |
<methods> | 匹配所有方法 |
* | 匹配所有方法和域 |
第三方jar导入
现在言归正传,说如如何引用第三方jar包注:如果是library库引用,不用管~~~~~1.有的第三方jar包会报出warning警告,不用管,加上-dontwarn关键字就行。 e.g. fastjson-1.1.41.jar 用于json数据解析,混淆时会报Waring,脚本中加上-dontwarn com.alibaba.fastjson.**即可2.所有的jar包,请老老实实的加上-keep class 包名+**{*;},比如我有添加了apache的一个jar包,我要写上-keep class org.apache.**{*;},注:**指包含子包中的内容,{*;}指类中的所有方法。3.-keep class并不是绝对的,但为了节省一个个甄别的时间,都keep了也没多大关系。如果有必要的话,interface也要keep,这种情况比较少见4.有些jar包的特殊要求:如一些jar包要对某些类反射取值,这时候要对这些类进行保持。如fastjson,是对实体进行反射解析的,所以要对fastjson使用的实体进行keep小技巧:一般混淆方法,都会在jar包提供方的官方网站上提及,仔细找找噢~注:以上解说仅适用于proguard 5.0以上,如果低于次版本,请移步官方升级https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#downloads.html,升级方法也很简单,把下载的包解压出来,把SDK(路径:\sdk\tools\proguard)中的proguard文件夹替换掉就可以了。更详细的内容请参考:https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#相关文章推荐
- android 混淆文件proguard.cfg详解
- Android 混淆文件proguard-project.txt详解
- Android ProGuard 混淆 详解
- Android ProGuard 混淆 详解
- Android笔记:防反编译、混淆文件proguard.cfg与proguard-project.txt详解
- Android proguard 详解,代码混淆
- android 混淆文件proguard.cfg详解
- Android ProGuard 混淆 详解
- android 混淆文件proguard.cfg详解
- Android gradle proguard 代码混淆详解
- android 混淆文件proguard.cfg详解
- Android项目混淆ProGuard详解
- android 混淆文件proguard.cfg详解
- android 混淆文件proguard.cfg详解 (转载)
- Android 多渠道打包之混淆文件ProGuard技术详解-特别篇(打包系列教程之三)
- Android ProGuard 混淆 详解
- Android面向面试复习----Proguard混淆技术详解
- Android ProGuard代码混淆技术详解
- Android 中 ProGuard 混淆详解(二)
- Android ProGuard 混淆 详解