Skip to content

ToBid Android 接入指南

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

阅读前置

请先阅读 ToBid 自定义接入概述,了解反向集成模式、工作原理、后台配置与常见问题。本文仅介绍 Android 端的依赖引入、SDK 初始化、广告加载与混淆规则。

依赖引入

1. 引入优聚 SDK 核心库

确保工程已引入优聚智汇 SDK 核心模块与 ADX 模块(ToBid 适配器运行时依赖):

kotlin
// app 模块的 build.gradle.kts
dependencies {
    // 优聚 SDK 核心 + ADX(本地 aar 或 maven 坐标二选一)
    implementation("com.ujusdk:uju-ad-core:3.1.49")
    implementation("com.ujusdk:uju-ad-adx:1.0.24")
}

2. 引入 ToBid 聚合 SDK

ToBid(Sigmob WindMill)SDK 以本地 aar 形式提供,需将以下 aar 文件放入 app 模块的 libs/ 目录:

文件说明
windmill-sdk-4.3.11.aarWindMill 聚合 SDK 主包
wind-sdk-4.19.8.aarWind 广告核心包
wind-common-1.7.6.aarWind 公共基础库
oaid_sdk_1.0.25.aarOAID 采集(含华为 ads-identifier)
kotlin
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 运行所需的网络与 UI 依赖
    implementation("com.squareup.okhttp3:okhttp:4.12.0")
    implementation("com.squareup.okio:okio:3.6.0")
    implementation("com.google.code.gson:gson:2.8.5")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("androidx.recyclerview:recyclerview:1.3.2")
    implementation("com.google.android.material:material:1.11.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")

    // 荣耀广告标识服务(华为 ads-identifier 已由 oaid_sdk 提供,无需重复引入)
    implementation("com.hihonor.mcs:ads-identifier:1.0.2.301")
}

3. 引入优聚 ToBid 适配器

引入优聚官方提供的 ToBid 自定义适配器模块,运行时由 ToBid 反射加载:

kotlin
dependencies {
    // 优聚 ToBid 自定义适配器(必须 implementation,运行时被 ToBid 反射加载)
    implementation("com.ujusdk:uju-custom-tobid-adapter:4.3.11")
}

必须使用 implementation

适配器必须以 implementation 方式引入,确保其类被编译进宿主 APK,供 ToBid 运行时通过反射发现并调用。

ToBid SDK 初始化

开发者只需初始化 ToBid SDK,优聚 SDK 的初始化由 ToBid 在启动时自动触发(通过适配器的 ADN 初始化入口)。

Application.onCreate() 中初始化 ToBid:

kotlin
import android.app.Application
import android.util.Log
import com.windmill.sdk.WindMillAd
import com.windmill.sdk.WMNetworkInitListener

class App : Application() {

    private val TAG = "App"

    override fun onCreate() {
        super.onCreate()
        initToBidSdk()
    }

    private fun initToBidSdk() {
        Log.d(TAG, "initToBidSdk 开始")
        try {
            // 获取 ToBid SDK 单例
            val ads = WindMillAd.sharedAds()
            // 是否成年(可选参数,默认是成年用户)
            ads.setAdult(true)
            // 是否开启个性化推荐(可选参数,默认开启)
            ads.setPersonalizedAdvertisingOn(true)
            // 开启 Debug 日志(调试阶段建议开启)
            ads.setDebugEnable(true)

            // 渠道初始化监听(可选):监听各广告网络初始化结果
            ads.setNetworkInitListener(object : WMNetworkInitListener {
                override fun onNetworkInitBefore(channel_id: Int, initInstance: Any?) {
                    Log.d(TAG, "onNetworkInitBefore: channel_id=$channel_id")
                }

                override fun onNetworkInitSuccess(channel_id: Int) {
                    Log.d(TAG, "onNetworkInitSuccess: channel_id=$channel_id")
                }

                override fun onNetworkInitFailed(channel_id: Int, error_code: Int, error_msg: String?) {
                    Log.w(TAG, "onNetworkInitFailed: channel_id=$channel_id, code=$error_code, msg=$error_msg")
                }
            })

            // 启动 ToBid SDK,传入 ToBid 后台分配的 AppId
            ads.startWithAppId(
                this,
                TOBID_APP_ID,
                object : WindMillAd.WindMillAdInitListener {
                    override fun onInitSuccess() {
                        Log.d(TAG, "ToBid SDK 初始化成功")
                    }

                    override fun onInitFailed(error_code: Int, error_msg: String?) {
                        Log.e(TAG, "ToBid SDK 初始化失败: code=$error_code, msg=$error_msg")
                    }
                }
            )
        } catch (e: Exception) {
            Log.e(TAG, "initToBidSdk 异常: ${e.message}", e)
        }
    }

    companion object {
        // ToBid 平台分配的 AppId
        private const val TOBID_APP_ID = "YOUR_TOBID_APP_ID"
    }
}

优聚 SDK 无需单独初始化

ToBid SDK 启动后会自动触发优聚 SDK 的 init + start 流程,开发者无需不应调用 UjuAdSdk.init() / UjuAdSdk.start()

广告加载示例

以下以激励视频为例,展示通过 ToBid 标准接口加载广告的完整流程。开屏、插屏、原生广告的调用方式类似,仅广告对象类名不同。

kotlin
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import com.windmill.sdk.models.AdInfo
import com.windmill.sdk.reward.WMRewardAd
import com.windmill.sdk.reward.WMRewardAdListener
import com.windmill.sdk.reward.WMRewardAdRequest
import com.windmill.sdk.WindMillError

class RewardAdActivity : ComponentActivity() {

    private val TAG = "RewardAdActivity"

    // 激励视频广告对象
    private var rewardAd: WMRewardAd? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadRewardAd()
    }

    private fun loadRewardAd() {
        Log.d(TAG, "开始加载激励视频广告: placementId=$REWARD_PLACEMENT_ID")
        try {
            // 构造广告请求(placementId 必填,userId 和 options 可选)
            val request = WMRewardAdRequest(
                REWARD_PLACEMENT_ID,
                "",   // userId 可选
                null  // options 可选
            )

            // 创建激励视频广告对象
            rewardAd = WMRewardAd(this, request)

            // 设置监听回调
            rewardAd?.setRewardedAdListener(object : WMRewardAdListener {
                override fun onVideoAdLoadSuccess(placementId: String?) {
                    Log.d(TAG, "广告加载成功: $placementId")
                    // 加载成功后可调用 show 展示
                }

                override fun onVideoAdLoadError(error: WindMillError?, placementId: String?) {
                    Log.e(TAG, "广告加载失败: ${error?.errorCode}-${error?.message}")
                }

                override fun onVideoAdPlayStart(adInfo: AdInfo?) {
                    Log.d(TAG, "广告开始播放")
                }

                override fun onVideoAdPlayError(error: WindMillError?, placementId: String?) {
                    Log.e(TAG, "广告播放失败: ${error?.errorCode}-${error?.message}")
                }

                override fun onVideoAdPlayEnd(adInfo: AdInfo?) {
                    Log.d(TAG, "广告播放结束")
                }

                override fun onVideoAdClicked(adInfo: AdInfo?) {
                    Log.d(TAG, "广告被点击")
                }

                override fun onVideoRewarded(adInfo: AdInfo?, rewardInfo: com.windmill.sdk.reward.WMRewardInfo?) {
                    Log.d(TAG, "获得奖励: isReward=${rewardInfo?.isReward()}")
                    // 在此发放应用内奖励
                }

                override fun onVideoAdClosed(adInfo: AdInfo?) {
                    Log.d(TAG, "广告关闭")
                }
            })

            // 发起加载
            rewardAd?.loadAd()
        } catch (e: Exception) {
            Log.e(TAG, "加载异常: ${e.message}", e)
        }
    }

    private fun showRewardAd() {
        try {
            // 空指针检查:广告对象存在且就绪才展示
            if (rewardAd != null && rewardAd?.isReady() == true) {
                rewardAd?.show(this, null)
            } else {
                Log.w(TAG, "广告未就绪,无法展示")
            }
        } catch (e: Exception) {
            Log.e(TAG, "展示异常: ${e.message}", e)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 销毁广告对象,释放资源
        rewardAd?.destroy()
        rewardAd = null
    }

    companion object {
        // ToBid 后台配置的广告位 ID(对应优聚广告位)
        private const val REWARD_PLACEMENT_ID = "YOUR_TOBID_REWARD_PLACEMENT_ID"
    }
}

各广告类型对应类

广告类型ToBid 广告类请求类
开屏WMSplashAdWMSplashAdRequest
激励视频WMRewardAdWMRewardAdRequest
插屏WMInterstitialAdWMInterstitialAdRequest
原生WMNativeAdWMNativeAdRequest

横幅广告说明

Android 端暂未提供独立的 ToBid Banner 适配器。如需 Banner,可参考其他适配器实现自行扩展,或联系优聚技术支持。

ProGuard 混淆规则

引入 ToBid 适配器后,需在 app 模块的 proguard-rules.pro 中添加以下规则,避免反射调用的类被混淆:

proguard
# 保留优聚 ToBid 自定义适配器类(ToBid 通过反射调用,不能混淆)
-keep class com.ujusdk.tobid.** { *; }

# 保留 ToBid SDK 的 WMCustom* 基类(避免编译期引用丢失)
-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 { *; }

consumer-rules 已内置

优聚 ToBid 适配器模块的 consumer-rules.pro 已包含 com.ujusdk.tobid.** 的保留规则,引入该模块的 app 会自动应用。上述规则中 WindMill SDK 部分需开发者自行添加。

适配器架构说明

优聚 ToBid 适配器位于 com.ujusdk.tobid 包下,采用 ToBid 自定义广告网络标准接口实现:

  • 初始化代理:实现 ToBid 的 ADN 初始化接口,在 ToBid 启动时解析后台 CustomInfo(appId/appKey/channel),完成优聚 SDK 的 init + start 流程,并回调 ToBid 初始化结果
  • 广告适配器:每种广告类型(开屏/激励/插屏/原生)对应一个独立的适配器类,实现 ToBid 的 WMCustom*Adapter 接口,负责广告的加载、展示、销毁与事件回调转发
  • 初始化等待机制:适配器内部维护初始化状态追踪,各广告适配器在 loadAd 入口会等待优聚 SDK 初始化完成后再执行实际加载,避免 "no strategy" 错误
  • 配置解析:统一解析 ToBid 后台下发的 CustomInfo JSON 字符串,提取 appId/appKey/channel(ADN 级别)与 placementId(广告位级别)

内部实现无需关注

适配器内部的所有类、方法与状态机均为 SDK 内部实现细节,开发者无需直接调用。开发者只需通过 ToBid 标准接口(WindMillAd / WMRewardAd 等)使用广告,后台配置正确的 CustomInfo 即可。

相关链接