Skip to content

Commit 7fadd33

Browse files
authored
SES-1971 : Enable minification (#1566)
* Initial proguard and minify * Initial proguard rules, App doesnt crash on start * Conversation and emoji * Some JNI rules * cleanup * Kryo proguard * Cleanup * more rules * added to proguard * added rules to proguard * proguard file cleanup * gradle and proguard cleanup * Cleanup * Gradle cleanup * Huawei warnings * Compile only for huawei * HMS analytics * Fix build error * Updated rules * Added rules, cleanups * Removed misplaced flag * Some rules cleanup * gradle update
1 parent 2d1d4ad commit 7fadd33

File tree

3 files changed

+227
-3
lines changed

3 files changed

+227
-3
lines changed

app/build.gradle.kts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,12 @@ android {
151151

152152
buildTypes {
153153
getByName("release") {
154-
isMinifyEnabled = false
155-
154+
isMinifyEnabled = true
155+
isShrinkResources = true
156+
proguardFiles(
157+
getDefaultProguardFile("proguard-android-optimize.txt"),
158+
file("proguard-rules.pro")
159+
)
156160
devNetDefaultOn(false)
157161
enablePermissiveNetworkSecurityConfig(false)
158162
setAlternativeAppName(null)
@@ -188,7 +192,6 @@ android {
188192

189193
getByName("debug") {
190194
isDefault = true
191-
isMinifyEnabled = false
192195
enableUnitTestCoverage = false
193196
signingConfig = signingConfigs.getByName("debug")
194197

@@ -373,6 +376,11 @@ dependencies {
373376
if (huaweiEnabled) {
374377
val huaweiImplementation = configurations.maybeCreate("huaweiImplementation")
375378
huaweiImplementation(libs.huawei.push)
379+
380+
// These are compileOnly on the Huawei flavor so R8 can resolve optional HMS classes
381+
// referenced by HMS Push during minification.
382+
compileOnly(libs.huawei.hianalytics)
383+
compileOnly(libs.huawei.availableupdate)
376384
}
377385

378386
implementation(libs.androidx.media3.exoplayer)

app/proguard-rules.pro

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
########## BASELINE / ATTRIBUTES ##########
2+
# Core attrs (serialization/DI/reflective access often rely on these)
3+
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record
4+
5+
# Honor @Keep if present
6+
-keep @androidx.annotation.Keep class * { *; }
7+
-keepclasseswithmembers class * { @androidx.annotation.Keep *; }
8+
9+
########## OPTIONAL GOOGLE BITS (SUPPRESSED WARNINGS) ##########
10+
-dontwarn com.google.android.gms.common.annotation.**
11+
-dontwarn com.google.firebase.analytics.connector.**
12+
13+
########## ANDROID / DI ##########
14+
# Workers constructed by class name
15+
-keep class ** extends androidx.work.ListenableWorker
16+
17+
########## KOTLINX SERIALIZATION ##########
18+
-keepclassmembers class ** {
19+
@kotlinx.serialization.Serializable *;
20+
*** Companion;
21+
kotlinx.serialization.KSerializer serializer(...);
22+
}
23+
24+
########## JACKSON (CORE + ANNOTATIONS + DTOs) ##########
25+
# Keep Jackson packages and common annotated members
26+
-keep class com.fasterxml.jackson.** { *; }
27+
-keepclassmembers class ** {
28+
@com.fasterxml.jackson.annotation.JsonCreator <init>(...);
29+
@com.fasterxml.jackson.annotation.JsonProperty *;
30+
}
31+
32+
-keep class ** extends com.fasterxml.jackson.core.type.TypeReference { *; }
33+
-keep class * implements com.fasterxml.jackson.databind.util.Converter { public <init>(); public *; }
34+
-keep class * extends com.fasterxml.jackson.databind.JsonDeserializer { public <init>(); public *; }
35+
36+
-dontwarn com.fasterxml.jackson.databind.**
37+
38+
# Jackson DTO used by OpenGroupApi (reactions map values)
39+
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction { *; }
40+
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction
41+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction {
42+
<fields>;
43+
*** get*();
44+
void set*(***);
45+
46+
# keep the default constructor too:
47+
public <init>(***, int, kotlin.jvm.internal.DefaultConstructorMarker);
48+
# and a bare no-arg constructor if it exists
49+
public <init>();
50+
}
51+
52+
# DTO used by OpenGroupApi
53+
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { *; }
54+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { <init>(); }
55+
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities
56+
57+
# Project models referenced via Jackson (from crashes)
58+
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper$SealedData { *; }
59+
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper$SealedData$* { *; }
60+
-keep class org.thoughtcrime.securesms.crypto.AttachmentSecret { *; }
61+
-keep class org.thoughtcrime.securesms.crypto.AttachmentSecret$* { *; }
62+
63+
# Keep names + bean-style accessors for OpenGroupApi models
64+
-keepnames class org.session.libsession.messaging.open_groups.**
65+
-keepclassmembers class org.session.libsession.messaging.open_groups.** {
66+
<fields>;
67+
*** get*();
68+
void set*(***);
69+
}
70+
71+
# Keep names + bean-style accessors for snode models
72+
-keepnames class org.session.libsession.snode.**
73+
-keepclassmembers class org.session.libsession.snode.** {
74+
<fields>;
75+
*** get*();
76+
void set*(***);
77+
}
78+
79+
# Converters / Deserializers
80+
-keep class org.session.libsession.snode.model.RetrieveMessageConverter { public <init>(); public *; }
81+
82+
########## JNI LOGGER / NATIVE ENTRYPOINTS ##########
83+
# Logging interface & implementations (JNI looks up log(String,String,int))
84+
-keep interface network.loki.messenger.libsession_util.util.Logger { *; }
85+
-keepnames class * implements network.loki.messenger.libsession_util.util.Logger
86+
-keepclassmembers class * implements network.loki.messenger.libsession_util.util.Logger {
87+
public void log(java.lang.String, java.lang.String, int);
88+
}
89+
90+
# JNI: ConfigPush constructors (exact signatures preserved)
91+
-keepnames class network.loki.messenger.libsession_util.util.ConfigPush
92+
-keepclassmembers class network.loki.messenger.libsession_util.util.ConfigPush {
93+
public <init>(java.util.List, long, java.util.List);
94+
public <init>(java.util.List, long, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker);
95+
}
96+
97+
# JNI: specific getter used from native
98+
-keepnames class network.loki.messenger.libsession_util.util.UserPic
99+
-keepclassmembers class network.loki.messenger.libsession_util.util.UserPic {
100+
public byte[] getKeyAsByteArray();
101+
}
102+
103+
-keep class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo { *; }
104+
-keepnames class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo
105+
-keepclassmembers class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo {
106+
public byte[] getAdminKeyAsByteArray();
107+
public byte[] getAuthDataAsByteArray();
108+
}
109+
110+
########## WEBRTC / CHROMIUM JNI ##########
111+
# WebRTC public Java APIs (kept for JNI_OnLoad registration)
112+
-keep class org.webrtc.** { *; }
113+
114+
# Chromium-based bits
115+
-keep class org.chromium.base.** { *; }
116+
-keep class org.chromium.net.** { *; }
117+
118+
# Keep all native bridges everywhere
119+
-keepclasseswithmembers,includedescriptorclasses class * {
120+
native <methods>;
121+
}
122+
123+
########## WEBRTC / CHROMIUM jni_zero ##########
124+
# Ensure jni_zero Java side is discoverable by native
125+
-keep class org.jni_zero.** { *; }
126+
-keepnames class org.jni_zero.**
127+
128+
########## CONVERSATION / MODELS (JNI + REFLECTION) ##########
129+
# Conversation.* types constructed via JNI with (String,long,boolean)
130+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$* {
131+
public <init>(java.lang.String, long, boolean);
132+
}
133+
134+
# Keep names and members of Conversation/Community models (JNI searches by name)
135+
-keep class network.loki.messenger.libsession_util.util.Conversation$Community { *; }
136+
-keep class network.loki.messenger.libsession_util.util.Conversation$OneToOne { *; }
137+
-keep class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { *; }
138+
-keep class network.loki.messenger.libsession_util.util.BaseCommunityInfo { *; }
139+
140+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$Community { public <init>(...); }
141+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { public <init>(...); }
142+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { public <init>(...); }
143+
144+
-keepnames class network.loki.messenger.libsession_util.util.Conversation$Community
145+
-keepnames class network.loki.messenger.libsession_util.util.Conversation$OneToOne
146+
-keepnames class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup
147+
-keepnames class network.loki.messenger.libsession_util.util.BaseCommunityInfo
148+
149+
# Group members (JNI constructor with long)
150+
-keep class network.loki.messenger.libsession_util.GroupMembersConfig { *; }
151+
-keep class network.loki.messenger.libsession_util.util.GroupMember { *; }
152+
-keepclassmembers class network.loki.messenger.libsession_util.util.GroupMember { public <init>(long); }
153+
-keepnames class network.loki.messenger.libsession_util.util.GroupMember
154+
155+
# Broad safety net for long-arg ctors in util package
156+
-keepclassmembers class network.loki.messenger.libsession_util.util.** { public <init>(long); }
157+
158+
########## EMOJI SEARCH (JACKSON / POLYMORPHIC) ##########
159+
# Keep names if @JsonTypeInfo uses CLASS/MINIMAL_CLASS
160+
-keepnames class org.thoughtcrime.securesms.database.model.**
161+
# Preserve abstract base + nested types for property/creator names
162+
-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; }
163+
-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; }
164+
165+
########## KRYO (SERIALIZATION OF DESTINATIONS) ##########
166+
# No-arg contructors required at runtime for these sealed subclasses
167+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { <init>(); }
168+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { <init>(); }
169+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { <init>(); }
170+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { <init>(); }
171+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { <init>(); }
172+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { <init>(); }
173+
174+
# Keep the Enum serializer contructor Kryo reflects on
175+
-keepclassmembers class com.esotericsoftware.kryo.serializers.** {
176+
public <init>(...);
177+
}
178+
179+
# Prevent enum unboxing/renaming for the enum field being serialized
180+
-keep class org.session.libsession.messaging.messages.control.TypingIndicator$Kind { *; }
181+
182+
# Preserve class names for Kryo
183+
-keepnames class org.session.libsession.messaging.messages.Destination$**
184+
185+
########## OPEN GROUP API (MESSAGES) ##########
186+
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { *; }
187+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { <init>(); }
188+
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Message
189+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message {
190+
*** get*();
191+
void set*(***);
192+
}
193+
194+
-keep class org.session.libsession.messaging.utilities.UpdateMessageData { *; }
195+
-keep class org.session.libsession.messaging.utilities.UpdateMessageData$* { *; }
196+
-keepnames class org.session.libsession.messaging.utilities.UpdateMessageData$*
197+
198+
########## HUAWEI / HMS (minified builds) ##########
199+
# Device-only classes referenced by HMS internals — not present on Maven.
200+
-dontwarn android.telephony.HwTelephonyManager
201+
-dontwarn com.huawei.android.os.BuildEx$VERSION
202+
-dontwarn com.huawei.libcore.io.**
203+
-dontwarn com.huawei.hianalytics.**
204+
-dontwarn com.huawei.hms.availableupdate.**
205+
206+
# Misc suppressed warnings
207+
-dontwarn java.beans.BeanInfo
208+
-dontwarn java.beans.IntrospectionException
209+
-dontwarn java.beans.Introspector
210+
-dontwarn java.beans.PropertyDescriptor
211+
-dontwarn java.lang.management.ManagementFactory
212+
-dontwarn java.lang.management.RuntimeMXBean
213+
-dontwarn sun.nio.ch.DirectBuffer

gradle/libs.versions.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ uiTestJunit4Version = "1.10.1"
6767
workRuntimeKtxVersion = "2.11.0"
6868
zxingVersion = "3.5.4"
6969
huaweiPushVersion = "6.13.0.300"
70+
huaweiAnalyticsVersion = "6.12.0.301"
7071
googlePlayReviewVersion = "2.0.2"
7172
coilVersion = "3.3.0"
7273
billingVersion = "8.3.0"
@@ -161,6 +162,8 @@ subsampling-scale-image-view = { module = "com.davemorrissey.labs:subsampling-sc
161162
truth = { module = "com.google.truth:truth", version.ref = "truthVersion" }
162163
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbineVersion" }
163164
huawei-push = { module = 'com.huawei.hms:push', version.ref = 'huaweiPushVersion' }
165+
huawei-hianalytics = { module = "com.huawei.hms:hianalytics", version.ref = "huaweiAnalyticsVersion" }
166+
huawei-availableupdate = { module = "com.huawei.hms:availableupdate", version.ref = "huaweiPushVersion" }
164167
google-play-review = { module = "com.google.android.play:review", version.ref = "googlePlayReviewVersion" }
165168
google-play-review-ktx = { module = "com.google.android.play:review-ktx", version.ref = "googlePlayReviewVersion" }
166169
sqlite-web-viewer = { module = "io.github.simophin:sqlite-web-viewer", version = "0.0.3" }

0 commit comments

Comments
 (0)