From 571068517ed3d3f6c99eda44e598bfc52b7c7c58 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 14:59:50 +0200 Subject: [PATCH 1/7] chore: enable r8 minify on release --- app/build.gradle.kts | 4 ++-- app/proguard-rules.pro | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1866008f4a..1cbfa9cf8c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -247,8 +247,8 @@ android { } } release { - isMinifyEnabled = false - isShrinkResources = false + isMinifyEnabled = true + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index ae39109b65..91a9ac4d6d 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,6 +20,11 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +# JNI method names must match the native side. +-keepclasseswithmembernames,includedescriptorclasses class * { + native ; +} + # btleplug (droidplug) Android Bluetooth support # These classes are loaded via JNI from Rust code -keep class com.nonpolynomial.btleplug.** { *; } From e4b54fb8493c2a9ce7600fcecf1e47b34a970416 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 15:00:49 +0200 Subject: [PATCH 2/7] chore: use public annotation target flag --- app/build.gradle.kts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1cbfa9cf8c..19bac75a64 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -306,11 +306,7 @@ android { kotlin { compilerOptions { jvmTarget = JvmTarget.JVM_11 - freeCompilerArgs.addAll( - listOf( - "-XXLanguage:+PropertyParamAnnotationDefaultTargetMode", - ) - ) + freeCompilerArgs.add("-Xannotation-default-target=param-property") } } From 985e6bc6065244e39d4ec12560624e5793a70ab3 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 17:41:54 +0200 Subject: [PATCH 3/7] chore: use agp 9.3 r8 optimization dsl --- app/build.gradle.kts | 9 +++------ app/proguard-rules.pro | 12 +----------- app/src/main/keepRules/jni.keep | 31 +++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 app/src/main/keepRules/jni.keep diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 19bac75a64..08e205f9d6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -247,12 +247,9 @@ android { } } release { - isMinifyEnabled = true - isShrinkResources = true - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro", - ) + optimization { + enable = true + } signingConfig = signingConfigs.getByName("release") ndk { debugSymbolLevel = "FULL" diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 91a9ac4d6d..d6b8a6a5a0 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,14 +20,4 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile -# JNI method names must match the native side. --keepclasseswithmembernames,includedescriptorclasses class * { - native ; -} - -# btleplug (droidplug) Android Bluetooth support -# These classes are loaded via JNI from Rust code --keep class com.nonpolynomial.btleplug.** { *; } - -# jni-utils support library for btleplug --keep class io.github.gedgygedgy.rust.** { *; } +# App keep rules live in src/main/keepRules/*.keep (AGP 9.3 optimization DSL). diff --git a/app/src/main/keepRules/jni.keep b/app/src/main/keepRules/jni.keep new file mode 100644 index 0000000000..dcb4ca1381 --- /dev/null +++ b/app/src/main/keepRules/jni.keep @@ -0,0 +1,31 @@ +# btleplug (droidplug) JNI types constructed from native. Local AAR ships no consumer rules. +-keep class com.nonpolynomial.btleplug.android.impl.Adapter { + (...); + *; +} +-keep class com.nonpolynomial.btleplug.android.impl.Adapter$* { + (...); + *; +} +-keep class com.nonpolynomial.btleplug.android.impl.Peripheral { + (...); + *; +} +-keep class com.nonpolynomial.btleplug.android.impl.Peripheral$* { + (...); + *; +} +-keep class com.nonpolynomial.btleplug.android.impl.ScanFilter { + (...); + *; +} +-keep class com.nonpolynomial.btleplug.android.impl.*Exception { + (...); + *; +} + +# jni-utils JNI glue used by btleplug. Local JAR ships no consumer rules. +-keep class io.github.gedgygedgy.rust.** { + (...); + *; +} From 2a20df0775d8547ea2aaa5ff9350d22c52c30876 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 17:43:10 +0200 Subject: [PATCH 4/7] chore: add r8 minify changelog fragment --- changelog.d/next/r8.changed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/next/r8.changed.md diff --git a/changelog.d/next/r8.changed.md b/changelog.d/next/r8.changed.md new file mode 100644 index 0000000000..04b881da36 --- /dev/null +++ b/changelog.d/next/r8.changed.md @@ -0,0 +1 @@ +Release builds now shrink unused code and resources with R8. From 2248c62f3f69b783c4e90b9701b8f8e9c4ef52cf Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 17:43:28 +0200 Subject: [PATCH 5/7] chore: rename changelog fragment --- changelog.d/next/{r8.changed.md => 1184.changed.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/next/{r8.changed.md => 1184.changed.md} (100%) diff --git a/changelog.d/next/r8.changed.md b/changelog.d/next/1184.changed.md similarity index 100% rename from changelog.d/next/r8.changed.md rename to changelog.d/next/1184.changed.md From a041650d9d5a2d91e126c1c5e345f61b18b87ffd Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 20:06:35 +0200 Subject: [PATCH 6/7] chore: consume r8-compatible android artifacts --- gradle/libs.versions.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 41012a0489..aed0c3e6a2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,8 +21,8 @@ activity-compose = { module = "androidx.activity:activity-compose", version = "1 appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.1" } barcode-scanning = { module = "com.google.mlkit:barcode-scanning", version = "17.3.0" } biometric = { module = "androidx.biometric:biometric", version = "1.4.0-alpha05" } -bitkit-core = { module = "com.synonym:bitkit-core-android", version = "0.5.5" } -paykit = { module = "com.synonym:paykit-android", version = "0.1.0-rc43" } +bitkit-core = { module = "com.synonym:bitkit-core-android", version = "0.5.9" } +paykit = { module = "com.synonym:paykit-android", version = "0.1.0-rc47" } bouncycastle-provider-jdk = { module = "org.bouncycastle:bcprov-jdk18on", version = "1.83" } camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camera" } camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camera" } @@ -64,7 +64,7 @@ ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" } ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" } ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } -ldk-node-android = { module = "com.synonym:ldk-node-android", version = "0.7.0-rc.63" } +ldk-node-android = { module = "com.synonym:ldk-node-android", version = "0.7.0-rc.64" } lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycle" } lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" } lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" } @@ -89,7 +89,7 @@ test-junit-ext = { module = "androidx.test.ext:junit", version = "1.3.0" } test-mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "6.2.2" } test-robolectric = { module = "org.robolectric:robolectric", version = "4.16.1" } test-turbine = { group = "app.cash.turbine", name = "turbine", version = "1.2.1" } -vss-client = { module = "com.synonym:vss-client-android", version = "0.5.23" } +vss-client = { module = "com.synonym:vss-client-android", version = "0.5.24" } webkit = { module = "androidx.webkit:webkit", version = "1.16.0" } work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version = "2.11.0" } zxing = { module = "com.google.zxing:core", version = "3.5.4" } From 0d106934a1f91c27a15c5ab375ac76c2fa3c018a Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 26 Aug 2026 21:23:36 +0200 Subject: [PATCH 7/7] fix: keep jna uniffi and bc for r8 --- app/src/main/keepRules/bouncycastle.keep | 3 +++ app/src/main/keepRules/jni.keep | 10 ++++++++++ app/src/main/keepRules/uniffi.keep | 6 ++++++ 3 files changed, 19 insertions(+) create mode 100644 app/src/main/keepRules/bouncycastle.keep create mode 100644 app/src/main/keepRules/uniffi.keep diff --git a/app/src/main/keepRules/bouncycastle.keep b/app/src/main/keepRules/bouncycastle.keep new file mode 100644 index 0000000000..a34d949c81 --- /dev/null +++ b/app/src/main/keepRules/bouncycastle.keep @@ -0,0 +1,3 @@ +# Crypto replaces Android's BC provider with the app's BouncyCastleProvider. +# The provider registers SPI classes by name, including KeyStore.BKS used by Conscrypt. +-keep class org.bouncycastle.** { *; } diff --git a/app/src/main/keepRules/jni.keep b/app/src/main/keepRules/jni.keep index dcb4ca1381..a41b9340ae 100644 --- a/app/src/main/keepRules/jni.keep +++ b/app/src/main/keepRules/jni.keep @@ -29,3 +29,13 @@ (...); *; } + +# libjnidispatch looks up Pointer.peer and other JNA members by JNI name. +# net.java.dev.jna ships no consumer keep rules. +-keep class com.sun.jna.** { *; } + +# JNA reads @Structure.FieldOrder and constructs ByValue/ByReference reflectively. +# Library consumer rules use -keepclassmembers, which does not keep the annotation. +-keep @com.sun.jna.Structure$FieldOrder class * { *; } +-keep class * extends com.sun.jna.Structure { *; } +-keep class * implements com.sun.jna.Callback { *; } diff --git a/app/src/main/keepRules/uniffi.keep b/app/src/main/keepRules/uniffi.keep new file mode 100644 index 0000000000..25d9612dd4 --- /dev/null +++ b/app/src/main/keepRules/uniffi.keep @@ -0,0 +1,6 @@ +# UniFFI JNA bindings. Library consumer rules keep members but still allow +# R8 to rename UniffiLib/FfiConverter types, which ClassCastExceptions on load. +-keep class com.synonym.vssclient.** { *; } +-keep class com.synonym.bitkitcore.** { *; } +-keep class com.synonym.paykit.** { *; } +-keep class org.lightningdevkit.ldknode.** { *; }