安卓混淆和资源压缩

Android开发中掌握混淆规则是必备技能之一。

混淆方式

主module中统一配置

这种情况简单,针对自己项目代码和三方库代码编写混淆规则即可。当取消某些module依赖时,需要剔除响应的混淆规则,较麻烦。

各module单独配置

随着项目不断扩大,多个module同时存在的项目已很普遍。

  • 主module配置一些通用的混淆规则。
  • 子module在gradle中配置consumerProguardFiles属性来指定混淆文件就可以。

    1
    2
    3
    4
    5
    6
    // 子模块单独配置混淆规则
    buildTypes {
    release {
    consumerProguardFiles 'proguard-rules.pro'
    }
    }

proguard使用及规则

主module开启混淆配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
android {
...
buildTypes {
release {
// zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。
zipAlignEnabled true
// 压缩资源
shrinkResources true
// 开启混淆
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}

通用规则

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
#指定压缩级别
-optimizationpasses 5
#不跳过非公共的库的类成员
-dontskipnonpubliclibraryclassmembers
#混淆时采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#把混淆类中的方法名也混淆了
-useuniqueclassmembernames
#优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification
#将文件来源重命名为“SourceFile”字符串
-renamesourcefileattribute SourceFile
#保留行号
-keepattributes SourceFile,LineNumberTable
#保持泛型
-keepattributes Signature
#保持所有实现 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();
}
#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
# 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 {
# 保持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>(...);
}
# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**

哪些需要添加keep规则

  • 三方库
  • 反射代码
  • JNI native代码
  • webview js注入方法相关类

自定义规则及语法

  • 不混淆某个类
1
-keep public class name.huihui.example.Test { *; }
  • 不混淆某个包所有的类
1
-keep class name.huihui.test.** { *; }
  • 不混淆某个类的子类
1
-keep public class * extends name.huihui.example.Test { *; }
  • 不混淆所有类名中包含了“model”的类及其成员
1
-keep public class **.*model*.** {*;}
  • 不混淆某个接口的实现
1
-keep class * implements name.huihui.example.TestInterface { *; }
  • 不混淆某个类的构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
-keepclassmembers class name.huihui.example.Test {
<init>; #匹配所有构造器
<fields>;#匹配所有域
<methods>;#匹配所有方法}
public void test(java.lang.String); # 特定方法
public <methods>;#保持该类下所有的共有方法不被混淆
public *;#保持该类下所有的共有内容不被混淆
private <methods>;#保持该类下所有的私有方法不被混淆
private *;#保持该类下所有的私有内容不被混淆
public <init>(java.lang.String);#保持该类的String类型的构造方法
}
  • 不混淆某个类的内部类
1
2
3
-keep class name.huihui.example.Test$* {
*;
}

Thanks

0%