refactor: r8 build optmisations

This commit is contained in:
2026-06-10 21:49:52 +02:00
parent 3c9b480a9e
commit d1c3722781
3 changed files with 133 additions and 55 deletions
+10 -4
View File
@@ -33,6 +33,10 @@ android {
targetSdk = 36 targetSdk = 36
versionCode = 1 versionCode = 1
versionName = "0.1.0" versionName = "0.1.0"
androidResources {
localeFilters += setOf("en", "es", "eu")
}
// testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" // testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner"
@@ -52,8 +56,8 @@ android {
buildTypes { buildTypes {
release { release {
// isMinifyEnabled = true // Enables R8/ProGuard shrinking isMinifyEnabled = true // Enables R8/ProGuard shrinking
// isShrinkResources = true // Removes unused resources isShrinkResources = true // Removes unused resources
proguardFiles( proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro" "proguard-rules.pro"
@@ -62,6 +66,8 @@ android {
} }
create("benchmark") { create("benchmark") {
initWith(buildTypes.getByName("release")) initWith(buildTypes.getByName("release"))
isMinifyEnabled = false // benchmarks must not be minified
isShrinkResources = false // or results are meaningless
signingConfig = signingConfigs.getByName("debug") // sign with debug key for easy deployment signingConfig = signingConfigs.getByName("debug") // sign with debug key for easy deployment
installation { installation {
enableBaselineProfile = false // ← disables profile embedding for this build type only enableBaselineProfile = false // ← disables profile embedding for this build type only
@@ -116,7 +122,7 @@ dependencies {
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4) androidTestImplementation(libs.androidx.compose.ui.test.junit4)
implementation(libs.androidx.benchmark.junit4) androidTestImplementation(libs.androidx.benchmark.junit4)
androidTestImplementation(libs.androidx.runner) androidTestImplementation(libs.androidx.runner)
androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
@@ -128,7 +134,7 @@ dependencies {
implementation(libs.retrofit2.retrofit) implementation(libs.retrofit2.retrofit)
implementation(libs.converter.gson) implementation(libs.converter.gson)
implementation(libs.okhttp) implementation(libs.okhttp)
implementation(libs.logging.interceptor) debugImplementation(libs.logging.interceptor)
// Coroutines // Coroutines
implementation(libs.kotlinx.coroutines.android) implementation(libs.kotlinx.coroutines.android)
+123 -23
View File
@@ -1,24 +1,124 @@
# Add project specific ProGuard rules here. # ──────────────────────────────────────────────────────────────────
# You can control the set of applied configuration files using the # Protobuf lite
# proguardFiles setting in build.gradle. # ──────────────────────────────────────────────────────────────────
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# Keep all protobuf generated message classes and their fields
-keep class * extends com.google.protobuf.GeneratedMessageLite { *; } -keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
# ──────────────────────────────────────────────────────────────────
# Google Tink 1.13.0
# ──────────────────────────────────────────────────────────────────
-keep class com.google.crypto.tink.proto.** { *; }
-keep class com.google.crypto.tink.shaded.protobuf.** { *; }
-keep class com.google.crypto.tink.** { *; }
-dontwarn com.google.crypto.tink.**
# ──────────────────────────────────────────────────────────────────
# Gson generic signature safety
# ──────────────────────────────────────────────────────────────────
-keepattributes Signature
-keepattributes *Annotation*
-keep,allowobfuscation,allowshrinking,allowoptimization class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking,allowoptimization class * extends com.google.gson.reflect.TypeToken
# ──────────────────────────────────────────────────────────────────
# Gson ALL classes Gson instantiates via reflection
# ──────────────────────────────────────────────────────────────────
# Response bodies
-keep class com.bitcointxoko.gudariwallet.api.WalletResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.PaymentStatusResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.PaymentDetails { *; }
-keep class com.bitcointxoko.gudariwallet.api.PaymentDetailResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.WithdrawCallbackResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.FiatRateResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.LnurlpLink { *; }
# NWC models
-keep class com.bitcointxoko.gudariwallet.api.NwcGetResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.NwcKey { *; }
-keep class com.bitcointxoko.gudariwallet.api.NwcBudget { *; }
-keep class com.bitcointxoko.gudariwallet.api.NwcNewBudget { *; }
-keep class com.bitcointxoko.gudariwallet.api.NwcRegistrationRequest { *; }
# Request bodies
-keep class com.bitcointxoko.gudariwallet.api.CreateInvoiceRequest { *; }
-keep class com.bitcointxoko.gudariwallet.api.PayInvoiceRequest { *; }
-keep class com.bitcointxoko.gudariwallet.api.DecodeInvoiceRequest { *; }
-keep class com.bitcointxoko.gudariwallet.api.PayLnurlRequest { *; }
# SuccessAction sealed class + TypeAdapter subclasses
-keep class com.bitcointxoko.gudariwallet.api.SuccessAction { *; }
-keep class com.bitcointxoko.gudariwallet.api.FlexibleStringAdapter
-keep class com.bitcointxoko.gudariwallet.api.SuccessActionAdapter
# Node alias API responses
-keep class com.bitcointxoko.gudariwallet.api.MempoolNodeResponse { *; }
-keep class com.bitcointxoko.gudariwallet.api.OneMlNodeResponse { *; }
# ──────────────────────────────────────────────────────────────────
# Retrofit 3.0.0
# ──────────────────────────────────────────────────────────────────
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
# ──────────────────────────────────────────────────────────────────
# OkHttp 5.x / Okio
# ──────────────────────────────────────────────────────────────────
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontwarn org.codehaus.mojo.animal_sniffer.*
# ──────────────────────────────────────────────────────────────────
# secp256k1-kmp (JNI)
# ──────────────────────────────────────────────────────────────────
-keep class fr.acinq.secp256k1.** { *; }
-keepclasseswithmembernames class * {
native <methods>;
}
# ──────────────────────────────────────────────────────────────────
# ZXing 4.3.0
# ──────────────────────────────────────────────────────────────────
-keep class com.google.zxing.** { *; }
-dontwarn com.google.zxing.**
# ──────────────────────────────────────────────────────────────────
# Room 2.7.1
# ──────────────────────────────────────────────────────────────────
-keep class * extends androidx.room.RoomDatabase
-keep @androidx.room.Entity class *
-dontwarn androidx.room.**
# ──────────────────────────────────────────────────────────────────
# WorkManager 2.9.1
# ──────────────────────────────────────────────────────────────────
-keep class * extends androidx.work.Worker
-keep class * extends androidx.work.CoroutineWorker
-keep class * extends androidx.work.ListenableWorker {
public <init>(android.content.Context, androidx.work.WorkerParameters);
}
# ──────────────────────────────────────────────────────────────────
# Kotlin Coroutines 1.11.0
# ──────────────────────────────────────────────────────────────────
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-dontwarn kotlinx.coroutines.**
# ──────────────────────────────────────────────────────────────────
# Lyricist 1.8.0
# ──────────────────────────────────────────────────────────────────
-keep class com.bitcointxoko.gudariwallet.**Strings { *; }
-keep class com.bitcointxoko.gudariwallet.**Translations { *; }
# ──────────────────────────────────────────────────────────────────
# Timber 5.0.1
# ──────────────────────────────────────────────────────────────────
-dontwarn org.jetbrains.annotations.**
# ──────────────────────────────────────────────────────────────────
# Stack traces upload mapping.txt to Play Console / Crashlytics
# ──────────────────────────────────────────────────────────────────
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
@@ -1,40 +1,22 @@
package com.bitcointxoko.gudariwallet.api package com.bitcointxoko.gudariwallet.api
import com.bitcointxoko.gudariwallet.BuildConfig
import com.bitcointxoko.gudariwallet.security.SecretStore import com.bitcointxoko.gudariwallet.security.SecretStore
import com.bitcointxoko.gudariwallet.util.WalletConstants import com.bitcointxoko.gudariwallet.util.WalletConstants
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import timber.log.Timber
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
object LNbitsClient { object LNbitsClient {
val logging = HttpLoggingInterceptor { message ->
Timber.tag("OkHttp").d(message)
}.apply {
level = HttpLoggingInterceptor.Level.BODY // logs full request + response body
}
// Single shared client — used by both Retrofit and WebSocket // Single shared client — used by both Retrofit and WebSocket
val httpClient: OkHttpClient = OkHttpClient.Builder() val httpClient: OkHttpClient = OkHttpClient.Builder()
.connectTimeout(WalletConstants.CONNECT_TIMEOUT_S, TimeUnit.SECONDS) .connectTimeout(WalletConstants.CONNECT_TIMEOUT_S, TimeUnit.SECONDS)
.readTimeout(WalletConstants.READ_TIMEOUT_S, TimeUnit.SECONDS) .readTimeout(WalletConstants.READ_TIMEOUT_S, TimeUnit.SECONDS)
.writeTimeout(WalletConstants.WRITE_TIMEOUT_S, TimeUnit.SECONDS) .writeTimeout(WalletConstants.WRITE_TIMEOUT_S, TimeUnit.SECONDS)
.addInterceptor(logging)
.apply {
if (BuildConfig.DEBUG) {
addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
}
}
.build() .build()
fun create(secrets: SecretStore): LNbitsApi { fun create(secrets: SecretStore): LNbitsApi {
@@ -71,21 +53,11 @@ object LNbitsClient {
} }
val client = httpClient.newBuilder() val client = httpClient.newBuilder()
// .addInterceptor(authInterceptor)
.addInterceptor(dynamicBaseUrlInterceptor) .addInterceptor(dynamicBaseUrlInterceptor)
.apply {
// Logging goes LAST — after URL rewrite — so logs show the real URL
if (BuildConfig.DEBUG) {
addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
}
}
.build() .build()
return Retrofit.Builder() return Retrofit.Builder()
.baseUrl("https://placeholder.invalid/") // structurally required by Retrofit; .baseUrl("https://placeholder.invalid/") // structurally required by Retrofit;
// always overwritten by the interceptor
.client(client) .client(client)
.addConverterFactory(GsonConverterFactory.create(GsonProvider.gson)) .addConverterFactory(GsonConverterFactory.create(GsonProvider.gson))
.build() .build()