The document discusses effective techniques for optimizing ProGuard configuration rules to reduce APK size. It outlines steps like removing duplicated and redundant rules, and using "-whyareyoukeeping" to analyze rules. This helps refine the configuration by only keeping necessary rules. The result was a 5.52% smaller APK size and 11.3% fewer methods. Care must be taken with libraries using reflection or dynamic naming. R8 is now the default compiler which handles ProGuard configs differently.
NO1 Top No1 Amil Baba In Azad Kashmir, Kashmir Black Magic Specialist Expert ...
[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size
1. Ansgar Lin - Android team of Oath: Yahoo TW
1
如何有效精簡ProGuard規則以達到
縮⼩小apk之⽬目的
2. 2
Foot note
iOS/Android Engineer App開發
Frontend Engineer 前端⼯工程師
Backend Engineer 後端⼯工程師
DevOps Engineer 系統維運⼯工程師
AI Engineer / Data Engineer AI⼯工程師
Product Designer 產品設計
Product Manager 產品管理理
Paranoid Software Engineer 資安⼯工程師
E-COMMERCE
電⼦子商務
MEDIA
媒體
DATA
⼤大數據
SEARCH
搜尋引擎
3. Effective ProGuard keep rules for smaller applications
(Google I/O ’18)
• https://www.youtube.com/watch?v=x9T5EYE-QWQ
3
Foot note
About the topic
4. • A most popular open source tool in the Android world.
• Shrink apk by removing unused code at run-time.
• Obfuscate code to provide minimal protections against reverse
engineering
• Add “-keep class * extends ClassA” into ProGuard configuration,
you can tell ProGuard don’t touch any subclass of ClassA
4
What is ProGuard?
Foot note
5. 5
What is ProGuard?
// In build.gradle
android {
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-project.txt'
}
}
}
6. 6
What is ProGuard?
• A most popular open source tool in the Android world.
• Shrink apk by removing unused code at run-time.
• Obfuscate code to provide minimal protections against reverse
engineering
• Add “-keep class * extends ClassA” into ProGuard configuration,
you can tell ProGuard don’t touch any subclass of ClassA
7. 7
What is ProGuard?
// In build.gradle
android {
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-project.txt'
}
}
}
28. 28
Foot note
• “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
29. 29
Foot note
• “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
30. 30
Foot note
• “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
31. 31
Foot note
• “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
32. • “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
32
Foot note
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
33. • “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
33
Foot note
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
34. • “-keep class com.example.Blur”
—> “-whyareyoukeeping class com.example.Blur”
34
Foot note
Refine ProGuard Configuration
com.example.Blur
is invoked by com.example.BlurView: doWorkA(int)
is invoked by com.example.BlurView: BlurView(android.content.Context)
is invoked by com.example.SelectActivity: onCreate(android.os.Bundle)
implements android.app.Activity: onCreate(android.os.Bundle)
is a library method.
35. 35
Foot note
• message from `-whyareyoukeeping`
• is a library class/method/field.
• is not been kept
• nothing
• is kept by a directive in the configuration.
Refine ProGuard Configuration
36. 36
Foot note
• message from `-whyareyoukeeping`
• is a library class/method/field.
• is not been kept
• nothing
• is kept by a directive in the configuration.
-keep class com.example.Blur
-whyareyoukeeping class com.example.Blur
Refine ProGuard Configuration
47. 47
What should be careful?
Foot note
• 3-rd Library implements with reflection.
• Glide: initialization
• Parsing data with field names
• Gson + Retrofit: JSON model
• Anything implementation with static name.
48. 48
What should be careful?
Foot note
• 3-rd Library implements with reflection.
• Glide: initialization
• Parsing data with field names
• Gson + Retrofit: JSON model
• Anything implementation with static name.
49. 49
Foot note
W/ProGuard: The class 'com.example.SampleActivity' is calling Class.forName to retrieve
the class 'com.exmaple.NoneExistClass', but the latter could not be found.
It may have been obfuscated or shrunk.
You should consider preserving the class with its original name,
with a setting like:
-keep class com.exmaple.NoneExistClass
W/System.err: java.lang.ClassNotFoundException: com.exmaple.NoneExistClass
at java.lang.Class.classForName(Native Method)
• Add “-addconfigurationdebugging”
What should be careful?
50. 50
Foot note
W/ProGuard: The class 'com.example.SampleActivity' is calling Class.forName to retrieve
the class 'com.exmaple.NoneExistClass', but the latter could not be found.
It may have been obfuscated or shrunk.
You should consider preserving the class with its original name,
with a setting like:
-keep class com.exmaple.NoneExistClass
W/System.err: java.lang.ClassNotFoundException: com.exmaple.NoneExistClass
at java.lang.Class.classForName(Native Method)
• Add “-addconfigurationdebugging”
What should be careful?
51. 51
Foot note
W/ProGuard: The class 'com.example.SampleActivity' is calling Class.forName to retrieve
the class 'com.exmaple.NoneExistClass', but the latter could not be found.
It may have been obfuscated or shrunk.
You should consider preserving the class with its original name,
with a setting like:
-keep class com.exmaple.NoneExistClass
W/System.err: java.lang.ClassNotFoundException: com.exmaple.NoneExistClass
at java.lang.Class.classForName(Native Method)
• Add “-addconfigurationdebugging”
Only use in debug version
What should be careful?
52. 52
Foot note
• ClassNotFoundException
• NoSuchFieldException
• NoSuchMethodException
• RuntimeException
• UnsatisfiedLinkError
• IOException
• Add “-addconfigurationdebugging”
What should be careful?
53. 53
Foot note
W/ProGuard: The class 'com.example.SampleActivity' is calling Class.forName to retrieve
the class 'com.exmaple.NoneExistClass', but the latter could not be found.
It may have been obfuscated or shrunk.
You should consider preserving the class with its original name,
with a setting like:
-keep class com.exmaple.NoneExistClass
W/System.err: java.lang.ClassNotFoundException: com.exmaple.NoneExistClass
at java.lang.Class.classForName(Native Method)
• Add “-addconfigurationdebugging”
What should be careful?
55. 55
R8
Foot note
• Powered by Google
• Default enable after Android Studio(3.3)
• Java bytecode(.class) —> Dalvik bytecode(.dex)
• ProGuard configuration is acceptable.
• Changes:
• “-addconfigurationdebugging” will be ignored by default.
• Error detection while compiling.