开启混淆
在AS中,借助于SDK中自带的PRoguard工具,开启混淆只需要在release闭包中添加如下两行代码:
release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' }其中minifyEnabled表示是否开启混淆,开启后打包出的apk就是混淆过的了。
有些代码如果被混淆了就会报错,因此需要混淆规则来定义那些不能混淆的代码。
proguard-android.txt是默认的混淆规则,该文件位于fake-path—sdk/tools/proguard目录下,它对本机上所有项目的混淆都生效,所以一般不改动这个文件。
proguard-rules.pro默认在每个项目的app模块中,我们可以在这个文件中编写适用于当前项目的混淆规则。
默认情况下,这样的写法会使两个文件中的混淆规则同时生效。
混淆语法
keep关键字
proguard中一共有三组六个keep关键字,区别如下:
| 关键字 | 描述 |
| keep | 保留类和类中的成员,防止它们被混淆或移除。 |
| keepnames | 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。 |
| keepclassmembers | 只保留类中的成员,防止它们被混淆或移除。 |
| keepclassmembernames | 只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。 |
| keepclasseswithmembers | 保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。 |
| keepclasseswithmembernames | 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。 |
通配符
| 通配符 | 描述 |
<field> | 匹配类中的所有字段 |
<method> | 匹配类中的所有方法 |
<init> | 匹配类中的所有构造函数 |
| * | 匹配任意长度字符,但不含包名分隔符(.)。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。 |
| ** | 匹配任意长度字符,并且包含包名分隔符(.),包括任意长度的子包。 |
*** | 匹配任意参数类型。比如void set*()就能匹配任意传入的参数类型, get*()就能匹配任意返回值的类型。 |
| … | 匹配任意长度的任意类型参数。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)这些方法。 |
默认混淆规则
下面是proguard-android.txt文件中的内容(手动加了注释):
# This is a configuration file for ProGuard.# http://proguard.sourceforge.net/index.html#manual/usage.html#混淆时不使用大小写混合类名。 -dontusemixedcaseclassnames#不跳过library中的非public的类。 -dontskipnonpubliclibraryclasses#混淆后产生映射文件#包含有类名->混淆后类名的映射关系-verbose# Optimization is turned off by default. Dex does not like code run# through the ProGuard optimize and preverify steps (and performs some# of these optimizations on its own).#不进行优化,建议使用此选项,因为根据proguard-android-optimize.txt中的描述,优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行。 -dontoptimize#不进行预校验。这个预校验是作用在java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度。-dontpreverify# Note that if you want to enable optimization, you cannot just# include optimization flags in your own project configuration file;# instead you will need to point to the# "proguard-android-optimize.txt" file instead of this one from your# project.properties file.#对注解中的参数进行保留。-keepattributes *Annotation*#不混淆声明的这两个类,这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。-keep public class com.google.vending.licensing.ILicensingService-keep public class com.android.vending.licensing.ILicensingService# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native#不混淆任何包含native方法的类的类名以及native方法名,但当成员没有被引用时会被移除-keepclasseswithmembernames class * { native <methods>;}# keep setters in Views so that animations can still work.# see http://proguard.sourceforge.net/manual/examples.html#beans#不混淆任何一个View中的setXxx()和getXxx()方法,因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。-keepclassmembers public class * extends android.view.View { void set*(***); *** get*();}# We want to keep methods in Activity that could be used in the xml attribute onClick#不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性,当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了。-keepclassmembers class * extends android.app.Activity { public void *(android.view.View);}# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations#不混淆枚举中的values()和valueOf()方法-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String);}#不混淆Parcelable实现类中的CREATOR字段,毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。-keepclassmembers class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator CREATOR;}#不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。 -keepclassmembers class **.R$* { public static <fields>;}# The support library contains references to newer platform versions.# Don't warn about those in case this app is linking against an older# platform version. We know about them, and they are safe.#对android.support包下的代码不警告,因为兼容库的中代码是安全的-dontwarn android.support.**# Understand the @Keep support annotation.#不混淆keep注解-keep class android.support.annotation.Keep-keep @android.support.annotation.Keep class * {*;}-keepclasseswithmembers class * { @android.support.annotation.Keep <methods>;}-keepclasseswithmembers class * { @android.support.annotation.Keep <fields>;}-keepclasseswithmembers class * { @android.support.annotation.Keep <init>(...);}自定义混淆规则
我们可以在当前项目的proguard-rules.pro中定义如下混淆规则,其中第三方混淆规则将不定期更新、完善:
##---------------Begin: proguard configuration common for all Android apps ----------#代码混淆压缩比,在0~7之间,默认为5,一般不做修改-optimizationpasses 5-dontusemixedcaseclassnames-dontskipnonpubliclibraryclasses-dontskipnonpubliclibraryclassmembers-dontpreverify-verbose-dump class_files.txt-printseeds seeds.txt-printusage unused.txt-printmapping mapping.txt#指定混淆采用的算法,后面的参数是一个过滤器#这个过滤器是谷歌推荐的算法,一般不做更改-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*-allowaccessmodification-keepattributes *Annotation*-renamesourcefileattribute SourceFile#抛出异常时保留代码行号-keepattributes SourceFile,LineNumberTable-repackageclasses ''#保留我们使用的四大组件,自定义的application等这些子类不被混淆#因为这些子类都有可能被外部调用-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-dontnote com.android.vending.licensing.ILicensingService# Explicitly preserve all serialization members. The Serializable interface# is only a marker interface, so it wouldn't save them.-keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private 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();}# Preserve all native method names and the names of their classes.-keepclasseswithmembernames class * { native <methods>;}-keepclasseswithmembernames class * { public <init>(android.content.Context, android.util.AttributeSet);}-keepclasseswithmembernames class * { public <init>(android.content.Context, android.util.AttributeSet, int);}# Preserve static fields of inner classes of R classes that might be accessed# through introspection.-keepclassmembers class **.R$* { public static <fields>;}# Preserve the special static methods that are required in all enumeration classes.-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String);}-keep public class * { public protected *;}-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}#实体类-keep class com.bean.** { *; }##---------------End: proguard configuration common for all Android apps ----------#Gson# Gson uses generic type information stored in a class file when working with fields. Proguard# removes such information by default, so configure it to keep all of it.#避免混淆泛型-keepattributes Signature# Gson specific classes-keep class sun.misc.Unsafe { *; }#-keep class com.google.gson.stream.** { *; }-keep class sun.misc.Unsafe.** { *; }-keep class sun.misc.Unsafe.**-keep class com.google.** { *; }#org apache-keep class org.apache.** { *; }#baidumap-keep class com.baidu.** { *; }-keep class com.baidu.**-keep class vi.com.gdi.bgl.android.**{*;}-keep class vi.com.gdi.bgl.android.**-keep class com.baidu.** {*;}-keep class vi.com.** {*;}-dontwarn com.baidu.**#chartengine-keep class org.achartengine.** { *; }-keep class org.achartengine.**#youmeng-keep class com.umeng.analytics.**{*;}-keep class com.umeng.analytics.**-keep class u.aly.** {*;}-keep class u.aly.**#alipay-keep class com.alipay.** { *; }-keep class com.alipay.**-keep class com.ta.utdid2.** { *; }-keep class com.ta.utdid2.**-keep class com.ut.device.** { *; }-keep class com.ut.device.**-keep class org.json.alipay.** { *; }-keep class org.json.alipay.**#pinyin4j-keep class com.hp.hpl.sparta..** { *; }-keep class com.hp.hpl.sparta..**-keep class demo..** { *; }-keep class demo..**-keep class net.sourceforge.pinyin4j..** { *; }-keep class net.sourceforge.pinyin4j..**#http legacy#webkit-keepclassmembers class * extends android.webkit.WebChromeClient{ public void openFileChooser(...);}#open-sdk mta-sdk libammsdk-keep class com.tencent..** { *; }-keep class com.tencent..**#zxing-keep class com.google.zxing.** { *; }-keep class com.google.zxing.**-dontwarn java.lang.invoke**-dontwarn org.apache.lang.**-dontwarn org.apache.commons.**-dontwarn com.com.nostra13.**-dontwarn com.github.**-dontwarn com.squareup.**#retrofit# Platform calls Class.forName on types which do not exist on Android to determine platform.-dontnote retrofit2.Platform# Platform used when running on RoboVM on iOS. Will not be used at runtime.-dontnote retrofit2.Platform$IOS$MainThreadExecutor# Platform used when running on Java 8 VMs. Will not be used at runtime.-dontwarn retrofit2.Platform$Java8# Retain generic type information for use by reflection by converters and adapters.-keepattributes Signature# Retain declared checked exceptions for use by a Proxy instance.-keepattributes Exceptions-keep class com.life.me.entity.postentity{*;}-keep class com.life.me.entity.resultentity{*;}-dontwarn retrofit.-keep class retrofit. { *; }-dontwarn retrofit2.**-keep class retrofit2.** { *; }#butterknife-keep class butterknife.** { *; }-dontwarn butterknife.internal.**-keep class **$$ViewBinder { *; }-keepclasseswithmembernames class * { @butterknife.* <fields>;}-keepclasseswithmembernames class * { @butterknife.* <methods>;}#rx-dontwarn sun.misc.**-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { long producerIndex; long consumerIndex;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { rx.internal.util.atomic.LinkedQueueNode producerNode;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode;}#okhttp-dontwarn com.squareup.okhttp3.**-keep class com.squareup.okhttp3.** { *;}-dontwarn okhttp3.logging.**-keep class okhttp3.internal.**{*;}-dontwarn okio.**DexGuard
对于更高的安全需求,Proguard可能有些力不从心了。而DexGuard就能提供更安全的保护,关于它的资料可以点这里
参考资料:http://blog.csdn.net/guolin_blog/article/details/50451259