sentry-java
sentry-java copied to clipboard
User interaction breadcrumbs not initialized when initializing Sentry after activity started
Integration
sentry-android
Build System
Gradle
AGP Version
8.5.1
Proguard
Enabled
Version
7.14.0
Steps to Reproduce
-
Disable auto-initialization by adding the appropriate metadata entry to the app's manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application> <meta-data android:name="io.sentry.auto-init" android:value="false" /> </application> </manifest> -
Wait for the
MainActivityto start (i.e. to receiveonStart()). -
Initialize Sentry manually using
Sentry.init(...), making sure to enable user interaction breadcrumbs:SentryAndroid.init(this) { options -> options.isDebug = true options.enableAllAutoBreadcrumbs(true) options.isEnableUserInteractionBreadcrumbs = true } -
Perform UI interactions (on tagged components). Observe that no interaction is logged to Logcat (despite debug mode and other breadcrumbs being correctly generated).
-
Put the app into the background (causing
onPause()andonStop()to be called on the activity) -
Bring the app back into the foreground (causing
onStart()andonResume()to be called on the activity). -
Retry UI interactions and observe that UI interactions are correctly tracked now.
Expected Result
UI interactions should be tracked starting with the initialization of Sentry, even if it happens after the activity was first started.
Actual Result
UI interaction won't be tracked, until the first time the activity is backgrounded and foregrounded again or a workaround (like this one) is applied:
// This is a workaround for an issue coming from the delayed initialization of Sentry.
// If the activity starts before Sentry is initialized, we're missing interaction
// breadcrumbs. This will ensure that interaction breadcrumbs are still collected.
val activity = this
Didomi.getInstance().apply {
onReady {
if(Sentry.isEnabled()) {
Sentry.configureScope { scope ->
val lifecycleState = activity.lifecycle.currentState
scope.options
.integrations
.filterIsInstance<ActivityLifecycleCallbacks>()
.forEach { integration ->
if (lifecycleState.isAtLeast(Lifecycle.State.CREATED)) {
integration.onActivityCreated(activity, null)
}
if (lifecycleState.isAtLeast(Lifecycle.State.STARTED)) {
integration.onActivityStarted(activity)
}
if (lifecycleState.isAtLeast(Lifecycle.State.RESUMED)) {
integration.onActivityResumed(activity)
}
}
}
}
}
}