在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模块中,我们可以在这个文件中编写适用于当前项目的混淆规则。
默认情况下,这样的写法会使两个文件中的混淆规则同时生效。
proguard中一共有三组六个keep关键字,区别如下:
关键字 | 描述 |
---|---|
keep | 保留类和类中的成员,防止它们被混淆或移除。 |
keepnames | 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。 |
keepclassmembers | 只保留类中的成员,防止它们被混淆或移除。 |
keepclassmembernames | 只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。 |
keepclasseswithmembers | 保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。 |
keepclasseswithmembernames | 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。 |
通配符 | 描述 |
---|---|
|
匹配类中的所有字段 |
|
匹配类中的所有方法 |
|
匹配类中的所有构造函数 |
* | 匹配任意长度字符,但不含包名分隔符(.)。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。 |
** | 匹配任意长度字符,并且包含包名分隔符(.),包括任意长度的子包。 |
*** |
匹配任意参数类型。比如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 ;
}
# 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 ;
}
# 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 ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep (...);
}
我们可以在当前项目的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 ;
}
-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public (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 ;
}
# 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.* ;
}
-keepclasseswithmembernames class * {
@butterknife.* ;
}
#阿里百川hotfix
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native ;
}
-keep class com.alipay.euler.andfix.**{
*;
}
-keep class com.taobao.hotfix.aidl.**{*;}
-keep class com.ta.utdid2.device.**{*;}
-keep class com.taobao.hotfix.HotFixManager{
public *;
}
#如果是打修复包,需要在当前模块中放有对应版本的mapping.txt文件
#再添加下面一行配置,保证修复前后两个APK的混淆结果一致
-applymapping mapping.txt
#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.**
#极光推送
-dontoptimize
-dontpreverify
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
#LitePal
-keep class org.litepal.** {
*;
}
-keep class * extends org.litepal.crud.DataSupport {
*;
}
#扫码
-keepclassmembers class net.sourceforge.zbar.ImageScanner { *; }
-keepclassmembers class net.sourceforge.zbar.Image { *; }
-keepclassmembers class net.sourceforge.zbar.Symbol { *; }
-keepclassmembers class net.sourceforge.zbar.SymbolSet { *; }
#联迪pos
-dontwarn com.landicorp.**
#新大陆pos
-dontwarn com.newland.**
-keep class com.newland.payment.trans.bean.** { *; }
#画板
-dontwarn me.panavtec.drawableview.**
对于更高的安全需求,Proguard可能有些力不从心了。而DexGuard就能提供更安全的保护,关于它的资料可以点这里
参考资料:http://blog.csdn.net/guolin_blog/article/details/50451259