SDK 运行时允许广告 SDK 在沙盒化环境中运行,以防止广告 SDK 访问发布商的视图层次结构。为了展示广告,平台会向 SDK 公开 SandboxedSdkProvider.getView
API 以获取广告视图,然后将其打包为 SurfacePackage
,通过 IPC(进程间通信)发送给客户端应用。这样做有几个缺点,下文将对此进行讨论。本文档随后将介绍一个提议的 Jetpack 库,该库是为解决这些难题而构建的。
扩充平台 API 的理由
这些框架 API 专为实现灵活性而设计,在其间构建边信道用于界面呈现的任务则由应用和 SDK 完成。这类边信道会执行以下操作:
- 让 SDK 在其生命周期内管理多个广告视图,并了解在 SDK 创建广告界面后,广告界面会发生什么变化。
- 将视图创建和内容绑定分离开来。使用边信道后,SDK 可以向应用返回与广告请求对应的对象(内容),在应用认为合适时,就可将该对象绑定到广告容器。
- 对用于跨进程显示界面的底层平台结构进行抽象化处理。(平台目前使用
SurfaceControlViewhost
并据此生成SurfacePackage
。) - 可让 SDK 运行时中的广告 SDK 在广告容器的界面发生更改时自动接收通知。如果发布商更改了广告容器的布局,除非发布商明确调用 API 来通知 SDK,否则 SDK 不会发现这些更改。
- 同步广告界面和广告容器的大小调整,不会出现任何用户可见的卡顿。
- 自动管理向后兼容性。
SurfacePackage
不适用于 API 级别 30 之前的版本。此外,在没有 SDK 运行时且 SDK 对于发布商来说是本地进程的设备上,当可以直接通过 SDK 获取视图时,为广告创建SurfacePackage
是一种浪费。边信道会将 SDK 和应用开发者代码中的这种复杂性进行抽象化处理。 - 可让广告界面与可组合项无缝集成。不使用视图的 Jetpack Compose 开发者也可以继续托管由仍在使用视图的 SDK 开发者生成的界面。
界面库
界面库对上文详述的复杂性进行抽象化处理,为发布商和 SDK 提供边信道用于显示跨进程界面,并会在用户与界面和设备互动时及时更新界面。
三个界面库分别是:核心库、客户端库和提供方库。核心库提供客户端库和提供方库使用的接口。界面提供方(通常是 SDK)依赖于提供方库,界面的使用方(通常是发布商)依赖于客户端库。这些客户端库和提供方库共同构成了创建和维护界面会话所需的边信道。
API
用于 SDK 运行时界面呈现的 API 如下所示:
SandboxedUiAdapter
:由 SDK 创建,用于获取要在发布商的界面中展示的内容。
SandboxedSdkView
:由发布商创建,是一个容器,用于存放通过 SandboxedUiAdapter
获取的内容。
Session
:在响应 SandboxedUiAdapter.openSession()
时由 SDK 创建,代表一个界面会话调用。此 API 构成了 SDK 与发布商之间通信隧道的 SDK 端,并会在 SandboxedSdkView
发生更改(例如窗口分离、调整大小或更改配置)时接收相关通知。
SessionClient
:由客户端库创建,此 API 构成了 SDK 和发布商之间通信隧道的发布商端。
SandboxedSdkUiSessionStateChangedListener
:由发布商创建。一个监听器,用于监听与 SandboxedSdkView
关联的界面会话的状态更改。
如需详细了解这些 API,请参阅 privacysandbox-ui 参考文档。
控制流
以下示意图显示了不同场景中客户端与提供方界面库的交互:
上图显示了发布商如何创建 SandboxedSdkView
以编程方式或通过 XML 将其附加到 SdkSandboxUiAdapter
从 SDK 获取。如需观察所有界面状态更改,发布商应在附加 SdkSandboxUiAdapter
之前将 SandboxedSdkUiSessionStateChangedListener
添加到 SandboxedSdkView
。
此图显示了如果发布商的 activity 处理配置更改,
客户端库负责将配置更改转发到 SDK,
以便相应地更新界面例如,当用户旋转设备并且发布商在其 activity 中通过设置 android:configChanges=["orientation"]
声明处理配置更改时,就会触发此流程。
此图展示了 SDK 如何对 SessionClient
调用方法以请求对广告容器进行更改。当 SDK 想要调整广告大小并需要发布商调整广告容器的大小以适应新的尺寸时,就会触发此 API。这种情况可能会在响应用户互动时发生,例如 mraid.resize()
。
此图显示了在 SandboxedSdkView
分离时如何关闭会话
从窗口中打开SDK 还可以通过调用 SessionClient.onSessionError()
随时(例如,当用户失去网络连接时)关闭会话。
Z 顺序
客户端界面库在内部使用 SurfaceView
来托管 SDK 的界面。SurfaceView
可以使用 Z 顺序,在发布商的窗口上方或下方显示 SDK 的界面。此过程由 SandboxedSdkView.orderProviderUiAboveClientUi()
方法控制,该方法接受布尔值 setOnTop
。
当 setOnTop
为 true
时,SandboxedSdkView
上的每个 android.view.MotionEvent
都会发送到 SDK。当 false
时,这些信息会发送给发布商。默认情况下,动作事件会发送到 SDK。
发布商通常不需要更改广告视图的默认 Z 顺序。但是,在显示会遮盖广告的界面(例如下拉菜单)时,应暂时将 Z 顺序的默认顺序颠倒过来,待遮盖界面的元素关闭后再恢复默认顺序。我们仍在探索各种方法,希望能在客户端界面库中自动完成此过程。
滚动
当广告界面按 Z-above 顺序显示在发布商窗口上方时,广告界面中的 MotionEvents
会发送到 SDK。在广告界面上发起的滚动和快速滑动手势会得到特殊处理:
- 垂直滚动和快速滑动手势会发送到发布商的容器并由容器进行处理。如果放置广告界面的发布商容器可以垂直滚动,这种处理可提供良好的用户体验。此过程不需要 SDK 或发布商方面进行任何额外工作。
- 水平滚动和快速滑动手势会发送到 SDK 并由 SDK 进行处理。如果广告界面本身可以水平滚动(例如广告轮播界面),这种处理可提供良好的用户体验。
实现指南
SDK 应实现以下内容:
SandboxedUiAdapter
:在响应 SDK 定义的 API(例如loadAd
)时,系统会将此实现返回给发布商。应使用此实现的openSession()
方法向 SDK 服务器发出广告请求,并为该请求准备广告视图。Session**
:在响应SandboxedUiAdapter.openSession
通话。它为客户端库提供了一种获取广告界面的方法,并会通知 SDK 此 API 发生了更改。全部 应在此处实现Session
方法。
发布商应执行以下操作:
- 通过 XML 或以程序化方式创建
SandboxedSdkView
。 - 将
SandboxedSdkUiSessionStateChangedListener
附加到SandboxedSdkView
,以观察界面的变化。 - 将 SDK 提供的
SandboxedUiAdapter
附加到SandboxedSdkView
。 - 像往常一样将
SandboxedSdkView
添加到该窗口中,并让客户端库通过 SDK 创建和维护界面会话。 - 在适当的时间对
SandboxedSdkUiSessionChangedListener
报告的状态变化做出回应。例如,如果 SDK 意外关闭会话,发布商可以将SandboxedSdkView
替换为静态图片,或将其从视图层次结构中移除。 - 在进行可能会覆盖广告界面的过渡(例如下拉菜单)时,暂时将
orderProviderUiAboveClientUi
设为 false,以便将广告界面放置在发布商窗口下方。关闭下拉菜单后,再将orderProviderUiAboveClientUi
设置为true
。
平台 API 的未来
界面库进入 Beta 版阶段后,我们计划废弃与界面呈现相关的 SDK 运行时平台 API,即 SdkSandboxManager.requestSurfacePackage()
和 SandbxedSdkProvider.getView()
。
开放性问题
- 是否还有界面库应自动处理的更常见的广告界面用例?
- 您使用哪些界面框架来展示广告界面,您预计在将界面库与这些框架集成时是否会出现问题?
- 对您来说,放置在可滚动发布商容器中的可滚动广告界面是否是常见用例?在这种情况下,广告界面和容器的滚动方向是什么?当用户在广告界面上发起滚动时,您希望呈现什么行为?