From 8822a8639ea48a17bd305da3726eff6485a26a07 Mon Sep 17 00:00:00 2001 From: jbsession Date: Wed, 17 Sep 2025 09:51:04 +0800 Subject: [PATCH 01/14] Initial proguard and minify --- app/build.gradle.kts | 8 ++++++-- content-descriptions/proguard-rules.pro | 13 ++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a8cb12013f..df17b5ed18 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -161,12 +161,16 @@ android { buildTypes { getByName("release") { - isMinifyEnabled = false - + isMinifyEnabled = true devNetDefaultOn(false) enablePermissiveNetworkSecurityConfig(false) setAlternativeAppName(null) setAuthorityPostfix("") + + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + file("proguard-rules.pro") + ) } create("qa") { diff --git a/content-descriptions/proguard-rules.pro b/content-descriptions/proguard-rules.pro index 481bb43481..befc27205f 100644 --- a/content-descriptions/proguard-rules.pro +++ b/content-descriptions/proguard-rules.pro @@ -18,4 +18,15 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +#Start rules + +### General: keep annotation/param/meta info that serializers and DI sometimes need +-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record + +### Honor @Keep (used in MessageId.kt) +-keep @androidx.annotation.Keep class * { *; } +-keepclasseswithmembers class * { @androidx.annotation.Keep *; } + +-include build/outputs/mapping/playDebug/missing_rules.txt \ No newline at end of file From 2d9228f0519e8661b1fbac7f1cee925c685200b8 Mon Sep 17 00:00:00 2001 From: jbsession Date: Wed, 17 Sep 2025 16:02:26 +0800 Subject: [PATCH 02/14] Initial proguard rules, App doesnt crash on start --- app/build.gradle.kts | 18 ++++--- app/proguard-rules.pro | 70 +++++++++++++++++++++++++ content-descriptions/proguard-rules.pro | 13 +---- 3 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 app/proguard-rules.pro diff --git a/app/build.gradle.kts b/app/build.gradle.kts index df17b5ed18..caff5a9b40 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -162,15 +162,15 @@ android { buildTypes { getByName("release") { isMinifyEnabled = true - devNetDefaultOn(false) - enablePermissiveNetworkSecurityConfig(false) - setAlternativeAppName(null) - setAuthorityPostfix("") - + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), file("proguard-rules.pro") ) + devNetDefaultOn(false) + enablePermissiveNetworkSecurityConfig(false) + setAlternativeAppName(null) + setAuthorityPostfix("") } create("qa") { @@ -197,7 +197,13 @@ android { getByName("debug") { isDefault = true - isMinifyEnabled = false +// isMinifyEnabled = false + isMinifyEnabled = true + isShrinkResources = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + file("proguard-rules.pro") + ) enableUnitTestCoverage = false signingConfig = signingConfigs.getByName("debug") diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000000..706433a2a1 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,70 @@ +########## BASELINE ########## +-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record + +# Honor @Keep if present +-keep @androidx.annotation.Keep class * { *; } +-keepclasseswithmembers class * { @androidx.annotation.Keep *; } + +# Optional Google bits you excluded +-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 ########## +-keep class kotlinx.serialization.** { *; } +-keepclassmembers class ** { + @kotlinx.serialization.Serializable *; + *** Companion; + kotlinx.serialization.KSerializer serializer(...); +} + +########## JACKSON ########## +-keep class com.fasterxml.jackson.** { *; } +-keepclassmembers class ** { + @com.fasterxml.jackson.annotation.JsonCreator (...); + @com.fasterxml.jackson.annotation.JsonProperty *; +} +-dontwarn com.fasterxml.jackson.databind.** + +# Project models used via Jackson (from your 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$* { *; } + +########## JNI LOGGER ########## +# Keep the interface + all implementors (incl. anonymous/lambdas) and the exact method JNI looks up +-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); +} + +########## WEBRTC / CHROMIUM JNI ########## +# Keep WebRTC Java APIs fully to satisfy JNI_OnLoad registration +-keep class org.webrtc.** { *; } + +# Some builds ship Chromium base helpers; harmless if absent +-keep class org.chromium.** { *; } +-keep class org.chromium.base.** { *; } +-keep class org.chromium.net.** { *; } +-keep class org.chromium.media.** { *; } + +# Keep all JNI bridges everywhere (prevents stripping/renaming of native methods) +-keepclasseswithmembers,includedescriptorclasses class * { + native ; +} + +########## WebRTC/Chromium jni_zero ########## +# Keep the jni_zero Java side so JNI_OnLoad can FindClass it. +-keep class org.jni_zero.** { *; } +-keepnames class org.jni_zero.** + +########## (OPTIONAL) easier stack traces while iterating ########## +# -keepattributes SourceFile,LineNumberTable +# This is generated automatically by the Android Gradle plugin. +-dontwarn java.lang.management.ManagementFactory +-dontwarn java.lang.management.RuntimeMXBean \ No newline at end of file diff --git a/content-descriptions/proguard-rules.pro b/content-descriptions/proguard-rules.pro index befc27205f..481bb43481 100644 --- a/content-descriptions/proguard-rules.pro +++ b/content-descriptions/proguard-rules.pro @@ -18,15 +18,4 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile - -#Start rules - -### General: keep annotation/param/meta info that serializers and DI sometimes need --keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record - -### Honor @Keep (used in MessageId.kt) --keep @androidx.annotation.Keep class * { *; } --keepclasseswithmembers class * { @androidx.annotation.Keep *; } - --include build/outputs/mapping/playDebug/missing_rules.txt \ No newline at end of file +#-renamesourcefileattribute SourceFile \ No newline at end of file From 7b754100daa7af17f1cb661a2f5b6c99242eaa47 Mon Sep 17 00:00:00 2001 From: jbsession Date: Wed, 17 Sep 2025 16:36:11 +0800 Subject: [PATCH 03/14] Conversation and emoji --- app/proguard-rules.pro | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 706433a2a1..1ee2939057 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -63,6 +63,24 @@ -keep class org.jni_zero.** { *; } -keepnames class org.jni_zero.** +# Conversation.* inner types constructed reflectively/JNI: +# keep the (String, long, boolean) ctor so GetMethodID/newInstance can find it +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { + public (java.lang.String, long, boolean); +} +# if other Conversation nested types do the same, cover them too: +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$* { + public (java.lang.String, long, boolean); +} + +# --- Emoji search (Jackson polymorphic) --- +# If @JsonTypeInfo uses CLASS or MINIMAL_CLASS, keep class NAMES for the model package. +-keepnames class org.thoughtcrime.securesms.database.model.** + +# Keep the abstract base + its nested types and members so property/creator names stay intact. +-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; } +-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; } + ########## (OPTIONAL) easier stack traces while iterating ########## # -keepattributes SourceFile,LineNumberTable # This is generated automatically by the Android Gradle plugin. From 471c9f39c9829639a11d04037f3d0581fa6051f2 Mon Sep 17 00:00:00 2001 From: jbsession Date: Thu, 18 Sep 2025 14:21:04 +0800 Subject: [PATCH 04/14] Some JNI rules --- app/proguard-rules.pro | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 1ee2939057..7905131e49 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -58,6 +58,22 @@ native ; } +# JNI: Config push constructor(s) must stay exactly as-is +-keepnames class network.loki.messenger.libsession_util.util.ConfigPush + +-keepclassmembers class network.loki.messenger.libsession_util.util.ConfigPush { + # The one JNI is calling: + public (java.util.List, long, java.util.List); + # Keep the Kotlin default-params ctor too (harmless if absent): + public (java.util.List, long, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker); +} + +# JNI: preserve the exact 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(); +} + ########## WebRTC/Chromium jni_zero ########## # Keep the jni_zero Java side so JNI_OnLoad can FindClass it. -keep class org.jni_zero.** { *; } From 875d5b88e310fea19ae61bd785dc7fd9223eac25 Mon Sep 17 00:00:00 2001 From: jbsession Date: Thu, 18 Sep 2025 15:08:54 +0800 Subject: [PATCH 05/14] cleanup --- app/proguard-rules.pro | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 7905131e49..6f18b4342e 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -89,7 +89,7 @@ public (java.lang.String, long, boolean); } -# --- Emoji search (Jackson polymorphic) --- +# Emoji search (Jackson polymorphic) # If @JsonTypeInfo uses CLASS or MINIMAL_CLASS, keep class NAMES for the model package. -keepnames class org.thoughtcrime.securesms.database.model.** @@ -101,4 +101,9 @@ # -keepattributes SourceFile,LineNumberTable # This is generated automatically by the Android Gradle plugin. -dontwarn java.lang.management.ManagementFactory --dontwarn java.lang.management.RuntimeMXBean \ No newline at end of file +-dontwarn java.lang.management.RuntimeMXBean +-dontwarn java.beans.BeanInfo +-dontwarn java.beans.IntrospectionException +-dontwarn java.beans.Introspector +-dontwarn java.beans.PropertyDescriptor +-dontwarn sun.nio.ch.DirectBuffer \ No newline at end of file From 9db631447234f1c8f65082d54af8001bf7192dec Mon Sep 17 00:00:00 2001 From: jbsession Date: Thu, 18 Sep 2025 15:58:09 +0800 Subject: [PATCH 06/14] Kryo proguard --- app/proguard-rules.pro | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 6f18b4342e..a12a55444c 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -97,6 +97,17 @@ -keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; } -keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; } +# Kryo needs real no-arg ctors at runtime +-keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { (); } + +# Optional: preserve class names so Kryo’s writeClassAndObject stays stable across app updates +-keepnames class org.session.libsession.messaging.messages.Destination$** + ########## (OPTIONAL) easier stack traces while iterating ########## # -keepattributes SourceFile,LineNumberTable # This is generated automatically by the Android Gradle plugin. From 67558c5b3701b3a54eaa86eb2c5cdbc40a6fde81 Mon Sep 17 00:00:00 2001 From: jbsession Date: Thu, 18 Sep 2025 15:59:56 +0800 Subject: [PATCH 07/14] Cleanup --- app/proguard-rules.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index a12a55444c..18dcac199e 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -97,7 +97,7 @@ -keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; } -keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; } -# Kryo needs real no-arg ctors at runtime +# Kryo needs real no-arg constructors at runtime -keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { (); } From 3ea2a85a471499cb933229f630dca34308606350 Mon Sep 17 00:00:00 2001 From: jbsession Date: Fri, 19 Sep 2025 08:48:01 +0800 Subject: [PATCH 08/14] more rules --- app/proguard-rules.pro | 66 ++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 18dcac199e..3d9339021f 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -8,6 +8,7 @@ # Optional Google bits you excluded -dontwarn com.google.android.gms.common.annotation.** -dontwarn com.google.firebase.analytics.connector.** +-dontwarn com.google.firebase.analytics.connector.** ########## ANDROID / DI ########## # Workers constructed by class name @@ -29,12 +30,38 @@ } -dontwarn com.fasterxml.jackson.databind.** +# Jackson DTO used by OpenGroupApi +-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { *; } +-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { (); } +-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities + # Project models used via Jackson (from your 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$* { *; } +-keepnames class org.session.libsession.messaging.open_groups.** +-keepclassmembers class org.session.libsession.messaging.open_groups.** { + ; + *** get*(); + void set*(***); +} + +-keepnames class org.session.libsession.snode.** +-keepclassmembers class org.session.libsession.snode.** { + ; + *** get*(); + void set*(***); +} + +-keepattributes Signature,InnerClasses,EnclosingMethod +-keep class ** extends com.fasterxml.jackson.core.type.TypeReference { *; } +-keepclassmembers class * { + @com.fasterxml.jackson.annotation.JsonCreator (...); + @com.fasterxml.jackson.annotation.JsonProperty *; +} + ########## JNI LOGGER ########## # Keep the interface + all implementors (incl. anonymous/lambdas) and the exact method JNI looks up -keep interface network.loki.messenger.libsession_util.util.Logger { *; } @@ -43,21 +70,6 @@ public void log(java.lang.String, java.lang.String, int); } -########## WEBRTC / CHROMIUM JNI ########## -# Keep WebRTC Java APIs fully to satisfy JNI_OnLoad registration --keep class org.webrtc.** { *; } - -# Some builds ship Chromium base helpers; harmless if absent --keep class org.chromium.** { *; } --keep class org.chromium.base.** { *; } --keep class org.chromium.net.** { *; } --keep class org.chromium.media.** { *; } - -# Keep all JNI bridges everywhere (prevents stripping/renaming of native methods) --keepclasseswithmembers,includedescriptorclasses class * { - native ; -} - # JNI: Config push constructor(s) must stay exactly as-is -keepnames class network.loki.messenger.libsession_util.util.ConfigPush @@ -74,6 +86,22 @@ public byte[] getKeyAsByteArray(); } + +########## WEBRTC / CHROMIUM JNI ########## +# Keep WebRTC Java APIs fully to satisfy JNI_OnLoad registration +-keep class org.webrtc.** { *; } + +# Some builds ship Chromium base helpers; harmless if absent +-keep class org.chromium.** { *; } +-keep class org.chromium.base.** { *; } +-keep class org.chromium.net.** { *; } +-keep class org.chromium.media.** { *; } + +# Keep all JNI bridges everywhere (prevents stripping/renaming of native methods) +-keepclasseswithmembers,includedescriptorclasses class * { + native ; +} + ########## WebRTC/Chromium jni_zero ########## # Keep the jni_zero Java side so JNI_OnLoad can FindClass it. -keep class org.jni_zero.** { *; } @@ -108,6 +136,14 @@ # Optional: preserve class names so Kryo’s writeClassAndObject stays stable across app updates -keepnames class org.session.libsession.messaging.messages.Destination$** +-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { *; } +-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { (); } +-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Message +-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { + *** get*(); + void set*(***); +} + ########## (OPTIONAL) easier stack traces while iterating ########## # -keepattributes SourceFile,LineNumberTable # This is generated automatically by the Android Gradle plugin. From ebcfcc00b601fac6f9937be4638475f5f54658f3 Mon Sep 17 00:00:00 2001 From: jbsession Date: Mon, 29 Sep 2025 09:25:30 +0800 Subject: [PATCH 09/14] added to proguard --- app/proguard-rules.pro | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 3d9339021f..e87f038ea4 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -133,6 +133,29 @@ -keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { (); } +# Keep the Conversation model types used by JNI +-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 { *; } + +# Ensure all constructors (including @JvmOverloads-generated) stay public & unstripped +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$Community { + public (...); +} +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { + public (...); +} +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { + public (...); +} + +# Don’t rename these (JNI searches by name) +-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 + # Optional: preserve class names so Kryo’s writeClassAndObject stays stable across app updates -keepnames class org.session.libsession.messaging.messages.Destination$** From 5f8bc03a0760a40d2b57b174735483de69e0313f Mon Sep 17 00:00:00 2001 From: jbsession Date: Mon, 29 Sep 2025 17:53:26 +0800 Subject: [PATCH 10/14] added rules to proguard --- app/proguard-rules.pro | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e87f038ea4..249c0827ef 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -62,6 +62,10 @@ @com.fasterxml.jackson.annotation.JsonProperty *; } +-keep class org.session.libsession.snode.model.RetrieveMessageConverter { public (); public *; } +-keep class * implements com.fasterxml.jackson.databind.util.Converter { public (); public *; } +-keep class * extends com.fasterxml.jackson.databind.JsonDeserializer { public (); public *; } + ########## JNI LOGGER ########## # Keep the interface + all implementors (incl. anonymous/lambdas) and the exact method JNI looks up -keep interface network.loki.messenger.libsession_util.util.Logger { *; } @@ -156,6 +160,13 @@ -keepnames class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup -keepnames class network.loki.messenger.libsession_util.util.BaseCommunityInfo +-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 (long); } +-keepnames class network.loki.messenger.libsession_util.util.GroupMember + +-keepclassmembers class network.loki.messenger.libsession_util.util.** { public (long); } + # Optional: preserve class names so Kryo’s writeClassAndObject stays stable across app updates -keepnames class org.session.libsession.messaging.messages.Destination$** From 4e5cff3b95632ab081a2290fa5e52d8d669eef00 Mon Sep 17 00:00:00 2001 From: jbsession Date: Tue, 30 Sep 2025 14:25:44 +0800 Subject: [PATCH 11/14] proguard file cleanup --- app/proguard-rules.pro | 109 ++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 249c0827ef..ceb4cb3d05 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,11 +1,15 @@ -########## BASELINE ########## +########## BASELINE / ATTRIBUTES ########## +# Core attrs (serialization/DI/reflective access often rely on these) -keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record +# Some tools repeat/override attribute keeps; keeping as provided +-keepattributes Signature,InnerClasses,EnclosingMethod # Honor @Keep if present -keep @androidx.annotation.Keep class * { *; } -keepclasseswithmembers class * { @androidx.annotation.Keep *; } -# Optional Google bits you excluded +########## OPTIONAL GOOGLE BITS (SUPPRESSED WARNINGS) ########## +# Kept verbatim (includes duplicate line as provided) -dontwarn com.google.android.gms.common.annotation.** -dontwarn com.google.firebase.analytics.connector.** -dontwarn com.google.firebase.analytics.connector.** @@ -22,7 +26,8 @@ kotlinx.serialization.KSerializer serializer(...); } -########## JACKSON ########## +########## JACKSON (CORE + ANNOTATIONS + DTOs) ########## +# Keep Jackson packages and common annotated members -keep class com.fasterxml.jackson.** { *; } -keepclassmembers class ** { @com.fasterxml.jackson.annotation.JsonCreator (...); @@ -30,17 +35,18 @@ } -dontwarn com.fasterxml.jackson.databind.** -# Jackson DTO used by OpenGroupApi +# DTO used by OpenGroupApi -keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { *; } -keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { (); } -keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities -# Project models used via Jackson (from your crashes) +# 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.** { ; @@ -48,6 +54,7 @@ void set*(***); } +# Keep names + bean-style accessors for snode models -keepnames class org.session.libsession.snode.** -keepclassmembers class org.session.libsession.snode.** { ; @@ -55,121 +62,112 @@ void set*(***); } --keepattributes Signature,InnerClasses,EnclosingMethod +# TypeReference subclasses and repeated Jackson-annotation keep (kept verbatim) -keep class ** extends com.fasterxml.jackson.core.type.TypeReference { *; } -keepclassmembers class * { @com.fasterxml.jackson.annotation.JsonCreator (...); @com.fasterxml.jackson.annotation.JsonProperty *; } +# Converters / Deserializers (Jackson constructs via reflection) -keep class org.session.libsession.snode.model.RetrieveMessageConverter { public (); public *; } -keep class * implements com.fasterxml.jackson.databind.util.Converter { public (); public *; } -keep class * extends com.fasterxml.jackson.databind.JsonDeserializer { public (); public *; } -########## JNI LOGGER ########## -# Keep the interface + all implementors (incl. anonymous/lambdas) and the exact method JNI looks up +########## 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: Config push constructor(s) must stay exactly as-is +# JNI: ConfigPush constructors (exact signatures preserved) -keepnames class network.loki.messenger.libsession_util.util.ConfigPush - -keepclassmembers class network.loki.messenger.libsession_util.util.ConfigPush { - # The one JNI is calling: public (java.util.List, long, java.util.List); - # Keep the Kotlin default-params ctor too (harmless if absent): public (java.util.List, long, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker); } -# JNI: preserve the exact getter used from native +# 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(); } - ########## WEBRTC / CHROMIUM JNI ########## -# Keep WebRTC Java APIs fully to satisfy JNI_OnLoad registration +# WebRTC public Java APIs (kept for JNI_OnLoad registration) -keep class org.webrtc.** { *; } -# Some builds ship Chromium base helpers; harmless if absent +# Chromium-based bits (harmless if absent, but kept as provided) -keep class org.chromium.** { *; } -keep class org.chromium.base.** { *; } -keep class org.chromium.net.** { *; } -keep class org.chromium.media.** { *; } -# Keep all JNI bridges everywhere (prevents stripping/renaming of native methods) +# Keep all native bridges everywhere -keepclasseswithmembers,includedescriptorclasses class * { native ; } -########## WebRTC/Chromium jni_zero ########## -# Keep the jni_zero Java side so JNI_OnLoad can FindClass it. +########## WEBRTC / CHROMIUM jni_zero ########## +# Ensure jni_zero Java side is discoverable by native -keep class org.jni_zero.** { *; } -keepnames class org.jni_zero.** -# Conversation.* inner types constructed reflectively/JNI: -# keep the (String, long, boolean) ctor so GetMethodID/newInstance can find it +########## CONVERSATION / MODELS (JNI + REFLECTION) ########## +# Conversation.* types constructed via JNI with (String,long,boolean) -keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { public (java.lang.String, long, boolean); } -# if other Conversation nested types do the same, cover them too: -keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$* { public (java.lang.String, long, boolean); } -# Emoji search (Jackson polymorphic) -# If @JsonTypeInfo uses CLASS or MINIMAL_CLASS, keep class NAMES for the model package. --keepnames class org.thoughtcrime.securesms.database.model.** - -# Keep the abstract base + its nested types and members so property/creator names stay intact. --keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; } --keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; } - -# Kryo needs real no-arg constructors at runtime --keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { (); } --keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { (); } --keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { (); } --keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { (); } --keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { (); } --keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { (); } - -# Keep the Conversation model types used by JNI +# 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 { *; } -# Ensure all constructors (including @JvmOverloads-generated) stay public & unstripped --keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$Community { - public (...); -} --keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { - public (...); -} --keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { - public (...); -} +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$Community { public (...); } +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { public (...); } +-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { public (...); } -# Don’t rename these (JNI searches by name) -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 (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 (long); } -# Optional: preserve class names so Kryo’s writeClassAndObject stays stable across app updates +########## 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 ctors required at runtime for these sealed subclasses +-keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { (); } +-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { (); } + +# Optional stability: preserve class names for Kryo (kept as provided) -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 { (); } -keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Message @@ -178,13 +176,14 @@ void set*(***); } -########## (OPTIONAL) easier stack traces while iterating ########## +########## (OPTIONAL) EASIER STACK TRACES WHILE ITERATING ########## # -keepattributes SourceFile,LineNumberTable -# This is generated automatically by the Android Gradle plugin. --dontwarn java.lang.management.ManagementFactory --dontwarn java.lang.management.RuntimeMXBean + +# Misc suppressed warnings left as provided -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 \ No newline at end of file From 8dd9ba8e557a8668688584e7bd9660feac572a87 Mon Sep 17 00:00:00 2001 From: jbsession Date: Tue, 30 Sep 2025 15:36:07 +0800 Subject: [PATCH 12/14] gradle and proguard cleanup --- app/build.gradle.kts | 3 +-- app/proguard-rules.pro | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index baa5f3f479..af73c54418 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -203,9 +203,8 @@ android { getByName("debug") { isDefault = true -// isMinifyEnabled = false isMinifyEnabled = true - isShrinkResources = false + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), file("proguard-rules.pro") diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index ceb4cb3d05..70ea18e754 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -35,6 +35,20 @@ } -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 { + ; + *** get*(); + void set*(***); + + # keep the default constructor too: + public (***, int, kotlin.jvm.internal.DefaultConstructorMarker); + # and a bare no-arg ctor if it exists + public (); +} + # DTO used by OpenGroupApi -keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { *; } -keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { (); } @@ -164,6 +178,14 @@ -keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { (); } +# Keep the Enum serializer ctor Kryo reflects on +-keepclassmembers class com.esotericsoftware.kryo.serializers.DefaultSerializers$EnumSerializer { + public (java.lang.Class); +} + +# Prevent enum unboxing/renaming for the enum field being serialized +-keep class org.session.libsession.messaging.messages.control.TypingIndicator$Kind { *; } + # Optional stability: preserve class names for Kryo (kept as provided) -keepnames class org.session.libsession.messaging.messages.Destination$** From 2a6471c0f3d217595150e90e874bed40098cd5b7 Mon Sep 17 00:00:00 2001 From: jbsession Date: Wed, 1 Oct 2025 08:20:33 +0800 Subject: [PATCH 13/14] Cleanup --- app/proguard-rules.pro | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 70ea18e754..92c282e3f2 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -9,10 +9,8 @@ -keepclasseswithmembers class * { @androidx.annotation.Keep *; } ########## OPTIONAL GOOGLE BITS (SUPPRESSED WARNINGS) ########## -# Kept verbatim (includes duplicate line as provided) -dontwarn com.google.android.gms.common.annotation.** -dontwarn com.google.firebase.analytics.connector.** --dontwarn com.google.firebase.analytics.connector.** ########## ANDROID / DI ########## # Workers constructed by class name @@ -45,7 +43,7 @@ # keep the default constructor too: public (***, int, kotlin.jvm.internal.DefaultConstructorMarker); - # and a bare no-arg ctor if it exists + # and a bare no-arg constructor if it exists public (); } @@ -76,14 +74,14 @@ void set*(***); } -# TypeReference subclasses and repeated Jackson-annotation keep (kept verbatim) +# TypeReference subclasses and repeated Jackson-annotation keep -keep class ** extends com.fasterxml.jackson.core.type.TypeReference { *; } -keepclassmembers class * { @com.fasterxml.jackson.annotation.JsonCreator (...); @com.fasterxml.jackson.annotation.JsonProperty *; } -# Converters / Deserializers (Jackson constructs via reflection) +# Converters / Deserializers -keep class org.session.libsession.snode.model.RetrieveMessageConverter { public (); public *; } -keep class * implements com.fasterxml.jackson.databind.util.Converter { public (); public *; } -keep class * extends com.fasterxml.jackson.databind.JsonDeserializer { public (); public *; } @@ -113,7 +111,7 @@ # WebRTC public Java APIs (kept for JNI_OnLoad registration) -keep class org.webrtc.** { *; } -# Chromium-based bits (harmless if absent, but kept as provided) +# Chromium-based bits -keep class org.chromium.** { *; } -keep class org.chromium.base.** { *; } -keep class org.chromium.net.** { *; } @@ -170,7 +168,7 @@ -keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; } ########## KRYO (SERIALIZATION OF DESTINATIONS) ########## -# No-arg ctors required at runtime for these sealed subclasses +# No-arg contructors required at runtime for these sealed subclasses -keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { (); } @@ -178,7 +176,7 @@ -keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { (); } -keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { (); } -# Keep the Enum serializer ctor Kryo reflects on +# Keep the Enum serializer contructor Kryo reflects on -keepclassmembers class com.esotericsoftware.kryo.serializers.DefaultSerializers$EnumSerializer { public (java.lang.Class); } @@ -186,7 +184,7 @@ # Prevent enum unboxing/renaming for the enum field being serialized -keep class org.session.libsession.messaging.messages.control.TypingIndicator$Kind { *; } -# Optional stability: preserve class names for Kryo (kept as provided) +# Preserve class names for Kryo -keepnames class org.session.libsession.messaging.messages.Destination$** ########## OPEN GROUP API (MESSAGES) ########## @@ -198,10 +196,7 @@ void set*(***); } -########## (OPTIONAL) EASIER STACK TRACES WHILE ITERATING ########## -# -keepattributes SourceFile,LineNumberTable - -# Misc suppressed warnings left as provided +# Misc suppressed warnings -dontwarn java.beans.BeanInfo -dontwarn java.beans.IntrospectionException -dontwarn java.beans.Introspector From ea12ef50281d69f688cb49955eec5f8e4eba6beb Mon Sep 17 00:00:00 2001 From: jbsession Date: Wed, 1 Oct 2025 08:29:11 +0800 Subject: [PATCH 14/14] Gradle cleanup --- app/build.gradle.kts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index af73c54418..188891da57 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -203,12 +203,7 @@ android { getByName("debug") { isDefault = true - isMinifyEnabled = true - isShrinkResources = true - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - file("proguard-rules.pro") - ) + isMinifyEnabled = false enableUnitTestCoverage = false signingConfig = signingConfigs.getByName("debug")