fix: r8 broke workmanager

This commit is contained in:
2026-06-11 01:22:48 +02:00
parent e242c7b5d0
commit 39c31f96a8
7 changed files with 112 additions and 78 deletions
+8 -4
View File
@@ -27,6 +27,14 @@ android {
minorApiLevel = 1 minorApiLevel = 1
} }
} }
splits {
abi {
isEnable = true
reset() // Clear all defaults
include("arm64-v8a") // Specify desired ABIs
isUniversalApk = false
}
}
defaultConfig { defaultConfig {
applicationId = "com.bitcointxoko.gudariwallet" applicationId = "com.bitcointxoko.gudariwallet"
@@ -37,9 +45,6 @@ android {
androidResources { androidResources {
localeFilters += setOf("en", "es", "eu") localeFilters += setOf("en", "es", "eu")
} }
// testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner"
testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "ACTIVITY-MISSING" testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "ACTIVITY-MISSING"
} }
@@ -174,7 +179,6 @@ dependencies {
//Navigation //Navigation
implementation(libs.androidx.navigation.compose) implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
// animations // animations
+65 -46
View File
@@ -6,53 +6,44 @@
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
# Google Tink 1.13.0 # Google Tink 1.13.0
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
-keep class com.google.crypto.tink.proto.** { *; } -keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite {
-keep class com.google.crypto.tink.shaded.protobuf.** { *; } <fields>;
-keep class com.google.crypto.tink.** { *; } }
-keep class com.google.crypto.tink.KeyTemplates { *; }
-keep class com.google.crypto.tink.StreamingAead { *; }
-keep class com.google.crypto.tink.KeysetHandle { *; }
-keep class com.google.crypto.tink.integration.android.AndroidKeysetManager { *; }
-keep class com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder { *; }
-keep class com.google.crypto.tink.streamingaead.StreamingAeadConfig { *; }
-keep class com.google.crypto.tink.streamingaead.AesGcmHkdfStreamingKeyManager { *; }
-keep class com.google.crypto.tink.streamingaead.StreamingAeadWrapper { *; }
-keep class com.google.crypto.tink.subtle.AesGcmHkdfStreaming { *; }
-dontwarn com.google.crypto.tink.** -dontwarn com.google.crypto.tink.**
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
# Gson generic signature safety # kotlinx.serialization
# The compiler plugin generates a $serializer inner class for every
# @Serializable class. R8 must not remove or rename these they are
# looked up by name at runtime via SerializersModule.
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
-keepattributes Signature -keepattributes *Annotation*, InnerClasses
-keepattributes *Annotation* -dontnote kotlinx.serialization.**
-keep,allowobfuscation,allowshrinking,allowoptimization class com.google.gson.reflect.TypeToken -dontwarn kotlinx.serialization.**
-keep,allowobfuscation,allowshrinking,allowoptimization class * extends com.google.gson.reflect.TypeToken
# ────────────────────────────────────────────────────────────────── # Keep generated serializers for all @Serializable classes in your app
# Gson ALL classes Gson instantiates via reflection -keepclassmembers class com.bitcointxoko.gudariwallet.** {
# ────────────────────────────────────────────────────────────────── kotlinx.serialization.KSerializer serializer(...);
}
# Response bodies # Keep the $serializer companion objects themselves
-keep class com.bitcointxoko.gudariwallet.api.WalletResponse { *; } -keep class com.bitcointxoko.gudariwallet.**$$serializer { *; }
-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 # Required for sealed class polymorphic serialization
-keep class com.bitcointxoko.gudariwallet.api.NwcGetResponse { *; } -keepclassmembers @kotlinx.serialization.Serializable class * {
-keep class com.bitcointxoko.gudariwallet.api.NwcKey { *; } *** Companion;
-keep class com.bitcointxoko.gudariwallet.api.NwcBudget { *; } *** INSTANCE;
-keep class com.bitcointxoko.gudariwallet.api.NwcNewBudget { *; } kotlinx.serialization.KSerializer serializer(...);
-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 # Retrofit 3.0.0
@@ -79,8 +70,32 @@
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
# ZXing 4.3.0 # ZXing 4.3.0
#
# ZXing uses reflection to instantiate Reader subclasses by class name.
# Only the classes your app actually exercises need to be kept.
# A Lightning wallet only needs QR code scanning (QR_CODE format).
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
-keep class com.google.zxing.** { *; }
# Core entry points used directly via the API
-keep class com.google.zxing.BarcodeFormat { *; }
-keep class com.google.zxing.DecodeHintType { *; }
-keep class com.google.zxing.Result { *; }
-keep class com.google.zxing.ResultMetadataType { *; }
-keep class com.google.zxing.MultiFormatReader { *; }
# QR code reader instantiated reflectively by MultiFormatReader
-keep class com.google.zxing.qrcode.QRCodeReader { *; }
-keep class com.google.zxing.qrcode.decoder.** { *; }
-keep class com.google.zxing.qrcode.detector.** { *; }
# QR code generator
-keep class com.google.zxing.qrcode.QRCodeWriter { *; }
# Common infrastructure used by all readers
-keep class com.google.zxing.common.** { *; }
# Suppress warnings for unused format readers (1D barcodes, DataMatrix, etc.)
# that are in the jar but not needed by a wallet app
-dontwarn com.google.zxing.** -dontwarn com.google.zxing.**
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
@@ -93,11 +108,15 @@
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
# WorkManager 2.9.1 # WorkManager 2.9.1
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
-keep class * extends androidx.work.Worker -keep class * extends androidx.work.InputMerger { *; }
-keep class * extends androidx.work.CoroutineWorker -keep class * extends androidx.work.Worker { *; }
-keep class * extends androidx.work.ListenableWorker { -keep class * extends androidx.work.CoroutineWorker { *; }
public <init>(android.content.Context, androidx.work.WorkerParameters); -keep class * extends androidx.work.ListenableWorker { *; }
} -keep class * extends androidx.work.WorkerFactory { *; }
# Keep specific classes explicitly as a safety net
-keep class com.bitcointxoko.gudariwallet.sync.HistoricalSyncWorker { *; }
-keep class com.bitcointxoko.gudariwallet.sync.HistoricalSyncWorker$Companion { *; }
-keep class com.bitcointxoko.gudariwallet.sync.HistoricalSyncWorkerFactory { *; }
# ────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────
# Kotlin Coroutines 1.11.0 # Kotlin Coroutines 1.11.0
+8 -3
View File
@@ -8,12 +8,17 @@
"variantName": "release", "variantName": "release",
"elements": [ "elements": [
{ {
"type": "SINGLE", "type": "ONE_OF_MANY",
"filters": [], "filters": [
{
"filterType": "ABI",
"value": "arm64-v8a"
}
],
"attributes": [], "attributes": [],
"versionCode": 1, "versionCode": 1,
"versionName": "0.1.0", "versionName": "0.1.0",
"outputFile": "app-release.apk" "outputFile": "app-arm64-v8a-release.apk"
} }
], ],
"elementType": "File", "elementType": "File",
@@ -29,7 +29,7 @@ class GudariWalletApplication : Application(), Configuration.Provider {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
NotificationHelper.createChannels(this) // moved from MainActivity NotificationHelper.createChannels(this)
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree()) Timber.plant(Timber.DebugTree())
} }
@@ -19,5 +19,6 @@ object JsonProvider {
ignoreUnknownKeys = true // tolerate extra fields from the API ignoreUnknownKeys = true // tolerate extra fields from the API
isLenient = true // accept unquoted/malformed JSON from some endpoints isLenient = true // accept unquoted/malformed JSON from some endpoints
explicitNulls = false // omit null fields when serializing requests explicitNulls = false // omit null fields when serializing requests
encodeDefaults = true
} }
} }
@@ -340,42 +340,43 @@ data class FiatRateResponse(
// ── History sync ────────────────────────────────────────────────────────────── // ── History sync ──────────────────────────────────────────────────────────────
@Serializable @Serializable
data class PaginatedPaymentsResponse( data class PaginatedPaymentsResponse(
@SerialName("data") val data: List<PaymentRecord>, @SerialName("data") val data: List<PaymentRecord> = emptyList(),
@SerialName("total") val total: Int @SerialName("total") val total: Int = 0
) )
// ── NWC Provider models ─────────────────────────────────────────────────────── // ── NWC Provider models ───────────────────────────────────────────────────────
@Serializable @Serializable
data class NwcKey( data class NwcKey(
val pubkey: String, val pubkey: String = "",
val wallet: String, val wallet: String = "",
val description: String, val description: String = "",
val expires_at: Long, val expires_at: Long = 0L,
val permissions: String, val permissions: String = "",
val created_at: Long, val created_at: Long = 0L,
val last_used: Long val last_used: Long = 0L
) )
@Serializable @Serializable
data class NwcBudget( data class NwcBudget(
val id: Int, val id: Int = 0,
val pubkey: String, val pubkey: String = "",
val budget_msats: Long, val budget_msats: Long = 0L,
val refresh_window: Int, // seconds val refresh_window: Int = 0,
val created_at: Long, val created_at: Long = 0L,
val used_budget_msats: Long = 0 val used_budget_msats: Long = 0L
) )
@Serializable @Serializable
data class NwcGetResponse( data class NwcGetResponse(
val data: NwcKey, val data: NwcKey = NwcKey(),
val budgets: List<NwcBudget> val budgets: List<NwcBudget> = emptyList()
) )
// Request models — no defaults needed (you control the fields, never deserializing)
@Serializable @Serializable
data class NwcNewBudget( data class NwcNewBudget(
val budget_msats: Long, val budget_msats: Long,
val refresh_window: Int, // seconds val refresh_window: Int,
val created_at: Long = System.currentTimeMillis() / 1000L val created_at: Long = System.currentTimeMillis() / 1000L
) )
@@ -383,7 +384,7 @@ data class NwcNewBudget(
data class NwcRegistrationRequest( data class NwcRegistrationRequest(
val permissions: List<String>, val permissions: List<String>,
val description: String, val description: String,
val expires_at: Long, // unix timestamp; 0 = no expiry val expires_at: Long,
val budgets: List<NwcNewBudget> = emptyList() val budgets: List<NwcNewBudget> = emptyList()
) )
+9 -5
View File
@@ -6,11 +6,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html # http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process. # Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. For more details, visit
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
# org.gradle.parallel=true
# Kotlin code style for this project: "official" or "obsolete": # Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official kotlin.code.style=official
#Your project is using a version of the Android Gradle Plugin that has built-in Kotlin support, #Your project is using a version of the Android Gradle Plugin that has built-in Kotlin support,
@@ -35,3 +31,11 @@ org.gradle.parallel=true
# Enable build caching (caches task outputs across clean builds) # Enable build caching (caches task outputs across clean builds)
org.gradle.caching=true org.gradle.caching=true
# Increase heap if R8 is being swapped out ? default is often too low
org.gradle.jvmargs=-Xmx4g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# Enables incremental R8 ? only reprocesses changed classes
# Safe for release builds, significant speedup on incremental rebuilds
android.enableR8.incremental=true
# R8-specific: run R8 in a separate process with more memory
android.r8.jvmArgs=-Xmx4g