From 433db9063fee97511a4295f787145239b66b0bd6 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:47:07 +0100 Subject: [PATCH] fix: touches fall back to single touches if out of bounds (#221) --- CHANGELOG.md | 2 + .../replay/PostHogReplayIntegration.kt | 52 ++++++++++++------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b9b9ed..13788014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Next +- fix: touches fall back to single touches if out of bounds ([#221](https://github.com/PostHog/posthog-android/pull/221)) + ## 3.11.1 - 2025-01-30 - fix: do not allow default integrations multiple times ([#219](https://github.com/PostHog/posthog-android/pull/219)) diff --git a/posthog-android/src/main/java/com/posthog/android/replay/PostHogReplayIntegration.kt b/posthog-android/src/main/java/com/posthog/android/replay/PostHogReplayIntegration.kt index 75eaeba4..0d58c4e9 100644 --- a/posthog-android/src/main/java/com/posthog/android/replay/PostHogReplayIntegration.kt +++ b/posthog-android/src/main/java/com/posthog/android/replay/PostHogReplayIntegration.kt @@ -261,20 +261,24 @@ public class PostHogReplayIntegration( ) { val mouseInteractions = mutableListOf() for (index in 0 until motionEvent.pointerCount) { - // if the id is 0, BE transformer will set it to the virtual bodyId - val id = motionEvent.getPointerId(index) - val absX = motionEvent.getRawXCompat(index).toInt().densityValue(displayMetrics.density) - val absY = motionEvent.getRawYCompat(index).toInt().densityValue(displayMetrics.density) - - val mouseInteractionData = - RRIncrementalMouseInteractionData( - id = id, - type = type, - x = absX, - y = absY, - ) - val mouseInteraction = RRIncrementalMouseInteractionEvent(mouseInteractionData, timestamp) - mouseInteractions.add(mouseInteraction) + try { + // if the id is 0, BE transformer will set it to the virtual bodyId + val id = motionEvent.getPointerId(index) + val absX = motionEvent.getRawXCompat(index).toInt().densityValue(displayMetrics.density) + val absY = motionEvent.getRawYCompat(index).toInt().densityValue(displayMetrics.density) + + val mouseInteractionData = + RRIncrementalMouseInteractionData( + id = id, + type = type, + x = absX, + y = absY, + ) + val mouseInteraction = RRIncrementalMouseInteractionEvent(mouseInteractionData, timestamp) + mouseInteractions.add(mouseInteraction) + } catch (e: Throwable) { + config.logger.log("Reading MotionEvent pointers failed: $e.") + } } if (mouseInteractions.isNotEmpty()) { @@ -1237,18 +1241,26 @@ public class PostHogReplayIntegration( } private fun MotionEvent.getRawXCompat(index: Int): Float { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - getRawX(index) + return if (index < 0 || index >= pointerCount) { + rawX // Fallback to single-touch `rawX` to prevent crashes } else { - rawX + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + getRawX(index) + } else { + rawX + } } } private fun MotionEvent.getRawYCompat(index: Int): Float { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - getRawY(index) + return if (index < 0 || index >= pointerCount) { + rawY // Fallback to single-touch `rawY` to prevent crashes } else { - rawY + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + getRawY(index) + } else { + rawY + } } }