博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android混淆配置
阅读量:4180 次
发布时间:2019-05-26

本文共 9890 字,大约阅读时间需要 32 分钟。

        项目到了快发布的时候,我们必然会对项目打包进行混淆,这样做可以提高别人对我们项目反编译的难度,其实Android的混淆在Android studio中已经帮我们做了一些基本的配置,看了网上了一些讲关于混淆的,都说在android sdk 目录下 \sdk\tools\proguard\proguard-android.txt 下提供了默认的混淆配置,我们打开这个文件查看,发现开头有这样一段注解:

# 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.

大致的意思就是说这个文件不再维护了,并且在Android Gradle插件2.2+以上不再使用了。相反,Android Gradle插件在构建时生成默认规则,并将它们存储在build目录中。所以说现在混淆的默认规则是由Gradle自动生成的。我们先看一点gradle中的配置:

buildTypes {    release {        minifyEnabled true        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        println getDefaultProguardFile('proguard-android.txt')    }}

要生成默认规则,上面的minifyEnable一定要改为true,如果为false是不会生成的。我们看到上面有一个输出语句println,这里打印的就是生成的proguard-android.txt文件的位置:

getDefaultProguardFile('proguard-android.txt').exists()

可以通过上面这个输出语句判断文件是否存在,minifyEnable为true时存在的,为false时是不存在的,如果已经存在,为false也是存在的,来看下输出:

E:\AndroidWorkProject\proguardtest\build\intermediates\proguard-files\proguard-android.txt-3.1.0

这里在说下查看输出的位置,对于3.0之前的版本,右下角有个Gradle Console可以查看,我用的是Android studio 3.1,查看位置如下图:

在看下生成后的工程目录:

在build目录下生成了三个混淆文件,可以看到这里多出了一串数字,这个是Gradle插件的版本号,后面会讲到。proguard-android.txt-3.1.0使用这个文件混淆时,是不会对混淆进行优化的,而另外两个是在混淆时会进行优化。

        接下来我们来看下下面这个方法:

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

对于studio是3.0之前的版本,想要看源码需要配置,不会的自己百度。对于这样的代码如果你有点看不太懂,那你就需要补点Groovy的语法了,这里我们先看下下面这个方法:

getDefaultProguardFile('proguard-android.txt')

这里我们直接按住ctr+左键 进入到这个方法内部去瞧一瞧,

public File getDefaultProguardFile(String name) {    if (!ProguardFiles.KNOWN_FILE_NAMES.contains(name)) {        extraModelInfo                .getSyncIssueHandler()                .reportError(                        EvalIssueReporter.Type.GENERIC, ProguardFiles.UNKNOWN_FILENAME_MESSAGE);    }    return ProguardFiles.getDefaultProguardFile(name, project);}

这里看到有一个判断,判断在这个集合中是否包含传进来的name,这个集合是通过lambda将一个枚举转换过来的的,我们来看下这个枚举:

public enum ProguardFile {    /** Default when not using the "postProcessing" DSL block. */    DONT_OPTIMIZE("proguard-android.txt"),    /** Variant of the above which does not disable optimizations. */    OPTIMIZE("proguard-android-optimize.txt"),    /**     * Does not disable any actions, includes optimizations config. To be used with the new     * "postProcessing" DSL block.     */    NO_ACTIONS("proguard-defaults.txt"),    ;    @NonNull public final String fileName;    ProguardFile(@NonNull String fileName) {        this.fileName = fileName;    }}
就是上面生成的那三个文件,我们接着往下看getDefaultProguardFile()这个方法:

public static File getDefaultProguardFile(@NonNull String name, @NonNull Project project) {    if (!KNOWN_FILE_NAMES.contains(name)) {        throw new IllegalArgumentException(UNKNOWN_FILENAME_MESSAGE);    }    return FileUtils.join(            project.getRootProject().getBuildDir(),            AndroidProject.FD_INTERMEDIATES,            "proguard-files",            name + "-" + Version.ANDROID_GRADLE_PLUGIN_VERSION);}

这个KNOW_FILE_NAMES还是上面那个集合,这里就是判断传进来的那个name是否是三个文件名中的一个,如果不是,那么会抛异常,我们来看下这个异常:

Supplied proguard configuration file name is unsupported. Valid values are: [proguard-android-optimize.txt, proguard-defaults.txt, proguard-android.txt]

这就是说传进来的文件名必须是这三个文件名中的一个,上面我们看到生成的文件有一个版本号的后缀,在这里我们就可以得到解释了,我们再往下看这个join方法:

public static File join(@NonNull File dir, @NonNull String... paths) {    if (paths.length == 0) {        return dir;    }    return new File(dir, PATH_JOINER.join(paths));}
这下就该明白了,这里就是在创建一个文件。看来默认的混淆文件就是这样创建而来的。

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

到这,getDefaultProguardFile()就分析完了,接下来就是是看proguardFiles,这也是个方法,后面的就是方法中的参数,proguard-rules.pro就是我们自己定义的混淆规则,来看看代码:

public BuildType proguardFiles(@NonNull Object... files) {    checkPostprocessingConfiguration(PostprocessingConfiguration.OLD_DSL, "proguardFiles");    for (Object file : files) {        proguardFile(file);    }    return this;}

遍历所有传进来的文件然后执行proguardFile():

public BuildType proguardFile(@NonNull Object proguardFile) {    checkPostprocessingConfiguration(PostprocessingConfiguration.OLD_DSL, "proguardFile");    getProguardFiles().add(project.file(proguardFile));    return this;}

这里getProguardFiles()返回的是一个List集合,也就是说这里把所有的混淆文件添加进了一个集合中,也就是说这两个混淆文件是共同作用的。

        我们这里来看下Android中的默认混淆规则,也就是proguard-android.txt这个文件中的内容:

-dontoptimize-dontusemixedcaseclassnames-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-keepclasseswithmembernames class * {    native 
;}# Keep setters in Views so that animations can still work.-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 ** CREATOR;}-keepclassmembers class **.R$* { public static
;}# Preserve annotated Javascript interface methods.-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.-dontnote android.support.**-dontwarn android.support.**# This class is deprecated, but remains for backward compatibility.-dontwarn android.util.FloatMath# Understand the @Keep support annotation.-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
(...);}

这里看到有好些规则Android中已经为我们配置了,那么我们在proguard-rules.pro中就没必要在去重新配置了,看到网上的好多配置都在proguard-rules.pro中去重新配置了。

        这里我说一个配置的属性,在proguard-rules.pro中我们配置如下属性:

-assumenosideeffects class android.util.Log {    public static int v(...);    public static int i(...);    public static int w(...);    public static int d(...);    public static int e(...);}

并且把proguard-android.txt中-dontoptimize去掉,那么我们在代码中的log日志将不会打印,当然也可以通过自己写个日志工具类来控制是否输出。

       
再来一个配合proguard-android.txt的proguard-rules.pro的通用配置:
# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改-optimizationpasses 5# 指定不去忽略非公共库的类成员-dontskipnonpubliclibraryclassmembers# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。-dontpreverify# 保留Annotation不混淆-keepattributes *Annotation*,InnerClasses# 避免混淆泛型-keepattributes Signature# 抛出异常时保留代码行号-keepattributes SourceFile,LineNumberTable# 指定混淆是采用的算法,后面的参数是一个过滤器# 这个过滤器是谷歌推荐的算法,一般不做更改-optimizations !code/simplification/cast,!field/*,!class/merging/*############################################### Android开发中一些需要保留的公共部分############################################### 保留我们使用的四大组件,自定义的Application等等这些类不被混淆# 因为这些子类都有可能被外部调用-keep public class * extends android.app.Activity-keep public class * extends android.app.Appliction-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 * extends android.view.View# 保留support下的所有类及其内部类-keep class android.support.** {*;}# 保留继承的-keep public class * extends android.support.v4.**-keep public class * extends android.support.v7.**-keep public class * extends android.support.annotation.**# 保留我们自定义控件(继承自View)不被混淆-keep public class * extends android.view.View{    public 
(android.content.Context); public
(android.content.Context, android.util.AttributeSet); public
(android.content.Context, android.util.AttributeSet, int);}# 保留Parcelable序列化类不被混淆-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}# 保留Serializable序列化的类不被混淆-keepnames class * implements java.io.Serializable-keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; !static !transient
; !private
; !private
; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve();}# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆-keepclassmembers class * { void *(**On*Event); void *(**On*Listener);}# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用# 记得proguard-android.txt中一定不要加-dontoptimize才起作用# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制#-assumenosideeffects class android.util.Log {# public static int v(...);# public static int i(...);# public static int w(...);# public static int d(...);# public static int e(...);#}
当我们这样配置编译报错时,如果是没有忽略warning,我么可以加上:
-ignorewarnings

好了,到这就差不多了。

你可能感兴趣的文章
std::max、std::min error C2589: “(”:“::”右边的非法标记,error C2059: 语法错误:“::”
查看>>
在Ubuntu Server上编译FFmpeg
查看>>
git 切换到远程分支
查看>>
AAC的ADTS头文件信息介绍
查看>>
CMAKE手册
查看>>
Doubango RTP包传输使用UDT可靠传输协议,解决RTP丢包问题
查看>>
Android手机H264软编码参数优化
查看>>
将AAC格式的RTP流存储为可以播放的m4a文件
查看>>
UDT协议-基于UDP的可靠数据传输协议
查看>>
[FFMPEG硬件加速]nvidia方案
查看>>
openal播放裸数据
查看>>
OpenAL对象属性
查看>>
OpenAL 3D效果营造
查看>>
librtmp协议分析---RTMP_SendPacket函数
查看>>
视频学习笔记:Android ffmpeg解码多路h264视频并显示
查看>>
关于对H264码流的TS的封装的相关代码实现
查看>>
PortAudio+webrtc+lame实现采集降噪增益mp3
查看>>
视频压缩编码和音频压缩编码的基本原理
查看>>
利用FFmpeg玩转Android视频录制与压缩(二)
查看>>
利用FFmpeg玩转Android视频录制与压缩(三)
查看>>