构建和使用支持运行时的 SDK

1
Key concepts
2
Set up your development environment
3
Build an RE SDK
4
Consume the RE SDK
5
Testing, and building for distribution

使用支持运行时的 SDK

本部分介绍了客户端如何与已声明的启用运行时 (RE) 的 SDK API 进行交互。

在本指南中,我们将现有 SDK 模块(或运行时感知型 SDK)称为客户端。

如果您想将启用运行时的 SDK 直接集成到应用中,则应用模块是客户端。

加载支持运行时的 SDK

在运行时感知型 SDK 或客户端应用中,您首先要做的就是加载已启用运行时的 SDK。

SdkSandboxManager 类有助于加载启用了运行时的 SDK,并返回一个 IBinder 类,该类可供支持运行时的 SDK 绑定到启用了运行时的 SDK 中声明的接口。

您需要确保每个启用运行时的 SDK 只加载一次,否则 SDK 管理器会返回异常。

shim 生成工具会生成帮助程序类,以将 SdkSandboxManager 返回的 IBinder 接口转换回声明的 SDK API 接口。

这些工具使用带有 @PrivacySandboxService 注释的接口来生成 *Factory 类。

此类包含一个静态 wrapTo* 函数,用于将 IBinder 对象转换为支持运行时的 SDK 接口的实例。

您的运行时感知型 SDK 可以使用此接口与启用了运行时的 SDK 进行通信,并调用您在上一步中声明的 SDK API。

// Name of the SDK to be loaded, defined in your ASB module
private const val SDK_NAME = "com.example.sdk"

try {
    // SdkSandboxManagerCompat is used to communicate with the sandbox and load SDKs with backward compatibility.
    val sandboxManagerCompat = SdkSandboxManagerCompat.from(context)
    val sandboxedSdk = sandboxManagerCompat.loadSdk(SDK_NAME, Bundle.EMPTY)
    val mySdk = MySdkFactory.wrapToMySdk(sandboxedSdk.getInterface()!!)
} catch (e: LoadSdkCompatException) {
    Log.e(TAG, "Failed to load SDK, error code: ${e.loadSdkErrorCode}", e)
    return null
}

界面库使用情况

如果您想使用界面库来展示广告,请确保已将 androidx.privacysandbox.ui:ui-coreandroidx.privacysandbox.ui:ui-client 添加到运行时感知型 SDK 的 build.gradle 中的依赖项中。

使用 SandboxedSdkView 加载横幅广告

androidx.privacysandbox.ui:ui-client 引入了一个新的 ViewGroup,称为 SandboxedSdkView,用于托管由支持运行时的 SDK 创建的界面。

setAdapter() 打开与启用运行时的 SDK 的会话,以接收广告视图和界面更改通知。当 SDK 打开会话时,系统会展示广告。

可以按如下方式集成:

class BannerAd(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
    suspend fun loadAd() {
        // mySdk is the previously loaded SDK in the SDK Runtime.
        val bannerAd = mySdk.loadAd()
        val sandboxedSdkView = SandboxedSdkView(context)
        addViewToLayout(sandboxedSdkView)

        // This renders the ad.
        sandboxedSdkView.setAdapter(bannerAd)
        return
    }
    private fun addViewToLayout(view: View) {
        view.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        super.addView(view)
    }
}

当界面展示的会话状态发生变化时,运行时感知型 SDK 也可以收到通知。具体操作步骤如下:

  1. 创建一个 SessionStateChangeListener() 类来处理不同的场景:

    private class SessionStateChangeListener() : SandboxedSdkUiSessionStateChangedListener {
        override fun onStateChanged(state: SandboxedSdkUiSessionState) {
            if (state is SandboxedSdkUiSessionState.Error) {
            // Some error has occurred while opening the session. Handle
            // accordingly.
            Log.e(TAG, state.throwable.message!!);
            } else if (state is SandboxedSdkUiSessionState.Loading) {
                // The session is attempting to be opened.
            } else if (state is SandboxedSdkUiSessionState.Active) {
                // The session is open and the UI presentation was successful.
            } else if (state is SandboxedSdkUiSessionState.Idle) {
                // There is no open session.
            }
        }
    }
    
  2. 向您之前实例化的 SandboxedSdkView 添加状态变化监听器。监听器附加到视图后,系统会立即使用当前状态调用该监听器。

请注意以下几点:

  • 如果运行时感知 SDK 在会话尚未完成打开时调用 SandboxedSdkView 方法,则所有效果将在会话完成打开后应用。
    • 方法,例如 SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop)
  • 不支持调用用于从 SandboxedSdkView 添加或移除视图的方法(例如 addView()removeView()removeViewAt() 等),否则会抛出 UnsupportedOperationException
    • 使用 setAdapter() 来展示广告。
  • SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop) 会切换 Z 顺序,从而影响用户互动产生的 MotionEvents 是发送到支持运行时的 SDK 还是感知运行时的 SDK。

开始活动

如需启动由启用运行时的 SDK 拥有的 activity,请使用 createSdkActivityLauncher 扩展程序在运行时感知型 SDK 中创建启动器。

然后,您可以将此启动器传递给已启用运行时的 SDK,使其能够根据需要启动 activity。

您可以使用谓词来控制是否启动 activity。 谓词需要返回 true 值,才能允许活动。

val launchSdkActivityPredicate = {
    // Boolean which has to be true to launch the activities
    }
val launcher = baseActivity.createSdkActivityLauncher(launchSdkActivityPredicate)
fullscreenService.showActivity(launcher)

在支持运行时的 SDK 中,注册 SdkSandboxActivityHandlerCompat 并将其提供给 SdkActivityLauncher.LaunchSdkActivity(IBinder)

fun showActivity(activityLauncher: SdkActivityLauncher) {
    val handler = object : SdkSandboxActivityHandlerCompat {
        override fun onActivityCreated(activityHolder: ActivityHolder) {
            activityHolder.getActivity().setContentView(contentView)
        }
    }

    val token = controller.registerSdkSandboxActivityHandler(handler)
    activityLauncher.launchSdkActivity(token)
}

传递给 SdkSandboxActivityHandlerCompat.onActivityCreated(ActivityHolder)ActivityHolder 会实现 LifecycleOwner,从而让支持运行时的 SDK 能够访问 activity 的生命周期。

它还提供 getOnBackPressedDispatcher API,该 API 可用于注册 getOnBackPressedCallback 实例,以处理 activity 内的返回按钮行为。


第 3 步:构建启用运行时的 SDK 第 5 步:测试和构建以进行分发