Skip to content

Commit 01221e2

Browse files
romtsnclaude
andauthored
fix(gestures): Use peekDecorView to not force view hierarchy construction (#5134)
* fix(gestures): Use peekDecorView to not force view hierarchy construction * fix(gestures): Add changelog entry for peekDecorView fix Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0dd3823 commit 01221e2

4 files changed

Lines changed: 51 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
- Remove `AndroidRuntimeManager` StrictMode relaxation to prevent ANRs during SDK init ([#5127](https://github.com/getsentry/sentry-java/pull/5127))
3434
- **IMPORTANT:** StrictMode violations may appear again in debug builds. This is intentional to prevent ANRs in production releases.
3535
- Fix crash when unregistering `SystemEventsBroadcastReceiver` with try-catch block. ([#5106](https://github.com/getsentry/sentry-java/pull/5106))
36+
- Use `peekDecorView` instead of `getDecorView` in `SentryGestureListener` to avoid forcing view hierarchy construction ([#5134](https://github.com/getsentry/sentry-java/pull/5134))
3637
- Log an actionable error message when Relay returns HTTP 413 (Content Too Large) ([#5115](https://github.com/getsentry/sentry-java/pull/5115))
3738
- Also switch the client report discard reason for all HTTP 4xx/5xx errors (except 429) from `network_error` to `send_error`
3839
- Trim DSN string before parsing to avoid `URISyntaxException` caused by trailing whitespace ([#5113](https://github.com/getsentry/sentry-java/pull/5113))

sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ void applyScope(final @NotNull IScope scope, final @NotNull ITransaction transac
347347
return null;
348348
}
349349

350-
final View decorView = window.getDecorView();
350+
final View decorView = window.peekDecorView();
351351
if (decorView == null) {
352352
options
353353
.getLogger()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.sentry.android.core.internal.gestures
2+
3+
import android.app.Activity
4+
import android.view.MotionEvent
5+
import androidx.test.ext.junit.runners.AndroidJUnit4
6+
import io.sentry.Breadcrumb
7+
import io.sentry.IScopes
8+
import io.sentry.android.core.SentryAndroidOptions
9+
import io.sentry.util.LazyEvaluator
10+
import kotlin.test.Test
11+
import kotlin.test.assertNull
12+
import org.junit.runner.RunWith
13+
import org.mockito.kotlin.any
14+
import org.mockito.kotlin.anyOrNull
15+
import org.mockito.kotlin.mock
16+
import org.mockito.kotlin.never
17+
import org.mockito.kotlin.verify
18+
import org.robolectric.Robolectric.buildActivity
19+
20+
@RunWith(AndroidJUnit4::class)
21+
class SentryGestureListenerPeekDecorViewTest {
22+
23+
@Test
24+
fun `does not force decor view creation when peekDecorView returns null`() {
25+
// A plain Activity that never calls setContentView — peekDecorView() should return null
26+
val activity = buildActivity(Activity::class.java).create().get()
27+
28+
// Sanity check: decor view has not been created yet
29+
assertNull(activity.window.peekDecorView())
30+
31+
val scopes = mock<IScopes>()
32+
val options =
33+
SentryAndroidOptions().apply {
34+
isEnableUserInteractionBreadcrumbs = true
35+
gestureTargetLocators = listOf(AndroidViewGestureTargetLocator(LazyEvaluator { true }))
36+
dsn = "https://key@sentry.io/proj"
37+
}
38+
39+
val sut = SentryGestureListener(activity, scopes, options)
40+
sut.onSingleTapUp(mock<MotionEvent>())
41+
42+
// The key assertion: peekDecorView is still null — we did not force view hierarchy creation
43+
assertNull(activity.window.peekDecorView())
44+
45+
// And no breadcrumb was captured
46+
verify(scopes, never()).addBreadcrumb(any<Breadcrumb>(), anyOrNull())
47+
}
48+
}

sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/ViewHelpers.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal inline fun <reified T : View> Window.mockDecorView(
2222
finalize: (T) -> Unit = {},
2323
): T {
2424
val view = mockView(id, event, touchWithinBounds, clickable, visible, context, finalize)
25-
whenever(decorView).doReturn(view)
25+
whenever(peekDecorView()).doReturn(view)
2626
return view
2727
}
2828

0 commit comments

Comments
 (0)