构建和使用支持运行时的 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 管理器将返回异常。

模拟程序生成工具会生成辅助类,以将 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 引入了一个名为 SandboxedSdkView 的新 ViewGroup,用于托管由支持运行时的 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 值,才能允许 activity。

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,可用于注册 getOnBackPressedCallback 实例以处理 activity 中的返回按钮行为。


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