Skip to content

Commit dda2380

Browse files
feat(cmp-firebase): commonMain-first Firebase (Analytics + Crashlytics, 15 targets) + crash→GA4 delivery audit fixes (#158)
* chore: initialize session branch — cmp-firebase commonMain * chore(source): update cmp-firebase/README.md cmp-firebase/build.gradle.kts cmp-firebase/src/androidMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseInitProvider.kt * chore(source): update cmp-firebase/api/jvm/cmp-firebase.api * chore(source): update cmp-firebase/api/jvm/cmp-firebase.api cmp-firebase/build.gradle.kts cmp-firebase/src/commonMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseKit.kt * chore(source): update cmp-firebase/DEVELOPMENT.md cmp-firebase/README.md cmp-firebase/src/commonMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig.kt * chore(source): update cmp-firebase/src/commonMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/analytics/InMemorySettings.kt cmp-firebase/src/commonMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporterExtensions.kt cmp-firebase/src/commonMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/di/CrashReporterModule.kt
1 parent 7e84cda commit dda2380

49 files changed

Lines changed: 1697 additions & 234 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmp-firebase/DEVELOPMENT.md

Lines changed: 220 additions & 50 deletions
Large diffs are not rendered by default.

cmp-firebase/README.md

Lines changed: 91 additions & 24 deletions
Large diffs are not rendered by default.

cmp-firebase/api/jvm/cmp-firebase.api

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,72 @@
1+
public final class io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig {
2+
public static final field Companion Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Companion;
3+
public fun <init> ()V
4+
public fun <init> (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;)V
5+
public synthetic fun <init> (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
6+
public final fun component1 ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
7+
public final fun component2 ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
8+
public final fun component3 ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
9+
public final fun component4 ()Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;
10+
public final fun copy (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig;
11+
public static synthetic fun copy$default (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;ILjava/lang/Object;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig;
12+
public fun equals (Ljava/lang/Object;)Z
13+
public final fun getAndroid ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
14+
public final fun getApple ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
15+
public final fun getMeasurementProtocol ()Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;
16+
public final fun getWeb ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
17+
public fun hashCode ()I
18+
public final fun optionsForCurrentPlatform ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
19+
public fun toString ()Ljava/lang/String;
20+
}
21+
22+
public final class io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Builder {
23+
public fun <init> ()V
24+
public final fun android (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Builder;
25+
public final fun apple (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Builder;
26+
public final fun build ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig;
27+
public final fun measurementProtocol (Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/mp/MpConfig;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Builder;
28+
public final fun web (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Builder;
29+
}
30+
31+
public final class io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Companion {
32+
public final fun builder ()Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig$Builder;
33+
}
34+
135
public final class io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseKit {
236
public static final field INSTANCE Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseKit;
337
public final fun getCrashReporter ()Lio/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporter;
438
public final fun initialize ()V
39+
public final fun initialize (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseConfig;)V
40+
public final fun installUncaughtHandler ()Z
541
public final fun isInitialized ()Z
642
}
743

44+
public final class io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions {
45+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
46+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
47+
public final fun component1 ()Ljava/lang/String;
48+
public final fun component2 ()Ljava/lang/String;
49+
public final fun component3 ()Ljava/lang/String;
50+
public final fun component4 ()Ljava/lang/String;
51+
public final fun component5 ()Ljava/lang/String;
52+
public final fun component6 ()Ljava/lang/String;
53+
public final fun component7 ()Ljava/lang/String;
54+
public final fun component8 ()Ljava/lang/String;
55+
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
56+
public static synthetic fun copy$default (Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/github/mobilebytelabs/kmptoolkit/firebase/FirebaseOptions;
57+
public fun equals (Ljava/lang/Object;)Z
58+
public final fun getApiKey ()Ljava/lang/String;
59+
public final fun getApplicationId ()Ljava/lang/String;
60+
public final fun getAuthDomain ()Ljava/lang/String;
61+
public final fun getDatabaseUrl ()Ljava/lang/String;
62+
public final fun getGaTrackingId ()Ljava/lang/String;
63+
public final fun getGcmSenderId ()Ljava/lang/String;
64+
public final fun getProjectId ()Ljava/lang/String;
65+
public final fun getStorageBucket ()Ljava/lang/String;
66+
public fun hashCode ()I
67+
public fun toString ()Ljava/lang/String;
68+
}
69+
870
public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsBatch {
971
public final fun add (Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsEvent;)Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsBatch;
1072
public final fun add (Ljava/lang/String;[Lkotlin/Pair;)Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsBatch;
@@ -115,7 +177,7 @@ public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/Analyt
115177
public static fun setUserProperty (Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsHelper;Ljava/lang/String;Ljava/lang/String;)V
116178
}
117179

118-
public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsProvider_firebaseKt {
180+
public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsProviderKt {
119181
public static final fun provideAnalyticsHelper ()Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsHelper;
120182
}
121183

@@ -161,6 +223,7 @@ public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/EventR
161223
public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/EventTypes {
162224
public static final field API_ERROR Ljava/lang/String;
163225
public static final field APP_BACKGROUND Ljava/lang/String;
226+
public static final field APP_CRASH Ljava/lang/String;
164227
public static final field APP_FOREGROUND Ljava/lang/String;
165228
public static final field APP_LAUNCH Ljava/lang/String;
166229
public static final field BUTTON_CLICK Ljava/lang/String;
@@ -224,29 +287,6 @@ public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/EventV
224287
public fun toString ()Ljava/lang/String;
225288
}
226289

227-
public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/FirebaseAnalyticsHelper : io/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsHelper {
228-
public static final field MAX_EVENT_NAME_LEN I
229-
public static final field MAX_PARAM_KEY_LEN I
230-
public static final field MAX_PARAM_VALUE_LEN I
231-
public static final field MAX_USER_ID_LEN I
232-
public static final field MAX_USER_PROP_NAME_LEN I
233-
public static final field MAX_USER_PROP_VALUE_LEN I
234-
public fun <init> (Ldev/gitlive/firebase/analytics/FirebaseAnalytics;Ljava/lang/String;)V
235-
public synthetic fun <init> (Ldev/gitlive/firebase/analytics/FirebaseAnalytics;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
236-
public fun logButtonClick (Ljava/lang/String;Ljava/lang/String;)V
237-
public fun logError (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
238-
public fun logEvent (Lio/github/mobilebytelabs/kmptoolkit/firebase/analytics/AnalyticsEvent;)V
239-
public fun logEvent (Ljava/lang/String;Ljava/util/Map;)V
240-
public fun logEvent (Ljava/lang/String;[Lkotlin/Pair;)V
241-
public fun logFeatureUsed (Ljava/lang/String;Ljava/lang/String;)V
242-
public fun logScreenView (Ljava/lang/String;Ljava/lang/String;)V
243-
public fun logStateTransition (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
244-
public fun setCollectionEnabled (Z)V
245-
public fun setConsent (ZZ)V
246-
public fun setUserId (Ljava/lang/String;)V
247-
public fun setUserProperty (Ljava/lang/String;Ljava/lang/String;)V
248-
}
249-
250290
public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/Funnel {
251291
public static final field EVENT_ABANDON Ljava/lang/String;
252292
public static final field EVENT_COMPLETE Ljava/lang/String;
@@ -342,6 +382,8 @@ public final class io/github/mobilebytelabs/kmptoolkit/firebase/analytics/ParamK
342382
public static final field ELEMENT_TYPE Ljava/lang/String;
343383
public static final field ERROR_CODE Ljava/lang/String;
344384
public static final field ERROR_MESSAGE Ljava/lang/String;
385+
public static final field EXCEPTION_TYPE Ljava/lang/String;
386+
public static final field FATAL Ljava/lang/String;
345387
public static final field FEATURE_NAME Ljava/lang/String;
346388
public static final field FIELD_NAME Ljava/lang/String;
347389
public static final field FILTER_TYPE Ljava/lang/String;
@@ -669,7 +711,9 @@ public final class io/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/Cras
669711

670712
public final class io/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporterExtensionsKt {
671713
public static final fun asCoroutineExceptionHandler (Lio/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporter;)Lkotlinx/coroutines/CoroutineExceptionHandler;
714+
public static final fun asCoroutineExceptionHandler (Lio/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporter;Z)Lkotlinx/coroutines/CoroutineExceptionHandler;
672715
public static final fun recording (Lio/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporter;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
716+
public static final fun recording (Lio/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporter;ZLkotlin/jvm/functions/Function0;)Ljava/lang/Object;
673717
}
674718

675719
public final class io/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReporterProvider_fallbackKt {
@@ -680,6 +724,8 @@ public final class io/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/Logg
680724
public fun <init> ()V
681725
public fun <init> (Ljava/lang/String;)V
682726
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
727+
public fun <init> (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
728+
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
683729
public fun getLastReport ()Lio/github/mobilebytelabs/kmptoolkit/firebase/crashlytics/CrashReport;
684730
public fun install ()V
685731
public fun log (Ljava/lang/String;)V

cmp-firebase/build.gradle.kts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ kotlin {
103103
// │ ├── tvosMain (tvosX64 / tvosArm64 / tvosSimulatorArm64)
104104
// │ └── jsMain (browser + node)
105105
//
106-
// └── nonFirebaseMain — Measurement Protocol HTTP (9 targets)
107-
// ├── watchosMain (watchosX64 / watchosArm64 / watchosSimulatorArm64 / watchosDeviceArm64)
106+
// └── nonFirebaseMain — Measurement Protocol HTTP (5 targets)
107+
// ├── jvmMain
108108
// ├── linuxMain (linuxX64 / linuxArm64)
109109
// ├── mingwMain (mingwX64)
110110
// └── wasmJsMain
111111
//
112-
// wasmWasi target intentionally omitted — Ktor / Kermit / multiplatform-settings
113-
// do not publish wasmWasi variants. 20/21 targets supported.
112+
// wasmWasi + watchOS intentionally omitted — cmp-network-monitor (a dependency) and
113+
// Ktor/Kermit/multiplatform-settings do not publish those variants. 15 targets supported.
114114
//
115115
// GitLive Firebase Analytics 3.0.x target matrix verified at:
116116
// https://github.com/GitLiveApp/firebase-kotlin-sdk/blob/master/firebase-analytics/build.gradle.kts
@@ -139,6 +139,7 @@ kotlin {
139139
val firebaseMain by creating {
140140
dependsOn(commonMain.get())
141141
dependencies {
142+
api(libs.gitlive.firebase.app)
142143
api(libs.gitlive.firebase.analytics)
143144
}
144145
}
@@ -149,15 +150,18 @@ kotlin {
149150
dependsOn(commonMain.get())
150151
}
151152

152-
// GitLive-supported → firebaseMain
153+
// GitLive-supported native analytics + programmatic init → firebaseMain
153154
androidMain.get().dependsOn(firebaseMain)
154-
jvmMain.get().dependsOn(firebaseMain)
155155
iosMain.get().dependsOn(firebaseMain)
156156
macosMain.get().dependsOn(firebaseMain)
157157
tvosMain.get().dependsOn(firebaseMain)
158158
jsMain.get().dependsOn(firebaseMain)
159159

160-
// Not supported by GitLive → nonFirebaseMain (Measurement Protocol HTTP)
160+
// Not supported by GitLive → nonFirebaseMain (Measurement Protocol HTTP).
161+
// JVM is here too: GitLive's JVM analytics is a no-op stub AND JVM has no
162+
// Android Context for programmatic init, so JVM runs on the MP tier
163+
// (no-op platformInitializeFirebase + MP analytics).
164+
jvmMain.get().dependsOn(nonFirebaseMain)
161165
linuxMain.get().dependsOn(nonFirebaseMain)
162166
mingwMain.get().dependsOn(nonFirebaseMain)
163167
wasmJsMain.get().dependsOn(nonFirebaseMain)
@@ -170,7 +174,7 @@ kotlin {
170174
// dependsOn exactly one crashlytics tier + one analytics tier.
171175
//
172176
// crashlyticsFirebaseMain (6) — GitLive Crashlytics: android, ios×3, macos×2
173-
// crashlyticsFallbackMain (13) — LoggingCrashReporter: jvm, js, tvos×3, watchos×4, linux×2, mingw, wasmJs
177+
// crashlyticsFallbackMain (9) — LoggingCrashReporter: jvm, js, tvos×3, linux×2, mingw, wasmJs
174178
//
175179
// GitLive firebase-crashlytics 3.0.0-alpha01 publishes ONLY android + iOS + macOS
176180
// (NO tvOS/watchOS/JVM/JS/native) — verified against its published artifacts.
@@ -243,9 +247,9 @@ mavenPublishing {
243247
description =
244248
"Firebase for Kotlin Multiplatform — Analytics + Crashlytics with a single in-library " +
245249
"setup surface (FirebaseKit.initialize + Android auto-init). GitLive Firebase Analytics " +
246-
"on 11 targets (Measurement-Protocol HTTP fallback on the rest) and GitLive Crashlytics " +
250+
"on 10 targets (Measurement-Protocol HTTP fallback on the rest) and GitLive Crashlytics " +
247251
"on 6 targets, with an AI-feedable structured CrashReport fallback (Kermit) everywhere else. " +
248-
"Interface + Stub/NoOp/Test variants across all 20 supported KMP targets."
252+
"Interface + Stub/NoOp/Test variants across all 15 supported KMP targets."
249253
inceptionYear = "2026"
250254
url = "https://github.com/MobileByteLabs/KmpToolkit/"
251255

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2026 MobileByteLabs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*/
10+
package io.github.mobilebytelabs.kmptoolkit.firebase
11+
12+
import android.content.Context
13+
14+
/**
15+
* Android application-Context holder for programmatic Firebase init.
16+
*
17+
* `FirebaseInitProvider` (a `ContentProvider`, runs before `Application.onCreate`)
18+
* captures the application `Context` here, so `FirebaseKit.initialize(config)`
19+
* stays a pure commonMain call — the consumer never passes a Context.
20+
*
21+
* If the provider is removed from the merged manifest (`tools:node="remove"`),
22+
* call [setApplicationContext] manually before `FirebaseKit.initialize(config)`.
23+
*/
24+
public object AndroidFirebaseContext {
25+
26+
/** The captured application [Context], or `null` if not yet set. */
27+
val app: Context?
28+
get() = FirebaseNativeContext.value as? Context
29+
30+
/** Manually supply the application [Context] (provider-removed fallback). */
31+
public fun setApplicationContext(context: Context) {
32+
FirebaseNativeContext.value = context.applicationContext
33+
}
34+
}

cmp-firebase/src/androidMain/kotlin/io/github/mobilebytelabs/kmptoolkit/firebase/FirebaseInitProvider.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ import android.net.Uri
2929
internal class FirebaseInitProvider : ContentProvider() {
3030

3131
override fun onCreate(): Boolean {
32-
runCatching { FirebaseKit.initialize() }
32+
// Capture the application Context (runs before Application.onCreate) so the
33+
// consumer's commonMain FirebaseKit.initialize(config) can pass it to GitLive's
34+
// Firebase.initialize on Android. Does NOT initialize Firebase itself — that is
35+
// the consumer's single commonMain init call.
36+
runCatching { context?.applicationContext?.let { AndroidFirebaseContext.setApplicationContext(it) } }
3337
return true
3438
}
3539

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2026 MobileByteLabs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*/
10+
package io.github.mobilebytelabs.kmptoolkit.firebase
11+
12+
/**
13+
* Chains a JVM default uncaught-exception handler that mirrors the fatal crash to
14+
* [onUncaught] (→ GA4 `app_crash`) BEFORE delegating to whatever handler was already
15+
* installed (e.g. the platform/Crashlytics default), so native capture is preserved.
16+
*/
17+
internal actual fun installPlatformUncaughtHandler(onUncaught: (Throwable) -> Unit): Boolean {
18+
val previous = Thread.getDefaultUncaughtExceptionHandler()
19+
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
20+
runCatching { onUncaught(throwable) }
21+
previous?.uncaughtException(thread, throwable)
22+
}
23+
return true
24+
}

0 commit comments

Comments
 (0)