Skip to content

Commit 11b642f

Browse files
feat: Android Dialog Capture (#302)
## Summary Implement capture multiple type of windows and draw them on each other. Some windows like Toast still not captured. Hoping in the next PRs <img width="720" height="681" alt="image" src="https://github.com/user-attachments/assets/25b1d33b-122f-48b2-83cc-6c09bb7fc21d" /> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds multi-window capture and compositing (activity + dialogs) with per-window masking, refactors capture into `replay.capture`, and updates instrumentation/internals accordingly. > > - **Capture (refactor to `com.launchdarkly.observability.replay.capture`)**: > - **Multi-window capture & compositing**: New `WindowInspector`/`WindowEntry` enumerate app windows and choose a base window; captures overlays and composites bitmaps with position offsets. > - **CaptureSource rewrite**: Uses `PixelCopy` (with fallback to canvas draw), synchronizes to frame, applies masking, encodes WEBP -> Base64, and emits `CaptureEvent`. > - Moves `CaptureEvent` to `replay.capture` package. > - **Masking**: > - `SensitiveAreasCollector.collectFromActivity` now collects from a root `View` (not `Activity`), enabling per-window mask extraction. > - **Instrumentation**: > - `ReplayInstrumentation` integrates new `CaptureSource` API (no Activity lifecycle attach), continues emitting media/interaction logs. > - **Exporter/Tests**: > - Update imports to `replay.capture.CaptureEvent`; minor formatting/test adjustments. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d07327d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 9e65784 commit 11b642f

File tree

9 files changed

+484
-244
lines changed

9 files changed

+484
-244
lines changed

sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/CaptureSource.kt

Lines changed: 0 additions & 232 deletions
This file was deleted.

sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/RRwebGraphQLReplayLogExporter.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.launchdarkly.observability.replay
33
import android.view.MotionEvent
44
import com.launchdarkly.observability.coroutines.DispatcherProviderHolder
55
import com.launchdarkly.observability.network.GraphQLClient
6+
import com.launchdarkly.observability.replay.capture.CaptureEvent
67
import io.opentelemetry.api.common.AttributeKey
78
import io.opentelemetry.sdk.common.CompletableResultCode
89
import io.opentelemetry.sdk.logs.data.LogRecordData

sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/ReplayInstrumentation.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.launchdarkly.observability.replay
33
import com.launchdarkly.logging.LDLogger
44
import com.launchdarkly.observability.coroutines.DispatcherProviderHolder
55
import com.launchdarkly.observability.interfaces.LDExtendedInstrumentation
6+
import com.launchdarkly.observability.replay.capture.CaptureSource
67
import io.opentelemetry.android.instrumentation.InstallationContext
78
import io.opentelemetry.api.logs.Logger
89
import io.opentelemetry.sdk.logs.LogRecordProcessor
@@ -79,7 +80,8 @@ class ReplayInstrumentation(
7980
_otelLogger = ctx.openTelemetry.logsBridge.get(INSTRUMENTATION_SCOPE_NAME)
8081
// TODO: Use real LDClient logger after creating SR Plugin
8182
val logger = LDLogger.none()
82-
_captureSource = CaptureSource(ctx.sessionManager, options.privacyProfile.asMatchersList(), logger)
83+
_captureSource =
84+
CaptureSource(ctx.sessionManager, options.privacyProfile.asMatchersList(), logger)
8385
_interactionSource = InteractionSource(ctx.sessionManager)
8486

8587
// TODO: O11Y-621 - don't use global scope
@@ -127,7 +129,6 @@ class ReplayInstrumentation(
127129
}
128130
}
129131

130-
_captureSource.attachToApplication(ctx.application)
131132
_interactionSource.attachToApplication(ctx.application)
132133

133134
// Start periodic capture automatically

sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/CaptureEvent.kt renamed to sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/capture/CaptureEvent.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.launchdarkly.observability.replay
1+
package com.launchdarkly.observability.replay.capture
22

33
/**
44
* Represents a capture for the replay instrumentation

0 commit comments

Comments
 (0)