Android 项目可以在 build.gradle 开启 proguard 代码混淆。
Android 项目可以在模块的 build.gradle 文件配置开启混淆。
buildTypes {
debug {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
minifyEnabled true 表示开启混淆。shrinkResources 表示资源压缩。
需要注意的是 Library 项目无法使用 shrinkResources。shrinkResources 只能用于 APK 资源压缩。这可能是因为工具无法判断 Library 中的资源是否会被其他模块使用到,所以只有在构建整个 APK 的时候才能知道哪些资源是无用资源,才可以启用资源压缩。
混淆规则有 2 部分组成,Android SDK 自带的默认规则 proguard-android.txt 和项目自定义的 proguard-rules.pro。
项目自定义的 proguard-rules.pro。
不混淆四大组件和 Application,在 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
不混淆 ww 目录下的所有类:
-keep public class xx.yy.zz.ww.* {*;}
不混淆 ww 目录下的所有子目录和类,循环子目录下的所有内容:
-keep public class xx.yy.zz.ww.** {*;}
不混淆 AA 类的名称,但是混淆 AA 类的成员:
-keep public class xx.yy.zz.ww.AA
不混淆 AA 类的名称和成员:
-keep public class xx.yy.zz.ww.AA {*;}
不混淆 AA 类的某个 public 方法,可能被反射调用或者被 Native 代码回调的方法:
-keep class xx.yy.zz.ww.AA {
public void callbackByNavtiveMethodXXXX();
}
不混淆 Serializable 子类:
-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();
public ;
}
系统默认的 proguard-android.txt,位于 $ANDROID_HOME\tools\proguard\proguard-android.txt。在 Android Gradle Plugin (AGP)2.2 以上版本会使用编译期间生成的 proguard-android.txt,比如 build\intermediates\proguard-files\proguard-android.txt-3.3.2,而不是 SDK 里面的 proguard-android.txt。
proguard-android.txt-3.3.2 的规则如下:
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.
# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize steps (and performs some
# of these optimizations on its own).
# 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.
# 不启用优化
-dontoptimize
# 混淆时不使用大小写混写的类名
-dontusemixedcaseclassnames
# 不跳过库中非 public 的类
-dontskipnonpubliclibraryclasses
# 打印处理日志
-verbose
# Preserve some attributes that may be required for reflection.
# 保留注解、泛型、内部类、封闭方法
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
# 不混淆指定的类
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.android.vending.licensing.ILicensingService
# 不打印潜在的错误或者疏漏的注释
-dontnote com.android.vending.licensing.ILicensingService
-dontnote com.google.vending.licensing.ILicensingService
-dontnote com.google.android.vending.licensing.ILicensingService
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
# 不混淆 Native 方法
-keepclasseswithmembernames class * {
native ;
}
# Keep setters in Views so that animations can still work.
# 不混淆 View 子类的 set 和 get 方法
-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 的 public 方法
-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);
}
# 不混淆 Parceable 子类的 CREATOR 常量
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}
# 不混淆 R 类的所有 public static 成员
-keepclassmembers class **.R$* {
public static ;
}
# Preserve annotated Javascript interface methods.
# 不混淆 JavascriptInterface 注解的方法
-keepclassmembers class * {
@android.webkit.JavascriptInterface ;
}
# The support libraries 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.
# 不要警告 support 和 androidx 的报错
-dontnote android.support.**
-dontnote androidx.**
-dontwarn android.support.**
-dontwarn androidx.**
# This class is deprecated, but remains for backward compatibility.
# 不要警告 FloatMath 的报错
-dontwarn android.util.FloatMath
# Understand the @Keep support annotation.
# 不混淆 @Keep 注解的类、成员
-keep class android.support.annotation.Keep
-keep class androidx.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keep @androidx.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep ;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep ;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep (...);
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep (...);
}
# These classes are duplicated between android.jar and org.apache.http.legacy.jar.
# 不警告 org.apache.http 和 android.net.http
-dontnote org.apache.http.**
-dontnote android.net.http.**
# These classes are duplicated between android.jar and core-lambda-stubs.jar.
# 不警告 java.lang.invoke
-dontnote java.lang.invoke.**