Skip to content

Commit 298bfba

Browse files
committed
fix: prevent rare crash in compose click detection
1 parent 8b90313 commit 298bfba

File tree

5 files changed

+12
-38
lines changed

5 files changed

+12
-38
lines changed

embrace-android-compose/src/main/java/io/embrace/android/embracesdk/compose/ComposeActivityListener.kt

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,17 @@ import android.view.Window
66
import io.embrace.android.embracesdk.compose.internal.ComposeInternalErrorLogger
77
import io.embrace.android.embracesdk.compose.internal.EmbraceGestureListener
88
import io.embrace.android.embracesdk.compose.internal.EmbraceWindowCallback
9-
import java.util.concurrent.Executors
10-
import java.util.concurrent.ScheduledExecutorService
11-
import java.util.concurrent.ThreadFactory
129

1310
class ComposeActivityListener : ActivityLifeCycleCallbacks {
1411

15-
private val threadFactory: ThreadFactory = ThreadFactory { runnable: Runnable ->
16-
Executors.defaultThreadFactory().newThread(runnable).apply {
17-
this.name = "emb-compose-scheduled-reg"
18-
}
19-
}
20-
21-
private val service: ScheduledExecutorService =
22-
Executors.newSingleThreadScheduledExecutor(threadFactory)
23-
2412
private val composeInternalErrorLogger = ComposeInternalErrorLogger()
2513

2614
override fun onActivityResumed(activity: Activity) {
2715
try {
2816
// Set EmbraceWindowCallback to install Embrace Gesture Listener to capture onClick events
2917
val window: Window = activity.window
3018
if (window.callback == null || window.callback !is EmbraceWindowCallback) {
31-
val gestureDetectorCompat = GestureDetector(activity, EmbraceGestureListener(activity, service))
19+
val gestureDetectorCompat = GestureDetector(activity, EmbraceGestureListener(activity))
3220
window.callback = EmbraceWindowCallback(
3321
window.callback,
3422
gestureDetectorCompat

embrace-android-compose/src/main/java/io/embrace/android/embracesdk/compose/internal/ComposeClickedTargetIterator.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import android.view.ViewGroup
55
import androidx.compose.ui.platform.ComposeView
66
import java.util.LinkedList
77
import java.util.Queue
8-
import java.util.concurrent.ScheduledExecutorService
98

109
internal class ComposeClickedTargetIterator : EmbraceClickedTargetIterator {
1110

@@ -16,7 +15,6 @@ internal class ComposeClickedTargetIterator : EmbraceClickedTargetIterator {
1615
decorView: View,
1716
x: Float,
1817
y: Float,
19-
onSingleTapUpBackgroundWorker: ScheduledExecutorService,
2018
) {
2119
try {
2220
val queue: Queue<View> = LinkedList()
@@ -32,7 +30,7 @@ internal class ComposeClickedTargetIterator : EmbraceClickedTargetIterator {
3230
}
3331

3432
if (it.parent is ComposeView) { // this validation is to reduce the locate method execution to the proper view
35-
nodeLocator.findClickedElement(it, x, y, onSingleTapUpBackgroundWorker)
33+
nodeLocator.findClickedElement(it, x, y)
3634
}
3735
}
3836
}

embrace-android-compose/src/main/java/io/embrace/android/embracesdk/compose/internal/EmbraceClickedTargetIterator.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.embrace.android.embracesdk.compose.internal
22

33
import android.view.View
4-
import java.util.concurrent.ScheduledExecutorService
54

65
/**
76
* Given a view and a position ( x, y),
@@ -13,6 +12,5 @@ internal interface EmbraceClickedTargetIterator {
1312
decorView: View,
1413
x: Float,
1514
y: Float,
16-
onSingleTapUpBackgroundWorker: ScheduledExecutorService,
1715
)
1816
}

embrace-android-compose/src/main/java/io/embrace/android/embracesdk/compose/internal/EmbraceGestureListener.kt

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,19 @@ import android.view.GestureDetector
55
import android.view.MotionEvent
66
import android.view.View
77
import java.lang.ref.WeakReference
8-
import java.util.concurrent.ScheduledExecutorService
98

109
/**
1110
* EmbraceGestureListener extends SimpleOnGestureListener to listen
1211
* just for onSingleTapUp when the onClick event is triggered
1312
*/
1413
internal class EmbraceGestureListener(
1514
activity: Activity,
16-
private val onSingleTapUpBackgroundWorker: ScheduledExecutorService,
1715
) : GestureDetector.SimpleOnGestureListener() {
1816

19-
private var singleTapUpError: ComposeInternalErrorLogger = ComposeInternalErrorLogger()
20-
private var activityRef: WeakReference<Activity>
21-
17+
private val singleTapUpError: ComposeInternalErrorLogger = ComposeInternalErrorLogger()
18+
private val activityRef: WeakReference<Activity> = WeakReference(activity)
2219
private val composeClickedTargetIterator = ComposeClickedTargetIterator()
2320

24-
init {
25-
activityRef = WeakReference(activity)
26-
}
27-
2821
override fun onSingleTapUp(event: MotionEvent): Boolean {
2922
try {
3023
if (event.actionMasked == MotionEvent.ACTION_UP) {
@@ -42,6 +35,6 @@ internal class EmbraceGestureListener(
4235
}
4336

4437
private fun logTapUp(decorView: View, event: MotionEvent) {
45-
composeClickedTargetIterator.findTarget(decorView, event.x, event.y, onSingleTapUpBackgroundWorker)
38+
composeClickedTargetIterator.findTarget(decorView, event.x, event.y)
4639
}
4740
}

embrace-android-compose/src/main/java/io/embrace/android/embracesdk/compose/internal/EmbraceNodeIterator.kt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import androidx.compose.ui.semantics.SemanticsProperties
1212
import androidx.compose.ui.semantics.getAllSemanticsNodes
1313
import androidx.compose.ui.semantics.getOrNull
1414
import io.embrace.android.embracesdk.internal.EmbraceInternalApi
15-
import java.util.concurrent.ScheduledExecutorService
1615

1716
private const val UNKNOWN_ELEMENT_NAME = "Unlabeled Compose element"
1817

@@ -23,18 +22,16 @@ internal class EmbraceNodeIterator {
2322
* we collect the compose tree and iterate over it to find the clicked view,
2423
* by comparing with the received position (x,y)
2524
* */
26-
fun findClickedElement(root: View, x: Float, y: Float, backgroundWorker: ScheduledExecutorService) {
25+
fun findClickedElement(root: View, x: Float, y: Float) {
2726
val semanticsOwner = if (root is AndroidComposeView) root.semanticsOwner else return
2827
val semanticsNodes = semanticsOwner.getAllSemanticsNodes(true)
2928

30-
backgroundWorker.submit {
31-
findClickedElement(semanticsNodes, x, y)?.let {
32-
val clickedView = ClickedView(it, x, y)
33-
EmbraceInternalApi.getInstance().internalInterface.logComposeTap(
34-
Pair(clickedView.x, clickedView.y),
35-
clickedView.tag
36-
)
37-
}
29+
findClickedElement(semanticsNodes, x, y)?.let {
30+
val clickedView = ClickedView(it, x, y)
31+
EmbraceInternalApi.getInstance().internalInterface.logComposeTap(
32+
Pair(clickedView.x, clickedView.y),
33+
clickedView.tag
34+
)
3835
}
3936
}
4037

0 commit comments

Comments
 (0)