我的Android混淆(Proguard文件)是怎么写的

当前环境

Android Studio: 3.2.1
Gradle 插件: ‘com.android.tools.build:gradle:3.2.1’
Gradle : gradle-4.6

具体配置

因为proguard文件要靠手写,所以有时候感觉很难,但是找到规律之后也挺简单的,感觉难是因为,不熟悉它的一些关键字,这里列出了常用的关键字,以及人能看懂的含义,其实要想看明白,自己写的Demo测试一下就好了,借助于反编译工具看下到底什么被混淆了,工具看这。我下面写了详细的注释github,常用的也就这么多了,其余的可以根据命令行进行调试,然后逐个添加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#-ignorewarnings                     # 忽略警告,避免打包时某些警告出现
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合 混淆时不会产生形形色色的类名
-dontskipnonpubliclibraryclasses # 是否混淆第三方jar
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志
-dontoptimize # 不优化输入的类文件

-keepattributes *Annotation*, SourceFile, InnerClasses, LineNumberTable, Signature, EnclosingMethod
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #优化 混淆时采用的算法

-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.app.View
-keep public class * extends android.app.IntentService
-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.hardware.display.DisplayManager
-keep public class * extends android.os.UserManager
-keep public class com.android.vending.licensing.ILicensingService
-keep public class * extends android.app.Fragment

-keep public class * extends android.support.v4.widget
# *匹配任意字符不包括 “ . ” ,**匹配任意字符
# 下面这行的意思是,保留v4下面的类名及其v4下面子包的类名不被混淆
-keep public class * extends android.support.v4.**
# 下面 这行表示一个接口中的所有的东西都不被混淆
-keep interface android.support.v4.app.** { *; }
# 下面这行表示保持这个包及其子包下面的所有类的类名及其类里面的所有内容都不混淆
-keep class android.support.v4.** { *; }
-keep class android.os.**{*;}
-keep class android.support.v8.renderscript.** { *; }

-keep class **.R$* { *; }
-keep class **.R{ *; }

#实现了android.os.Parcelable接口类的任何类,以及其内部定义的Creator内部类类型的public final静态成员变量,都不能被混淆和删除
-keep class * implements android.os.Parcelable { # 保持Parcelable不被混淆
public static final android.os.Parcelable$Creator *;
}

#keepclasseswithmembernames 保留类和类中的成员,防止被混淆,保留指明的成员,成员没有引用会被移除
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}

#keepclasseswithmembers 保留类和类中的成员,防止被混淆或移除,保留指明的成员
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * { # 保持自定义控件类不被混淆
public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int, int);
}

-keepclassmembers class * extends android.app.Activity { #保持类成员
public void *(android.view.View);
}

-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
public void *(android.view.MenuItem);
}

-keepclassmembers enum * { # 保持枚举 enum 类不被混淆
public static **[] values();
public static ** valueOf(java.lang.String);
}

# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepnames class * implements java.io.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();
}

#####################上面这些是系统默认配置的#####################3
## 一般来说上面的这些即使我们不写,开了混淆也会自动启用
## 现在我用的 Android Studio Gradle的插件是 3.2.1 这个插件自带默认混淆文件
## 在启用混淆的时候解压出来,详情参考 /项目名/build/intermediates/proguard-files/proguard-android.txt-3.2.1 里面的注释
## 注释上说gradle 的 Android 插件,从2.2 版本开始,不再使用sdk本地的Proguard,而以后gradle插件自带默认Proguard配置文件


#-libraryjars libs/jar包名字.jar #缺省proguard 会检查每一个引用是否正确,但是第三方库里面往往有些不会用到的类,没有正确引用。如果不配置的话,系统就会报错。
-dontwarn android.support.v4.**
-dontwarn android.os.**

#编译时关掉Log的打印,
#-assumenosideeffects class android.util.Log { #如果是自定义Log类,修改下面的包名
# public static *** d(...);
# public static *** e(...);
# public static *** i(...);
# public static *** v(...);
# public static *** println(...);
# public static *** w(...);
# public static *** wtf(...);
#}

##############################--------以上是Android基本配置----------##############################

# 实体类不混淆(自己项目实体类不被混淆,因为Gson中用到了反射)
#-keep class me.febsky.entity.** { *; }
### -----这是个列子---- ###
#这个类里面的所有的成员变量和方法都不混淆
-keep class me.febsky.testprogard.MainActivity { *; }
#这个类里面的内部类的所有的成员变量和方法都不混淆
-keep class me.febsky.testprogard.MainActivity$* { *; }
#这个类里面的所有public的内部类的所有的成员变量和方法都不混淆
-keep public class me.febsky.testprogard.MainActivity$* { *; }
#这个类里面的内部类的类名不备混淆,方法和变量还是混淆的
-keep class me.febsky.testprogard.MainActivity$*
#保持一个类的类名不被混淆,里面的方法和成员变量名还是被混淆的
-keep public class me.febsky.testprogard.MyOutClass
### -----这是个列子---- ###

## for sharedSDK
-keep class android.net.http.SslError
-keep class android.webkit.**{*;}
-keep class cn.sharesdk.**{*;}
-keep class com.sina.**{*;}
-keep class m.framework.**{*;}


#butter knife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}