Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8822a86
Initial proguard and minify
jbsession Sep 17, 2025
2d9228f
Initial proguard rules, App doesnt crash on start
jbsession Sep 17, 2025
7b75410
Conversation and emoji
jbsession Sep 17, 2025
471c9f3
Some JNI rules
jbsession Sep 18, 2025
875d5b8
cleanup
jbsession Sep 18, 2025
4dfe66d
Merge remote-tracking branch 'upstream/dev' into improvements/enable-…
jbsession Sep 18, 2025
9db6314
Kryo proguard
jbsession Sep 18, 2025
67558c5
Cleanup
jbsession Sep 18, 2025
3ea2a85
more rules
jbsession Sep 19, 2025
977c40f
Merge branch 'dev' into improvements/enable-minify
jbsession Sep 29, 2025
ebcfcc0
added to proguard
jbsession Sep 29, 2025
5f8bc03
added rules to proguard
jbsession Sep 29, 2025
4e5cff3
proguard file cleanup
jbsession Sep 30, 2025
8dd9ba8
gradle and proguard cleanup
jbsession Sep 30, 2025
2a6471c
Cleanup
jbsession Oct 1, 2025
ea12ef5
Gradle cleanup
jbsession Oct 1, 2025
34842b6
Merge branch 'dev' into improvements/enable-minify
jbsession Oct 1, 2025
78c3ce0
Merge branch 'dev' into improvements/enable-minify
jbsession Nov 25, 2025
a28a2ee
Merge branch 'dev' into improvements/enable-minify
jbsession Nov 25, 2025
e2c4ce1
Huawei warnings
jbsession Nov 25, 2025
65eeb6d
Compile only for huawei
jbsession Nov 26, 2025
06dbe75
HMS analytics
jbsession Nov 26, 2025
ef173af
Fix build error
jbsession Nov 26, 2025
c852c23
Merge branch 'dev' into improvements/enable-minify
jbsession Nov 26, 2025
7ee98bb
Updated rules
jbsession Nov 28, 2025
6cf29c3
Added rules, cleanups
jbsession Nov 28, 2025
9f7d02d
Removed misplaced flag
jbsession Nov 30, 2025
85a6ac3
Merge branch 'dev' into improvements/enable-minify
jbsession Dec 5, 2025
d4d3ec2
Some rules cleanup
jbsession Dec 5, 2025
a800976
gradle update
jbsession Dec 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,12 @@ android {

buildTypes {
getByName("release") {
isMinifyEnabled = false

isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
file("proguard-rules.pro")
)
devNetDefaultOn(false)
enablePermissiveNetworkSecurityConfig(false)
setAlternativeAppName(null)
Expand Down Expand Up @@ -179,7 +183,6 @@ android {

getByName("debug") {
isDefault = true
isMinifyEnabled = false
enableUnitTestCoverage = false
signingConfig = signingConfigs.getByName("debug")

Expand Down Expand Up @@ -357,6 +360,11 @@ dependencies {
if (huaweiEnabled) {
val huaweiImplementation = configurations.maybeCreate("huaweiImplementation")
huaweiImplementation(libs.huawei.push)

// These are compileOnly on the Huawei flavor so R8 can resolve optional HMS classes
// referenced by HMS Push during minification.
compileOnly(libs.huawei.hianalytics)
compileOnly(libs.huawei.availableupdate)
}

implementation(libs.androidx.media3.exoplayer)
Expand Down
213 changes: 213 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
########## BASELINE / ATTRIBUTES ##########
# Core attrs (serialization/DI/reflective access often rely on these)
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record

# Honor @Keep if present
-keep @androidx.annotation.Keep class * { *; }
-keepclasseswithmembers class * { @androidx.annotation.Keep *; }

########## OPTIONAL GOOGLE BITS (SUPPRESSED WARNINGS) ##########
-dontwarn com.google.android.gms.common.annotation.**
-dontwarn com.google.firebase.analytics.connector.**

########## ANDROID / DI ##########
# Workers constructed by class name
-keep class ** extends androidx.work.ListenableWorker

########## KOTLINX SERIALIZATION ##########
-keepclassmembers class ** {
@kotlinx.serialization.Serializable *;
*** Companion;
kotlinx.serialization.KSerializer serializer(...);
}

########## JACKSON (CORE + ANNOTATIONS + DTOs) ##########
# Keep Jackson packages and common annotated members
-keep class com.fasterxml.jackson.** { *; }
-keepclassmembers class ** {
@com.fasterxml.jackson.annotation.JsonCreator <init>(...);
@com.fasterxml.jackson.annotation.JsonProperty *;
}

-keep class ** extends com.fasterxml.jackson.core.type.TypeReference { *; }
-keep class * implements com.fasterxml.jackson.databind.util.Converter { public <init>(); public *; }
-keep class * extends com.fasterxml.jackson.databind.JsonDeserializer { public <init>(); public *; }

-dontwarn com.fasterxml.jackson.databind.**

# Jackson DTO used by OpenGroupApi (reactions map values)
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction { *; }
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction {
<fields>;
*** get*();
void set*(***);

# keep the default constructor too:
public <init>(***, int, kotlin.jvm.internal.DefaultConstructorMarker);
# and a bare no-arg constructor if it exists
public <init>();
}

# DTO used by OpenGroupApi
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { *; }
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { <init>(); }
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities

# Project models referenced via Jackson (from crashes)
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper$SealedData { *; }
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper$SealedData$* { *; }
-keep class org.thoughtcrime.securesms.crypto.AttachmentSecret { *; }
-keep class org.thoughtcrime.securesms.crypto.AttachmentSecret$* { *; }

# Keep names + bean-style accessors for OpenGroupApi models
-keepnames class org.session.libsession.messaging.open_groups.**
-keepclassmembers class org.session.libsession.messaging.open_groups.** {
<fields>;
*** get*();
void set*(***);
}

# Keep names + bean-style accessors for snode models
-keepnames class org.session.libsession.snode.**
-keepclassmembers class org.session.libsession.snode.** {
<fields>;
*** get*();
void set*(***);
}

# Converters / Deserializers
-keep class org.session.libsession.snode.model.RetrieveMessageConverter { public <init>(); public *; }

########## JNI LOGGER / NATIVE ENTRYPOINTS ##########
# Logging interface & implementations (JNI looks up log(String,String,int))
-keep interface network.loki.messenger.libsession_util.util.Logger { *; }
-keepnames class * implements network.loki.messenger.libsession_util.util.Logger
-keepclassmembers class * implements network.loki.messenger.libsession_util.util.Logger {
public void log(java.lang.String, java.lang.String, int);
}

# JNI: ConfigPush constructors (exact signatures preserved)
-keepnames class network.loki.messenger.libsession_util.util.ConfigPush
-keepclassmembers class network.loki.messenger.libsession_util.util.ConfigPush {
public <init>(java.util.List, long, java.util.List);
public <init>(java.util.List, long, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker);
}

# JNI: specific getter used from native
-keepnames class network.loki.messenger.libsession_util.util.UserPic
-keepclassmembers class network.loki.messenger.libsession_util.util.UserPic {
public byte[] getKeyAsByteArray();
}

-keep class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo { *; }
-keepnames class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo
-keepclassmembers class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo {
public byte[] getAdminKeyAsByteArray();
public byte[] getAuthDataAsByteArray();
}

########## WEBRTC / CHROMIUM JNI ##########
# WebRTC public Java APIs (kept for JNI_OnLoad registration)
-keep class org.webrtc.** { *; }

# Chromium-based bits
-keep class org.chromium.base.** { *; }
-keep class org.chromium.net.** { *; }

# Keep all native bridges everywhere
-keepclasseswithmembers,includedescriptorclasses class * {
native <methods>;
}

########## WEBRTC / CHROMIUM jni_zero ##########
# Ensure jni_zero Java side is discoverable by native
-keep class org.jni_zero.** { *; }
-keepnames class org.jni_zero.**

########## CONVERSATION / MODELS (JNI + REFLECTION) ##########
# Conversation.* types constructed via JNI with (String,long,boolean)
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$* {
public <init>(java.lang.String, long, boolean);
}

# Keep names and members of Conversation/Community models (JNI searches by name)
-keep class network.loki.messenger.libsession_util.util.Conversation$Community { *; }
-keep class network.loki.messenger.libsession_util.util.Conversation$OneToOne { *; }
-keep class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { *; }
-keep class network.loki.messenger.libsession_util.util.BaseCommunityInfo { *; }

-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$Community { public <init>(...); }
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { public <init>(...); }
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { public <init>(...); }

-keepnames class network.loki.messenger.libsession_util.util.Conversation$Community
-keepnames class network.loki.messenger.libsession_util.util.Conversation$OneToOne
-keepnames class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup
-keepnames class network.loki.messenger.libsession_util.util.BaseCommunityInfo

# Group members (JNI constructor with long)
-keep class network.loki.messenger.libsession_util.GroupMembersConfig { *; }
-keep class network.loki.messenger.libsession_util.util.GroupMember { *; }
-keepclassmembers class network.loki.messenger.libsession_util.util.GroupMember { public <init>(long); }
-keepnames class network.loki.messenger.libsession_util.util.GroupMember

# Broad safety net for long-arg ctors in util package
-keepclassmembers class network.loki.messenger.libsession_util.util.** { public <init>(long); }

########## EMOJI SEARCH (JACKSON / POLYMORPHIC) ##########
# Keep names if @JsonTypeInfo uses CLASS/MINIMAL_CLASS
-keepnames class org.thoughtcrime.securesms.database.model.**
# Preserve abstract base + nested types for property/creator names
-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; }
-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; }

########## KRYO (SERIALIZATION OF DESTINATIONS) ##########
# No-arg contructors required at runtime for these sealed subclasses
-keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { <init>(); }
-keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { <init>(); }
-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { <init>(); }
-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { <init>(); }
-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { <init>(); }
-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { <init>(); }

# Keep the Enum serializer contructor Kryo reflects on
-keepclassmembers class com.esotericsoftware.kryo.serializers.** {
public <init>(...);
}

# Prevent enum unboxing/renaming for the enum field being serialized
-keep class org.session.libsession.messaging.messages.control.TypingIndicator$Kind { *; }

# Preserve class names for Kryo
-keepnames class org.session.libsession.messaging.messages.Destination$**

########## OPEN GROUP API (MESSAGES) ##########
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { *; }
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { <init>(); }
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Message
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message {
*** get*();
void set*(***);
}

-keep class org.session.libsession.messaging.utilities.UpdateMessageData { *; }
-keep class org.session.libsession.messaging.utilities.UpdateMessageData$* { *; }
-keepnames class org.session.libsession.messaging.utilities.UpdateMessageData$*

########## HUAWEI / HMS (minified builds) ##########
# Device-only classes referenced by HMS internals — not present on Maven.
-dontwarn android.telephony.HwTelephonyManager
-dontwarn com.huawei.android.os.BuildEx$VERSION
-dontwarn com.huawei.libcore.io.**
-dontwarn com.huawei.hianalytics.**
-dontwarn com.huawei.hms.availableupdate.**

# Misc suppressed warnings
-dontwarn java.beans.BeanInfo
-dontwarn java.beans.IntrospectionException
-dontwarn java.beans.Introspector
-dontwarn java.beans.PropertyDescriptor
-dontwarn java.lang.management.ManagementFactory
-dontwarn java.lang.management.RuntimeMXBean
-dontwarn sun.nio.ch.DirectBuffer
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ uiTestJunit4Version = "1.9.4"
workRuntimeKtxVersion = "2.11.0"
zxingVersion = "3.5.4"
huaweiPushVersion = "6.13.0.300"
huaweiAnalyticsVersion = "6.12.0.301"
googlePlayReviewVersion = "2.0.2"
coilVersion = "3.3.0"
billingVersion = "8.0.0"
Expand Down Expand Up @@ -165,6 +166,8 @@ subsampling-scale-image-view = { module = "com.davemorrissey.labs:subsampling-sc
truth = { module = "com.google.truth:truth", version.ref = "truthVersion" }
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbineVersion" }
huawei-push = { module = 'com.huawei.hms:push', version.ref = 'huaweiPushVersion' }
huawei-hianalytics = { module = "com.huawei.hms:hianalytics", version.ref = "huaweiAnalyticsVersion" }
huawei-availableupdate = { module = "com.huawei.hms:availableupdate", version.ref = "huaweiPushVersion" }
google-play-review = { module = "com.google.android.play:review", version.ref = "googlePlayReviewVersion" }
google-play-review-ktx = { module = "com.google.android.play:review-ktx", version.ref = "googlePlayReviewVersion" }
sqlite-web-viewer = { module = "io.github.simophin:sqlite-web-viewer", version = "0.0.3" }
Expand Down