ToBid 自定义接入优聚智汇 SDK
概述
本文档指导开发者将优聚智汇 SDK 以**自定义广告网络(Custom Adapter)**形式接入 ToBid(Sigmob WindMill)聚合平台。
接入模式
优聚 SDK 作为 ToBid 的自定义广告网络接入,采用反向集成模式:
- 优聚 SDK 的初始化由 ToBid 自动触发
- 广告加载由 ToBid 调用适配器
loadAd方法发起 - 广告竞价采用 C2S(Client-to-Server)模式,价格由适配器回传给 ToBid
- 开发者无需单独调用
UjuAdSdk.init/UjuAdSdk.start
支持的广告类型
| 广告类型 | Android | iOS(未正式上线) |
|---|---|---|
| 开屏广告(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 中引入适配器模块:
// settings.gradle.kts
include(":olib_tobid_adapter")在 app/build.gradle 中添加依赖:
// 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 提供):
// 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_core、ad_adx、windmill-sdk 使用 compileOnly,意味着这些依赖由宿主 APP 统一提供版本。请确保宿主 APP 已引入对应依赖。
2. 初始化 ToBid 聚合 SDK
在 Application.onCreate() 中初始化 ToBid(WindMill)SDK:
// 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 格式):
{
"appId": "YOUR_UJU_APP_ID",
"appKey": "YOUR_UJU_APP_KEY",
"channel": "tobid1"
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
appId | String | 是 | 优聚智慧后台分配的应用 ID |
appKey | String | 是 | 优聚智汇后台分配的 RSA 公钥,原样传入 |
channel | String | 否 | 渠道标识,用于数据统计与分账 |
3.2 配置广告位
在 ToBid 后台为每个广告位配置 CustomInfo(JSON 格式):
{
"placementId": "YOUR_UJU_PLACEMENT_ID"
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
placementId | String | 是 | 优聚智汇后台分配的广告位 ID |
3.3 配置示例
假设优聚后台分配的信息如下:
- App ID:
a6a4ccd79a067a - App Key:
MIIBI...(RSA 公钥) - 渠道:
tobid1 - 开屏广告位 ID:
3516343733169009
则 ToBid 后台配置为:
ADN 级别 CustomInfo:
{"appId":"a6a4ccd79a067a","appKey":"MIIBI...","channel":"tobid1"}开屏广告位 CustomInfo:
{"placementId":"3516343733169009"}4. 加载广告
ToBid 后台配置完成后,使用 ToBid 标准 API 加载广告。以下以开屏广告为例:
// 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 中添加以下规则:
# 优聚 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_core、ad_adx、windmill-sdk 使用 compileOnly 依赖,由宿主 APP 统一提供版本。竞价结果由优聚 SDK 内部自动处理,开发者无需手动上报。
iOS 接入指南
1. 引入依赖
1.1 引入 ToBid 适配器 Package
在 Xcode 中通过 SPM 引入优聚 ToBid 适配器:
// 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(),防止链接器将适配器代码优化掉:
// 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 加载广告。以下以激励视频为例:
// 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/,包含以下核心组件:
- 公开入口:提供
version和ensureLinked()方法,防止链接器优化掉适配器代码 - 初始化适配器:接收 ToBid 的初始化调用,解析 CustomInfo 并触发优聚 SDK 初始化
- 各广告类型适配器:开屏、激励视频、插屏、横幅(iOS 独有)、原生广告各一个适配器类
- 初始化状态追踪:单例模式追踪优聚 SDK 初始化状态
- 配置解析器:解析 ToBid 后台下发的 CustomInfo JSON 配置
- Bridge 回调分发:通过运行时机制调用 ToBid bridge 回调,避免编译期对 WindMillSDK 的硬依赖
工作原理
初始化流程
ToBid SDK 启动后,自动触发优聚 SDK 初始化:
- ToBid 启动时发现优聚 ToBid 适配器的初始化入口
- 适配器解析 CustomInfo(appId/appKey/channel)
- 调用
UjuAdSdk.init()保存基础配置 - 调用
UjuAdSdk.start()异步拉取策略 - 初始化成功/失败后,适配器回调 ToBid 对应的初始化结果
广告加载流程
- ToBid 调用适配器的
loadAd方法 - 适配器内部等待优聚 SDK 初始化完成(若尚未完成)
- 初始化完成后,解析 placementId(从 CustomInfo)
- 调用
UjuAdObject.getXxxObject()创建广告对象并设置监听器 - 调用
load()发起广告加载 - 加载成功:若为 C2S 竞价,将 eCPM 回传给 ToBid;否则通知加载完成
- 加载失败:回调 ToBid 加载失败
- 广告展示/点击/关闭等事件自动回调给 ToBid
C2S 竞价机制
| 阶段 | 说明 |
|---|---|
| 加载成功 | 适配器将 eCPM 价格回传给 ToBid,参与竞价 |
| 竞价胜出 | 优聚 SDK 内部自动处理竞胜通知,开发者无需关注 |
| 竞价失败 | 优聚 SDK 内部自动处理竞败通知,开发者无需关注 |
无需手动上报竞价结果
竞价胜负的上报由优聚 SDK 内部自动完成,开发者无需手动调用任何方法。ToBid 的竞价结果回调方法在适配器中为空实现,不会影响功能。
离线策略说明
ToBid 反向集成场景下,presetStrategyFileName 必须设为空字符串 "",仅依赖服务端策略:
// 适配器内部已自动设置,开发者无需关心
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 无法发现适配器。
相关链接
- 自定义广告平台概述 — 反向集成概念说明
- Android SDK 初始化 — 优聚 SDK 标准初始化流程(参考)
- iOS 集成说明 — 优聚 iOS SDK 标准集成(参考)
