fix: upgrade privacysandbox.ui to alpha17 (embedded drag/scroll input)

The embedded surface forwarding taps but cancelling drags was a known bug in
androidx.privacysandbox.ui alpha10: with the provider surface z-ordered above,
"the gesture is exclusively received by the provider window and not transferred
to the client window" (alpha13 release notes). alpha15 then "set the default
Z-ordering to below" and "added support for the UI provider to receive
MotionEvents in this mode after being received by the client window" — i.e. the
drag-input path we needed.

Bump alpha10 → alpha17 and adapt the changed API: openSession takes SessionData
instead of a windowInputToken IBinder, Session adds notifySessionRendered, and
the session-state listener became setEventListener(SandboxedSdkViewEventListener)
(ready now flips on onUiDisplayed). The direct-WebView browser is unaffected
(it doesn't use this library).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgMpRcWj6y82LxLiwcuzmN
This commit is contained in:
Claude
2026-06-23 23:16:02 +00:00
parent 1531f3baad
commit 90150e72e4
5 changed files with 29 additions and 19 deletions
@@ -35,9 +35,8 @@ import androidx.annotation.RequiresApi
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.privacysandbox.ui.client.SandboxedUiAdapterFactory
import androidx.privacysandbox.ui.client.view.SandboxedSdkUiSessionState
import androidx.privacysandbox.ui.client.view.SandboxedSdkUiSessionStateChangedListener
import androidx.privacysandbox.ui.client.view.SandboxedSdkView
import androidx.privacysandbox.ui.client.view.SandboxedSdkViewEventListener
import androidx.privacysandbox.ui.core.SandboxedUiAdapter
import com.vitorpamplona.amethyst.napplethost.NappletBrowserContract
import com.vitorpamplona.amethyst.ui.screen.loggedIn.embed.EmbeddedSurfaceController
@@ -105,12 +104,16 @@ class EmbeddedBrowserController(
// Paint the surface placeholder in the app's theme background so there's no white flash before
// the remote WebView delivers its first frame.
view.setBackgroundColor(backgroundColor)
// Flip ready once the session opens, so callers can drop their loading placeholder.
view.addStateChangedListener(
object : SandboxedSdkUiSessionStateChangedListener {
override fun onStateChanged(state: SandboxedSdkUiSessionState) {
if (state is SandboxedSdkUiSessionState.Active) readyState.value = true
// Flip ready once the remote UI is displayed, so callers can drop their loading placeholder.
view.setEventListener(
object : SandboxedSdkViewEventListener {
override fun onUiDisplayed() {
readyState.value = true
}
override fun onUiError(error: Throwable) {}
override fun onUiClosed() {}
},
)
pendingAdapter?.let {
@@ -35,9 +35,8 @@ import androidx.annotation.RequiresApi
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.privacysandbox.ui.client.SandboxedUiAdapterFactory
import androidx.privacysandbox.ui.client.view.SandboxedSdkUiSessionState
import androidx.privacysandbox.ui.client.view.SandboxedSdkUiSessionStateChangedListener
import androidx.privacysandbox.ui.client.view.SandboxedSdkView
import androidx.privacysandbox.ui.client.view.SandboxedSdkViewEventListener
import androidx.privacysandbox.ui.core.SandboxedUiAdapter
import com.vitorpamplona.amethyst.napplethost.NappletEmbedContract
import com.vitorpamplona.amethyst.napplethost.NappletHostContract
@@ -106,12 +105,16 @@ class EmbeddedNappletController(
// Paint the surface placeholder in the app's theme background so there's no white flash before
// the remote WebView delivers its first frame.
view.setBackgroundColor(params.getInt(NappletHostContract.EXTRA_BG_COLOR, android.graphics.Color.WHITE))
// Flip ready once the session opens, so callers can drop their loading placeholder.
view.addStateChangedListener(
object : SandboxedSdkUiSessionStateChangedListener {
override fun onStateChanged(state: SandboxedSdkUiSessionState) {
if (state is SandboxedSdkUiSessionState.Active) readyState.value = true
// Flip ready once the remote UI is displayed, so callers can drop their loading placeholder.
view.setEventListener(
object : SandboxedSdkViewEventListener {
override fun onUiDisplayed() {
readyState.value = true
}
override fun onUiError(error: Throwable) {}
override fun onUiClosed() {}
},
)
pendingAdapter?.let {
+1 -1
View File
@@ -78,7 +78,7 @@ zxing = "3.5.4"
zxingAndroidEmbedded = "4.3.0"
webkit = "1.12.1"
# Cross-process UI embedding (SurfaceControlViewHost wrapper) for the in-app browser surface. Apache-2.0.
privacysandboxUi = "1.0.0-alpha10"
privacysandboxUi = "1.0.0-alpha17"
windowCoreAndroid = "1.5.1"
workRuntime = "2.11.2"
androidxCamera = "1.6.1"
@@ -25,13 +25,13 @@ import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.view.View
import android.webkit.WebView
import android.widget.FrameLayout
import androidx.annotation.RequiresApi
import androidx.privacysandbox.ui.core.SandboxedUiAdapter
import androidx.privacysandbox.ui.core.SessionData
import androidx.privacysandbox.ui.provider.AbstractSandboxedUiAdapter
import java.util.concurrent.Executor
@@ -48,7 +48,7 @@ class NappletBrowserUiAdapter(
override fun openSession(
context: Context,
windowInputToken: IBinder,
sessionData: SessionData,
initialWidth: Int,
initialHeight: Int,
isZOrderOnTop: Boolean,
@@ -79,6 +79,8 @@ private class BrowserSession(
override val signalOptions: Set<String> = emptySet()
override fun notifySessionRendered(supportedSignalOptions: Set<String>) {}
override fun notifyResized(
width: Int,
height: Int,
@@ -25,13 +25,13 @@ import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.view.View
import android.webkit.WebView
import android.widget.FrameLayout
import androidx.annotation.RequiresApi
import androidx.privacysandbox.ui.core.SandboxedUiAdapter
import androidx.privacysandbox.ui.core.SessionData
import androidx.privacysandbox.ui.provider.AbstractSandboxedUiAdapter
import java.util.concurrent.Executor
@@ -49,7 +49,7 @@ class NappletHostUiAdapter(
override fun openSession(
context: Context,
windowInputToken: IBinder,
sessionData: SessionData,
initialWidth: Int,
initialHeight: Int,
isZOrderOnTop: Boolean,
@@ -80,6 +80,8 @@ private class HostSession(
override val signalOptions: Set<String> = emptySet()
override fun notifySessionRendered(supportedSignalOptions: Set<String>) {}
override fun notifyResized(
width: Int,
height: Int,