Skip to content

ToBid 自定义接入优聚智汇 SDK

概述

本文档指导开发者将优聚智汇 SDK 以**自定义广告网络(Custom Adapter)**形式接入 ToBid(Sigmob WindMill)聚合平台。

接入模式

优聚 SDK 作为 ToBid 的自定义广告网络接入,采用反向集成模式:

  • 优聚 SDK 的初始化由 ToBid 自动触发
  • 广告加载由 ToBid 调用适配器 loadAd 方法发起
  • 广告竞价采用 C2S(Client-to-Server)模式,价格由适配器回传给 ToBid
  • 开发者无需单独调用 UjuAdSdk.init / UjuAdSdk.start

支持的广告类型

广告类型AndroidiOS(未正式上线)
开屏广告(Splash)
激励视频(Rewarded Video)
插屏广告(Interstitial)
原生广告(Native)
横幅广告(Banner)

支持的平台说明

Android 端已适配

iOS 端未正式上线

前期对接接入以安卓端优先接入验证


Android 接入指南

1. 引入依赖

1.1 引入 ToBid SDK

ToBid SDK(WindMill SDK)以本地 AAR 方式引入,请将以下文件放置到 app/libs/ 目录:

app/libs/
├── windmill-sdk-4.3.11.aar       # ToBid 聚合 SDK
├── wind-sdk-4.19.8.aar           # WindMill 基础库
├── wind-common-1.7.6.aar         # WindMill 通用库
└── oaid_sdk_1.0.25.aar           # OAID 标识库

1.2 引入优聚 ToBid 适配器模块

settings.gradle.kts 中引入适配器模块:

kotlin
// settings.gradle.kts
include(":olib_tobid_adapter")

app/build.gradle 中添加依赖:

groovy
// app/build.gradle
dependencies {
    // ToBid SDK(本地 AAR)
    implementation(files("libs/windmill-sdk-4.3.11.aar"))
    implementation(files("libs/wind-sdk-4.19.8.aar"))
    implementation(files("libs/wind-common-1.7.6.aar"))
    implementation(files("libs/oaid_sdk_1.0.25.aar"))

    // 优聚 ToBid 适配器
    implementation(project(":olib_tobid_adapter"))
}

1.3 适配器模块说明

适配器模块 olib_tobid_adapter 的核心依赖以 compileOnly 方式引入(由宿主 APP 提供):

kotlin
// olib_tobid_adapter/build.gradle.kts
dependencies {
    compileOnly(project(":ad_core"))                    // 优聚核心 SDK
    compileOnly(project(":ad_adx"))                     // 优聚 ADX 模块
    compileOnly(files("libs/windmill-sdk-4.3.11.aar"))  // ToBid SDK
}

compileOnly 说明

适配器模块对 ad_coread_adxwindmill-sdk 使用 compileOnly,意味着这些依赖由宿主 APP 统一提供版本。请确保宿主 APP 已引入对应依赖。

2. 初始化 ToBid 聚合 SDK

Application.onCreate() 中初始化 ToBid(WindMill)SDK:

kotlin
// MyApplication.kt
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        initToBidSdk()
    }

    private fun initToBidSdk() {
        val ads = WindMillAd.sharedAds()
        // 设置成年人状态与个性化广告
        ads.setAdult(true)
        ads.setPersonalizedAdvertisingOn(true)
        // 开发发阶段开启调试日志
        ads.setDebugEnable(true)

        // 监听各 ADN 初始化状态(可选)
        ads.setNetworkInitListener { networkName, isSuccess ->
            Log.d("ToBid", "ADN 初始化: $networkName, success=$isSuccess")
        }

        // 启动 ToBid SDK
        ads.startWithAppId(this, TOBID_APP_ID, object : WindMillAd.InitListener {
            override fun onSuccess() {
                Log.d("ToBid", "ToBid SDK 启动成功")
            }

            override fun onError(error: WindMillError?) {
                Log.e("ToBid", "ToBid SDK 启动失败: ${error?.message}")
            }
        })
    }

    companion object {
        // ToBid 后台分配的 App ID
        private const val TOBID_APP_ID = "YOUR_TOBID_APP_ID"
    }
}

优聚 SDK 自动初始化

ToBid SDK 启动后,会自动发现并调用优聚 ToBid 适配器的初始化方法,自动触发优聚 SDK 的 init + start 流程。开发者无需单独调用 UjuAdSdk.init()UjuAdSdk.start()

3. ToBid 后台配置

3.1 添加自定义广告网络

在 ToBid 后台添加自定义广告网络,配置 ADN 级别的 CustomInfo(JSON 格式):

json
{
    "appId": "YOUR_UJU_APP_ID",
    "appKey": "YOUR_UJU_APP_KEY",
    "channel": "tobid1"
}
字段类型必填说明
appIdString优聚智慧后台分配的应用 ID
appKeyString优聚智汇后台分配的 RSA 公钥,原样传入
channelString渠道标识,用于数据统计与分账

3.2 配置广告位

在 ToBid 后台为每个广告位配置 CustomInfo(JSON 格式):

json
{
    "placementId": "YOUR_UJU_PLACEMENT_ID"
}
字段类型必填说明
placementIdString优聚智汇后台分配的广告位 ID

3.3 配置示例

假设优聚后台分配的信息如下:

  • App ID: a6a4ccd79a067a
  • App Key: MIIBI...(RSA 公钥)
  • 渠道: tobid1
  • 开屏广告位 ID: 3516343733169009

则 ToBid 后台配置为:

ADN 级别 CustomInfo

json
{"appId":"a6a4ccd79a067a","appKey":"MIIBI...","channel":"tobid1"}

开屏广告位 CustomInfo

json
{"placementId":"3516343733169009"}

4. 加载广告

ToBid 后台配置完成后,使用 ToBid 标准 API 加载广告。以下以开屏广告为例:

kotlin
// SplashAdActivity.kt
class SplashAdActivity : AppCompatActivity() {

    private lateinit var splashAd: WMSplashAd

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        val adContainer = findViewById<ViewGroup>(R.id.splash_ad_container)

        // 创建 ToBid 开屏广告对象
        splashAd = WMSplashAd(this)

        // 加载并展示开屏广告
        splashAd.loadAdAndShow(
            adContainer,
            TOBID_SPLASH_PLACEMENT_ID,  // ToBid 后台广告位 ID
            object : WMSplashAd.SplashAdLoadListener {
                override fun splashAdLoadSuccess() {
                    Log.d("ToBid", "开屏广告加载成功")
                }

                override fun splashAdLoadFail(error: WindMillError?) {
                    Log.e("ToBid", "开屏广告加载失败: ${error?.message}")
                    // 加载失败,跳转到主页
                    gotoMainActivity()
                }

                override fun splashAdShowSuccess() {
                    Log.d("ToBid", "开屏广告展示成功")
                }

                override fun splashAdShowFail(error: WindMillError?) {
                    Log.e("ToBid", "开屏广告展示失败: ${error?.message}")
                    gotoMainActivity()
                }

                override fun splashAdClicked() {
                    Log.d("ToBid", "开屏广告被点击")
                }

                override fun splashAdClosed() {
                    Log.d("ToBid", "开屏广告关闭")
                    gotoMainActivity()
                }
            }
        )
    }

    private fun gotoMainActivity() {
        startActivity(Intent(this, MainActivity::class.java))
        finish()
    }

    companion object {
        // ToBid 后台分配的开屏广告位 ID
        private const val TOBID_SPLASH_PLACEMENT_ID = "YOUR_TOBID_SPLASH_PLACEMENT_ID"
    }
}

其他广告类型

激励视频、插屏、原生广告的加载方式请参考 ToBid 官方文档。优聚适配器会自动处理广告加载、展示、竞价等逻辑。

5. ProGuard 混淆配置

proguard-rules.pro 中添加以下规则:

groovy
# 优聚 ToBid 适配器(反射调用,不可混淆)
-keep class com.ujusdk.tobid.** { *; }

# ToBid WindMill SDK
-keep class com.windmill.sdk.custom.** { *; }
-keep class com.windmill.sdk.models.** { *; }
-keep class com.windmill.sdk.natives.** { *; }
-keep class com.windmill.sdk.base.** { *; }
-keep class com.windmill.sdk.WMConstants { *; }
-keep class com.windmill.sdk.WindMillError { *; }

6. Android 适配器架构

适配器架构说明(选读)

优聚 ToBid 适配器位于 olib_tobid_adapter 模块,包含以下核心组件:

  • 初始化代理:接收 ToBid 的初始化调用,解析 CustomInfo 并触发优聚 SDK 初始化
  • 各广告类型适配器:开屏、激励视频、插屏、原生广告各一个适配器类,继承 ToBid 对应的 Custom Adapter 基类
  • 初始化状态追踪:单例模式追踪优聚 SDK 初始化状态,确保广告加载在初始化完成后才执行
  • 配置解析器:解析 ToBid 后台下发的 CustomInfo JSON 配置

适配器对 ad_coread_adxwindmill-sdk 使用 compileOnly 依赖,由宿主 APP 统一提供版本。竞价结果由优聚 SDK 内部自动处理,开发者无需手动上报。


iOS 接入指南

1. 引入依赖

1.1 引入 ToBid 适配器 Package

在 Xcode 中通过 SPM 引入优聚 ToBid 适配器:

swift
// Package.swift 或 Xcode SPM 依赖
.package(path: "path/to/ios/Adapters/ToBidAdapter")

或直接在 Xcode 中:File → Add Packages → Add Local → 选择 ToBidAdapter 目录

适配器依赖关系:

  • ToBidAdapter → 依赖 UjuAdSdk(优聚核心 SDK)
  • WindMillSDK 由宿主 APP 引入(适配器不硬依赖)

1.2 引入 WindMillSDK

按照 ToBid 官方文档引入 WindMillSDK(CocoaPods 或 SPM)。适配器在编译期不依赖 WindMillSDK,通过 ObjC 运行时动态调用 bridge 回调。

2. 防止 dead-strip(关键)

AppDelegate 中调用 ensureLinked(),防止链接器将适配器代码优化掉:

swift
// AppDelegate.swift
import ToBidAdapter
import WindMillAd  // ToBid SDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // 关键:防止 ToBidAdapter 被 dead-strip
        _ = ToBidAdapter.ensureLinked()

        // 初始化 ToBid SDK
        WindMillAd.sharedAds().startWithAppId("YOUR_TOBID_APP_ID") { success, error in
            if success {
                print("ToBid SDK 启动成功")
            } else {
                print("ToBid SDK 启动失败: \(error?.localizedDescription ?? "")")
            }
        }

        return true
    }
}

ensureLinked 必须调用

iOS 端的 ToBid 适配器采用反向集成模式,不通过 register() 注册。如果不调用 ensureLinked(),链接器可能会将适配器代码优化掉(dead-strip),导致 ToBid 无法发现适配器,广告加载会失败。

3. ToBid 后台配置

iOS 的 ToBid 后台配置与 Android 后台配置完全一致,包括 ADN 级别和广告位级别的 CustomInfo

4. 加载广告

使用 ToBid 标准 API 加载广告。以下以激励视频为例:

swift
// ToBidRewardAdViewController.swift
import WindMillAd

class ToBidRewardAdViewController: UIViewController {

    private var rewardAd: WMRewardVideoAd?

    override func viewDidLoad() {
        super.viewDidLoad()
        loadRewardAd()
    }

    private func loadRewardAd() {
        // 创建 ToBid 激励视频广告对象
        rewardAd = WMRewardVideoAd(placementId: "YOUR_TOBID_REWARD_PLACEMENT_ID")

        // 设置代理
        rewardAd?.delegate = self

        // 加载广告
        rewardAd?.loadAd()
    }
}

// MARK: - WMRewardVideoAdDelegate
extension ToBidRewardAdViewController: WMRewardVideoAdDelegate {

    func rewardVideoAdDidLoad(_ rewardVideoAd: WMRewardVideoAd) {
        print("激励视频加载成功")
        // 展示广告
        rewardVideoAd.showAd(withRootViewController: self)
    }

    func rewardVideoAdDidFail(toLoad rewardVideoAd: WMRewardVideoAd, withError error: Error) {
        print("激励视频加载失败: \(error.localizedDescription)")
    }

    func rewardVideoAdDidShow(_ rewardVideoAd: WMRewardVideoAd) {
        print("激励视频展示成功")
    }

    func rewardVideoAdDidClick(_ rewardVideoAd: WMRewardVideoAd) {
        print("激励视频被点击")
    }

    func rewardVideoAdDidClose(_ rewardVideoAd: WMRewardVideoAd) {
        print("激励视频关闭")
    }

    func rewardVideoAdDidRewardEffective(_ rewardVideoAd: WMRewardVideoAd) {
        print("激励视频奖励到达,发放奖励")
        // 在此发放奖励
    }
}

5. iOS 适配器架构

适配器架构说明(选读)

优聚 ToBid 适配器位于 ios/Adapters/ToBidAdapter/,包含以下核心组件:

  • 公开入口:提供 versionensureLinked() 方法,防止链接器优化掉适配器代码
  • 初始化适配器:接收 ToBid 的初始化调用,解析 CustomInfo 并触发优聚 SDK 初始化
  • 各广告类型适配器:开屏、激励视频、插屏、横幅(iOS 独有)、原生广告各一个适配器类
  • 初始化状态追踪:单例模式追踪优聚 SDK 初始化状态
  • 配置解析器:解析 ToBid 后台下发的 CustomInfo JSON 配置
  • Bridge 回调分发:通过运行时机制调用 ToBid bridge 回调,避免编译期对 WindMillSDK 的硬依赖

工作原理

初始化流程

ToBid SDK 启动后,自动触发优聚 SDK 初始化:

  1. ToBid 启动时发现优聚 ToBid 适配器的初始化入口
  2. 适配器解析 CustomInfo(appId/appKey/channel)
  3. 调用 UjuAdSdk.init() 保存基础配置
  4. 调用 UjuAdSdk.start() 异步拉取策略
  5. 初始化成功/失败后,适配器回调 ToBid 对应的初始化结果

广告加载流程

  1. ToBid 调用适配器的 loadAd 方法
  2. 适配器内部等待优聚 SDK 初始化完成(若尚未完成)
  3. 初始化完成后,解析 placementId(从 CustomInfo)
  4. 调用 UjuAdObject.getXxxObject() 创建广告对象并设置监听器
  5. 调用 load() 发起广告加载
  6. 加载成功:若为 C2S 竞价,将 eCPM 回传给 ToBid;否则通知加载完成
  7. 加载失败:回调 ToBid 加载失败
  8. 广告展示/点击/关闭等事件自动回调给 ToBid

C2S 竞价机制

阶段说明
加载成功适配器将 eCPM 价格回传给 ToBid,参与竞价
竞价胜出优聚 SDK 内部自动处理竞胜通知,开发者无需关注
竞价失败优聚 SDK 内部自动处理竞败通知,开发者无需关注

无需手动上报竞价结果

竞价胜负的上报由优聚 SDK 内部自动完成,开发者无需手动调用任何方法。ToBid 的竞价结果回调方法在适配器中为空实现,不会影响功能。


离线策略说明

ToBid 反向集成场景下,presetStrategyFileName 必须设为空字符串 "",仅依赖服务端策略:

kotlin
// 适配器内部已自动设置,开发者无需关心
val config = UjuAdInitConfig(
    // ...其他参数
    presetStrategyFileName = ""  // ToBid 场景必须为空
)

原因:ToBid 场景下优聚 SDK 的策略完全由服务端下发,本地预置策略文件无效。


常见问题

Q: 优聚 SDK 需要单独初始化吗?

A: 不需要。ToBid SDK 启动后会自动触发优聚 SDK 的 init + start 流程。开发者只需初始化 ToBid SDK 即可。

Q: 广告加载时报 "no strategy" 错误怎么办?

A: 该错误表示优聚 SDK 尚未初始化完成就调用了 loadAd。适配器内置了初始化等待机制,正常情况下会自动等待。如果仍出现该错误,请检查:

  • ToBid 后台 ADN 级别 CustomInfo 中的 appId / appKey 是否正确
  • 优聚后台是否已创建对应的应用和广告位
  • 网络连接是否正常

Q: 如何查看优聚 SDK 的初始化状态?

A: 通过 ToBid 的 setNetworkInitListener(Android)/ 初始化回调(iOS)监听各 ADN 初始化状态。适配器内部也维护了初始化状态(对应 UjuAdInitStatus 枚举:IDLE / INITIALIZING / INITIALIZED / INITIALIZATION_FAILED),但该状态由适配器内部管理,开发者通常通过 ToBid 的初始化回调即可感知。

Q: 激励视频的奖励如何发放?

A: 优聚 SDK 的激励视频奖励回调(onAdRewardArrived)由适配器内部处理并转发给 ToBid。开发者应在 ToBid 的激励视频代理回调(rewardVideoAdDidRewardEffective)中发放奖励,无需直接处理优聚 SDK 的监听器。

Q: 原生广告为什么是模板渲染模式?

A: 优聚原生广告采用模板渲染模式(isExpressAd() = true),由 SDK 内部渲染广告视图。适配器通过 UjuAdObject.show(activity, container) 将模板视图绑定到 ToBid 提供的容器中。NativeAdData 的字段(title/desc/iconUrl 等)可能为空,开发者无需自行渲染。

Q: iOS 端为什么需要调用 ensureLinked()?

A: iOS 端的 ToBid 适配器采用反向集成模式,不通过 register() 注册,由 WindMillSDK 运行时通过 ObjC 运行时发现 Custom*Adapter 类。如果不调用 ensureLinked(),链接器可能会将适配器代码优化掉(dead-strip),导致 ToBid 无法发现适配器。


相关链接