Skip to content

Commit ae1cec9

Browse files
authored
Merge 92de082 into 41fa056
2 parents 41fa056 + 92de082 commit ae1cec9

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
### Fixes
3232

3333
- Fix crash when unregistering `SystemEventsBroadcastReceiver` with try-catch block. ([#5106](https://github.com/getsentry/sentry-java/pull/5106))
34+
- Use `peekDecorView` instead of `getDecorView` in `SentryGestureListener` to avoid forcing view hierarchy construction ([#5134](https://github.com/getsentry/sentry-java/pull/5134))
3435

3536
### Dependencies
3637

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)