混淆是常用的减小app大小,增加app安全性的方法。
作用
代码混淆由ProGuard提供支持,ProGuard会检测和移除封装应用中未使用的类、字段、方法和属性,包括自带代码库中的未使用项(这使其成为以变通方式解决64k引用限制的有用工具)。ProGuard还可优化字节码,移除未使用的代码指令,以及用短名称混淆其余的类、字段和方法。混淆过的代码可令您的APK难以被逆向工程,这在应用使用许可验证等安全敏感性功能时特别有用。
以上为Android官网原文描述,其主要作用主要有那么几点:
- 减少方法数
- 增加反编译的难度
- app瘦身
一言不合上实例
以下为收集整理的混淆配置,复制到项目就可使用
-
通用配置
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#开启即可关闭混淆
#-dontobfuscate
#---------------Begin: proguard configuration common for all Android apps ----------#
#指定代码的压缩级别
-optimizationpasses 5
#包名不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
#优化 不优化输入的类文件
-dontoptimize
#预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#-------------start:记录生成的日志数据,gradle build时在本项目根目录输出-------------#
#apk 包内所有 class 的内部结构
-dump proguard/class_files.txt
#未混淆的类和成员
-printseeds proguard/seeds.txt
#列出从 apk 中删除的代码
-printusage proguard/unused.txt
#混淆前后的映射
-printmapping proguard/mapping.txt
#-------------End:记录生成的日志数据,gradle build时在本项目根目录输出-------------#
#避免混淆泛型 如果混淆报错建议关掉
#-keepattributes Signature
#保护注解
-keepattributes *Annotation*
# 保持哪些类不被混淆
-keep public class * extends android.support.v4.app.Fragment
-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
#如果有引用v4包可以添加下面这行
#-keep public class * extends android.support.v4.app.Fragment
#忽略警告
-ignorewarning
#如果引用了v4或者v7包
-dontwarn android.support.**
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable
#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保持枚举 enum 类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * {
public void *ButtonClicked(android.view.View);
}
#不混淆资源类
-keepclassmembers class **.R$* {
public static <fields>;
}
-keep class **.R { *; }
-keep class **.R$* { *; }
#移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
#-assumenosideeffects class android.util.Log {
# public static *** v(...);
# public static *** i(...);
# public static *** d(...);
# public static *** w(...);
# public static *** e(...);
#}
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
} -
ReactNative混淆配置
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#------------------------Start: React Native------------------------#
# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.proguard.annotations.DoNotStrip class *
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
@com.facebook.proguard.annotations.DoNotStrip *;
@com.facebook.common.internal.DoNotStrip *;
}
-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
void set*(***);
*** get*();
}
-keep class com.facebook.react.cxxbridge.ModuleRegistryHolder { *; }
-keep class com.facebook.react.cxxbridge.CatalystInstanceImpl { *; }
-keep class com.facebook.react.cxxbridge.JavaScriptExecutor { *; }
-keep class com.facebook.react.bridge.queue.NativeRunnable { *; }
-keep class com.facebook.react.bridge.ExecutorToken { *; }
-keep class com.facebook.react.bridge.ReadableType { *; }
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
-keepclassmembers,includedescriptorclasses class * { native <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; }
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }
-dontwarn com.facebook.react.**
# stetho
-dontwarn com.facebook.stetho.**
-keep class android.text.StaticLayout
#------------------------End: React Native------------------------# -
Gson
1
2
3
4
5
6
7-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
# Application classes that will be serialized/deserialized over Gson
# 下面替换成自己的实体类
-keep class com.example.bean.** { *; } -
Butter Knife
1
2
3
4
5
6
7
8
9-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
} -
Okio
1
2
3
4-dontwarn com.squareup.**
-dontwarn okio.**
-keep public class org.codehaus.* { *; }
-keep public class java.nio.* { *; } -
OkHttp3
1
2
3-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.** -
Retrofit
1
2
3
4-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions -
Ormlite
1
2
3
4
5
6
7
8
9-keepattributes *DatabaseField*
-keepattributes *DatabaseTable*
-keepattributes *SerializedName*
-keep class com.j256.**
-keepclassmembers class com.j256.** { *; }
-keep enum com.j256.**
-keepclassmembers enum com.j256.** { *; }
-keep interface com.j256.**
-keepclassmembers interface com.j256.** { *; } -
RxJava RxAndroid
1
2
3
4
5
6
7
8
9
10
11-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;
} -
AndroidEventBus
1
2
3
4
5-keep class org.simple.** { *; }
-keep interface org.simple.** { *; }
-keepclassmembers class * {
@org.simple.eventbus.Subscriber <methods>;
} -
EventBus
1
2
3
4
5-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; } -
Glide
1
2
3
4
5-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
混淆语法解析
-
保留选项(配置不进行处理的内容)
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 保护指定的类文件和类的成员
-keep {modifier} {class_specification}
# 保护指定类的成员,如果此类受到保护他们会保护的更好
-keepclassmembers {modifier} {class_specification}
# 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
-keepclasseswithmembers {class_specification}
# 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
-keepnames {class_specification}
# 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
-keepclassmembernames {class_specification}
# 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
-keepclasseswithmembernames {class_specification}
# 列出类和类的成员-keep选项的清单,标准输出到给定的文件
-printseeds {filename} -
压缩
1
2
3
4
5
6# 不压缩输入的类文件
-dontshrink
# 打印为什么一个类或类的成员被保护,这对检查一个输出文件中的类的结果有帮助.
-whyareyoukeeping {class_specification}
# 将被删除的元素输出到文件
-printusage {filename} -
优化
1
2
3
4
5
6# 不优化输入的类文件
-dontoptimize
# 优化时假设指定的方法,没有任何副作用
-assumenosideeffects {class_specification}
# 优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification -
混淆
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 不混淆输入的类文件
-dontobfuscate
# 使用给定文件中的关键字作为要混淆方法的名称
-obfuscationdictionary {filename}
# 混淆时应用侵入式重载
-overloadaggressively
# 确定统一的混淆类的成员名称来增加混淆
-useuniqueclassmembernames
# 重新包装所有重命名的包并放在给定的单一包中
-flattenpackagehierarchy {package_name}
# 重新包装所有重命名的类文件中放在给定的单一包中
-repackageclass {package_name}
# 混淆时不会产生形形色色的类名
-dontusemixedcaseclassnames
# 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-keepattributes {attribute_name,...}
# 设置源文件中给定的字符串常量
-renamesourcefileattribute {string}