Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ follow [https://changelog.md/](https://changelog.md/) guidelines.

## [Unreleased]

## [55.5] - 2026-02-12

### FIXED

- Missing method after bumping `compileSdk` crash
- Crashlytics obfuscating crash names

## [55.4] - 2026-01-29

### CHANGED
Expand Down
4 changes: 2 additions & 2 deletions android/apolloui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ android {
applicationId "io.muun.apollo"
minSdk 21
targetSdk 35
versionCode 1504
versionName "55.4"
versionCode 1505
versionName "55.5"

// Use default Proguard file, bundled with Android Gradle Plugin
// See: https://issuetracker.google.com/issues/126772206
Expand Down
6 changes: 5 additions & 1 deletion android/apolloui/proguard/proguard-crashlytics-2.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
-keepattributes SourceFile, LineNumberTable, *Annotation*

# If you are using custom exceptions, add this line so that custom exception types are skipped during obfuscation:
-keep public class * extends java.lang.Exception
# -keep public class * extends java.lang.Exception

# The line above is the crashlytics recommended way to whitelist this. We are wrapping some exceptions with io.muun.Cause
# that extends from Throwable, using this more permisive way we prevent crashlytics obfuscating it
-keep public class * extends java.lang.Throwable

# For Fabric to properly de-obfuscate your crash reports, you need to remove this line from your ProGuard config:
-printmapping mapping.txt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import android.content.Context
import android.content.res.Resources
import android.os.Bundle
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import io.muun.apollo.domain.analytics.AnalyticsEvent
import io.muun.apollo.domain.errors.ReportAnalyticError
import io.muun.apollo.domain.model.report.ErrorReport
import io.muun.apollo.domain.model.user.User
import rx.Single
Expand Down Expand Up @@ -59,9 +61,15 @@ class AnalyticsProvider @Inject constructor(context: Context) {
}

} catch (t: Throwable) {

val bundle = Bundle().apply { putString("event", event.eventId) }
fba.logEvent("e_tracking_error", bundle)
try {
// FIXME: Desperate times require desperate solutions, currently Crashlytics object
// doesn't expose a plain log, it records an analytics event too, we will address this later.
FirebaseCrashlytics.getInstance().log("AnalyticsProvider: Failed processing analytics event ${event.eventId}, cause: ${t.message}")
val bundle = Bundle().apply { putString("event", event.eventId) }
fba.logEvent("e_tracking_error", bundle)
} catch (e: Exception) {
FirebaseCrashlytics.getInstance().recordException(ReportAnalyticError("AnalyticsProvider: Failed processing analytics event e_tracking_error, cause: ${e.message}"))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ object LoggingRequestTracker {

fun getRecentRequests(): List<Entry> =
synchronized(lock) {
lastEndpoints.values.toList().reversed() // most recent first
lastEndpoints.values.toList().asReversed() // most recent first
}

fun reportRecentRequest(key: IdempotencyKey, url: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.muun.apollo.domain.errors

class ReportAnalyticError(message: String) : MuunError(message)
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,9 @@ public void onDeleteKey() {

@Override
public void onBiometricsKey() {
biometricsRequestedListener.onBiometricsRequested();
if (biometricsRequestedListener != null) {
biometricsRequestedListener.onBiometricsRequested();
}
}
}
}