在应用发布前,需要对代码进行混淆处理,从而让我们代码即使被反编译,也难以阅读。
Android Studio自身集成Java语言的ProGuard作为压缩,优化、混淆和预检工具,配合Gradle构建工具使用很简单,只需要在工程应用目录的gradle文件中设置minifyEnabled为true即可。然后我们就可以到proguard-rules.pro文件中加入我们的混淆规则了。ProGuard一共包括以下4个功能。
压缩(Shrink): 侦测并移除代码中无用的类、字段、方法、和特性(Attribute)。
优化(OPtimize): 对字节码进行优化,移除无用指令。
混淆(Obfuscate): 使用a、b、c、d这样简短而无意义的名称,对类、字段和方法进行重命名。
预检(Preveirfy): 在java平台上对处理后的代码进行预检。
关于混淆规则,这两篇文章写的很好,值得参考:
仔细研究那些书写规则之后,就可以自己独立写混淆文件了。
注意gradle文件中的设置:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
其中提到proguard-android.txt,这里保存着默认混淆规则,文件真实路径在:Sdk\tools\proguard之下。
这里贴一下里面的内容(Android Studio 3.1)
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# This file is no longer maintained and is not used by new (2.2+) versions of the
# Android plugin for Gradle. Instead, the Android plugin for Gradle generates the
# default rules at build time and stores them in the build directory.
-dontusemixedcaseclassnames
-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).
-dontoptimize
-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*
-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
-keepclasseswithmembernames class * {
native <methods>;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-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
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
-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.
-dontwarn android.support.**
# Understand the @Keep support annotation.
-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>(...);
}
因此许多规则不需要重写,只需要关注自定义的类及其成员等等,以及引用的第三方包。
混淆示例:
本人某个APP中,build.gradle中的依赖如下:
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:design:26.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation 'com.github.florent37:materialtextfield:1.0.7'
implementation 'com.github.bumptech.glide:glide:4.2.0'
implementation 'jp.wasabeef:glide-transformations:3.0.1'
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
其中Android官方包以及Activity的忽略,都在默认混淆规则中处理掉了,剩下的某些依赖不需要添加混淆忽略处理,而代码中没有其他特别的,因此proguard-rules.pro文件如下所示:
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# okhttp3
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
# glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
检测:
第一步:重新测试APP,未发现异常。
第二步:用APKtool、smali2dex、dex2jar及JD-GUI反编译可知,代码可读性差了很多,反编译破解难度大大增加。