v0.3.2 — fix overlay crash on first show

v0.3.1 introduced TouchInterceptor (a FrameLayout wrapping the
ComposeView) so we could intercept touches before the inner MapView
saw ACTION_DOWN. That made the wrapper the window-root view (the
View actually attached to WindowManager) but I left the
ViewTreeLifecycleOwner / ViewTreeSavedStateRegistryOwner tags on
the inner ComposeView.

Compose's WindowRecomposer.create looks up findViewTreeLifecycleOwner
on the window-root, not on the inner ComposeView. With the tag
missing on the wrapper, Compose throws IllegalStateException at
composition startup — service crash on overlay enable.

Fix: move setViewTreeLifecycleOwner + setViewTreeSavedStateRegistryOwner
to the wrapper. v0.3.0 worked because the ComposeView itself was the
window-root then; the same pattern (owners on whatever's attached
directly to WindowManager) holds here.
This commit is contained in:
2026-05-07 23:52:57 -04:00
parent eb26def14b
commit fc67d3d203
2 changed files with 9 additions and 4 deletions
+2 -2
View File
@@ -12,8 +12,8 @@ android {
applicationId = "org.soulstone.overwatch" applicationId = "org.soulstone.overwatch"
minSdk = 26 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 13 versionCode = 14
versionName = "0.3.1" versionName = "0.3.2"
} }
buildTypes { buildTypes {
@@ -92,12 +92,17 @@ class OverlayManager(
val newOwner = OverlayOwner() val newOwner = OverlayOwner()
val composeView = ComposeView(context).apply { val composeView = ComposeView(context).apply {
setViewTreeLifecycleOwner(newOwner)
setViewTreeSavedStateRegistryOwner(newOwner)
setContent { OverlayBubble() } setContent { OverlayBubble() }
} }
// Wrap so we can intercept *before* MapView's own touch handling. // Wrap so we can intercept *before* MapView's own touch handling.
// Compose's WindowRecomposer reads findViewTreeLifecycleOwner from
// the *window-root* view (= the wrapper here, since it's what's
// attached to WindowManager). Setting the owner only on the inner
// ComposeView throws IllegalStateException at composition startup —
// that was the v0.3.1 crash.
val wrapper = TouchInterceptor(context).apply { val wrapper = TouchInterceptor(context).apply {
setViewTreeLifecycleOwner(newOwner)
setViewTreeSavedStateRegistryOwner(newOwner)
addView( addView(
composeView, composeView,
FrameLayout.LayoutParams( FrameLayout.LayoutParams(