CloudX Android SDK
使用 Claude Code 自动集成
借助 AI 驱动的代理,15 分钟内完成 CloudX SDK 集成:
需要 Claude Code。
# 安装 CloudX 代理
bash <(curl -fsSL https://raw.githubusercontent.com/cloudx-io/cloudx-sdk-agents/main/scripts/install.sh)
# 在您的 Android 项目中:
claude "Use @agent-cloudx-android-integrator to integrate CloudX SDK with app key: YOUR_KEY"
- CloudX 优先加载,自动回退到现有广告设置
- 隐私合规验证(GDPR、CCPA)
- 构建验证及早发现错误
- 保留现有广告设置作为备份
完整设置指南
手动安装
需要 Android API 23+ 和 Java 8+。
将 CloudX SDK 添加到您应用的 build.gradle:
dependencies {
implementation("io.cloudx:sdk:3.0.0")
// 广告网络适配器
implementation("io.cloudx:sdk:3.0.0")
implementation("io.cloudx:adapter-meta:3.0.0") // Meta Audience Network 6.20.0
implementation("io.cloudx:adapter-vungle:3.0.0") // Vungle SDK 7.7.1
implementation("io.cloudx:adapter-inmobi:3.0.0") // InMobi SDK 11.1.1
implementation("io.cloudx:adapter-mintegral:3.0.0") // Mintegral SDK 17.0.91
implementation("io.cloudx:adapter-unityads:3.0.0") // Unity Ads SDK 4.17.0
}
初始化
// 使用应用密钥初始化
CloudX.initialize(
configuration = CloudXInitializationConfiguration.builder("your-app-key-here")
.build(),
listener = object : CloudXInitializationListener {
override fun onInitialized(configuration: CloudXSdkConfiguration) {
Log.d("CloudX", "CloudX SDK 初始化成功")
}
override fun onInitializationFailed(cloudXError: CloudXError) {
Log.e("CloudX", "CloudX SDK 初始化失败: ${cloudXError.message}")
}
}
)
广告集成
横幅广告 (320x50)
class MainActivity : AppCompatActivity(), CloudXAdViewListener, CloudXAdRevenueListener {
private lateinit var bannerAd: CloudXAdView
private fun createBannerAd() {
bannerAd = CloudX.createBanner("your-banner-ad-unit-id")
bannerAd.listener = this
bannerAd.revenueListener = this
val layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
layoutParams.gravity = Gravity.CENTER_HORIZONTAL
findViewById<LinearLayout>(R.id.banner_container).addView(bannerAd, layoutParams)
}
override fun onDestroy() {
super.onDestroy()
bannerAd.destroy()
}
// CloudXAdViewListener 回调
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "横幅广告已加载,来自 ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "横幅广告加载失败: ${cloudXError.message}")
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "横幅广告被点击")
}
override fun onAdExpanded(cloudXAd: CloudXAd) {
Log.d("CloudX", "横幅广告已展开")
}
override fun onAdCollapsed(cloudXAd: CloudXAd) {
Log.d("CloudX", "横幅广告已折叠")
}
// CloudXAdRevenueListener 回调
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "横幅收入: ${cloudXAd.revenue},来自 ${cloudXAd.networkName}")
}
}
横幅广告默认自动刷新。手动控制刷新:
bannerAd.stopAutoRefresh() // 停止自动刷新
bannerAd.load() // 手动加载新广告
bannerAd.startAutoRefresh() // 重新启用自动刷新
可选的广告位和自定义数据用于跟踪:
bannerAd.setPlacement("home_screen")
bannerAd.setCustomData("level:5,coins:100")
MREC 广告 (300x250)
class MainActivity : AppCompatActivity(), CloudXAdViewListener, CloudXAdRevenueListener {
private lateinit var mrecAd: CloudXAdView
private fun createMrecAd() {
mrecAd = CloudX.createMREC("your-mrec-ad-unit-id")
mrecAd.listener = this
mrecAd.revenueListener = this
val layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
layoutParams.gravity = Gravity.CENTER_HORIZONTAL
findViewById<LinearLayout>(R.id.mrec_container).addView(mrecAd, layoutParams)
}
override fun onDestroy() {
super.onDestroy()
mrecAd.destroy()
}
// CloudXAdViewListener 回调(与横幅广告相同)
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC 广告已加载,来自 ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "MREC 广告加载失败: ${cloudXError.message}")
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC 广告被点击")
}
override fun onAdExpanded(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC 广告已展开")
}
override fun onAdCollapsed(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC 广告已折叠")
}
// CloudXAdRevenueListener 回调
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC 收入: ${cloudXAd.revenue},来自 ${cloudXAd.networkName}")
}
}
MREC 广告也默认自动刷新。使用与横幅广告相同的刷新控制方法。
插屏广告
class MainActivity : AppCompatActivity(), CloudXInterstitialListener, CloudXAdRevenueListener {
private lateinit var interstitialAd: CloudXInterstitialAd
private fun createInterstitialAd() {
interstitialAd = CloudX.createInterstitial("your-interstitial-ad-unit-id")
interstitialAd.listener = this
interstitialAd.revenueListener = this
interstitialAd.load()
}
private fun showInterstitialAd() {
if (interstitialAd.isAdReady) {
// 基本展示
interstitialAd.show(this)
// 或带有可选的广告位和自定义数据用于跟踪
// interstitialAd.show(this, "level_complete", "level:5,score:1000")
} else {
Log.w("CloudX", "插屏广告尚未准备好")
}
}
override fun onDestroy() {
super.onDestroy()
interstitialAd.destroy()
}
// CloudXInterstitialListener 回调
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "插屏广告已加载,来自 ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "插屏广告加载失败: ${cloudXError.message}")
}
override fun onAdDisplayed(cloudXAd: CloudXAd) {
Log.d("CloudX", "插屏广告已展示")
}
override fun onAdDisplayFailed(cloudXAd: CloudXAd, cloudXError: CloudXError) {
Log.e("CloudX", "插屏广告展示失败: ${cloudXError.message}")
}
override fun onAdHidden(cloudXAd: CloudXAd) {
Log.d("CloudX", "插屏广告已隐藏")
// 为下次使用重新加载
interstitialAd.load()
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "插屏广告被点击")
}
// CloudXAdRevenueListener 回调
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "插屏收入: ${cloudXAd.revenue},来自 ${cloudXAd.networkName}")
}
}
激励视频广告
class MainActivity : AppCompatActivity(), CloudXRewardedListener, CloudXAdRevenueListener {
private lateinit var rewardedAd: CloudXRewardedAd
private fun createRewardedAd() {
rewardedAd = CloudX.createRewarded("your-rewarded-ad-unit-id")
rewardedAd.listener = this
rewardedAd.revenueListener = this
rewardedAd.load()
}
private fun showRewardedAd() {
if (rewardedAd.isAdReady) {
// 基本展示
rewardedAd.show(this)
// 或带有可选的广告位和自定义数据用于跟踪
// rewardedAd.show(this, "bonus_coins", "level:5,coins:100")
} else {
Log.w("CloudX", "激励视频广告尚未准备好")
}
}
override fun onDestroy() {
super.onDestroy()
rewardedAd.destroy()
}
// CloudXRewardedListener 回调
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "激励视频广告已加载,来自 ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "激励视频广告加载失败: ${cloudXError.message}")
}
override fun onAdDisplayed(cloudXAd: CloudXAd) {
Log.d("CloudX", "激励视频广告已展示")
}
override fun onAdDisplayFailed(cloudXAd: CloudXAd, cloudXError: CloudXError) {
Log.e("CloudX", "激励视频广告展示失败: ${cloudXError.message}")
}
override fun onAdHidden(cloudXAd: CloudXAd) {
Log.d("CloudX", "激励视频广告已隐藏")
// 为下次使用重新加载
rewardedAd.load()
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "激励视频广告被点击")
}
override fun onUserRewarded(cloudXAd: CloudXAd, reward: CloudXReward) {
Log.d("CloudX", "用户获得奖励: ${reward.amount} ${reward.label}")
// 为用户发放奖励
}
// CloudXAdRevenueListener 回调
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "激励视频收入: ${cloudXAd.revenue},来自 ${cloudXAd.networkName}")
}
}
广告信息 (CloudXAd)
CloudXAd 对象在监听器回调中传递,包含已加载/已展示广告的信息:
| 属性 | 类型 | 描述 |
|---|
adFormat | CloudXAdFormat | 广告格式 (BANNER、MREC、INTERSTITIAL、REWARDED) |
adUnitId | String | 广告单元 ID |
networkName | String | 获胜广告网络的名称 |
networkPlacement | String? | 网络特定的广告位 ID |
placement | String? | 通过 setPlacement() 设置的自定义广告位 |
revenue | Double | 展示级收入(以美元计价) |
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "广告格式: ${cloudXAd.adFormat}")
Log.d("CloudX", "网络: ${cloudXAd.networkName}")
Log.d("CloudX", "收入: ${cloudXAd.revenue}")
}
错误处理
所有 SDK 错误都以 CloudXError 对象的形式在监听器回调中返回:
| 属性 | 类型 | 描述 |
|---|
code | CloudXErrorCode | 错误类别 |
message | String | 人类可读的描述 |
cause | Throwable? | 可选的底层异常 |
formattedMessage | String | 预格式化的消息,包含代码和描述 |
错误代码类别
| 范围 | 类别 | 常见代码 |
|---|
| 0 | 一般 | INTERNAL_ERROR |
| 100-199 | 网络 | NETWORK_ERROR、NETWORK_TIMEOUT、NETWORK_SERVER_ERROR、NETWORK_NO_CONNECTION |
| 200-299 | 初始化 | NOT_INITIALIZED、SDK_DISABLED、NO_ADAPTERS_FOUND、INVALID_APP_KEY |
| 300-399 | 广告加载 | NO_FILL、INVALID_AD_UNIT、ADS_DISABLED |
| 400-499 | 展示 | AD_NOT_READY、AD_ALREADY_SHOWING |
| 600-699 | 适配器 | ADAPTER_NO_FILL、ADAPTER_TIMEOUT、ADAPTER_LOAD_TIMEOUT、ADAPTER_INITIALIZATION_ERROR |
高级功能
调试日志
CloudX.setMinLogLevel(CloudXLogLevel.DEBUG) // 启用调试日志
CloudX.setMinLogLevel(CloudXLogLevel.NONE) // 禁用所有日志
日志级别: VERBOSE < DEBUG < INFO < WARN < ERROR < NONE
使用标签 CloudX 过滤 logcat 以查看 SDK 日志。
展示级收入追踪
在任何广告格式上设置 revenueListener 以接收展示级收入 (ILR) 回调。CloudXAd 对象包含以美元计价的收入值和获胜网络名称。
bannerAd.revenueListener = object : CloudXAdRevenueListener {
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "收入: ${cloudXAd.revenue},来自 ${cloudXAd.networkName}")
}
}
适用于所有广告格式(横幅、MREC、插屏、激励视频)。
测试模式
测试模式由服务器控制,通过设备白名单实现。这提供了更好的安全性,并能控制哪些设备接收测试广告。
启用测试模式:
-
初始化 SDK 并检查 logcat 中的设备广告 ID:
[CloudX][AdvertisingIdProvider] Device IFA for test whitelisting: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX (LAT: false)
-
复制广告 ID 并将其添加到 CloudX 服务器控制台的设备白名单中
-
SDK 将自动为测试模式配置适配器,并在竞价请求中包含测试标志
注意: 测试模式由服务器决定,因此您无需在开发和生产构建之间更改任何代码。
隐私合规
CloudX SDK 通过从 SharedPreferences 读取标准 IAB 隐私字符串来支持 GDPR 和 CCPA 隐私合规。这些值通常由您的同意管理平台(CMP)自动设置,如 Google UMP、OneTrust 或 Sourcepoint。
工作原理
SDK 自动检测用户位置并读取同意信号:
- 欧盟用户 (GDPR):根据 IAB 全球供应商列表 检查 TCF v2 目的 1 和 2 的同意和供应商同意(CloudX 供应商 ID:1510)
- 美国用户 (CCPA):检查销售/共享退出信号
- 其他地区:不应用限制
当同意被拒绝或用户选择退出时,SDK 会从广告请求中删除个人身份信息:
- 广告 ID (GAID) 被清除
- 地理坐标(经纬度)被删除
- 用户键值对不发送
- 哈希用户 ID 被排除
支持的隐私密钥
| 密钥 | 标准 | 描述 |
|---|
IABGPP_HDR_GppString | GPP | 全球隐私平台字符串(现代) |
IABGPP_GppSID | GPP | 部分 ID(例如,“2” 代表欧盟,“7” 代表美国国家,“8” 代表美国加州) |
IABTCF_TCString | TCF v2 | GDPR 同意字符串(传统) |
IABTCF_gdprApplies | TCF v2 | GDPR 是否适用(1 = 是,0 = 否) |
IABUSPrivacy_String | US Privacy | CCPA 隐私字符串(传统,例如 “1YNN”) |
注意:当 GPP(现代标准)和传统 TCF/US Privacy 字符串同时存在时,SDK 优先使用 GPP。
手动隐私 API
如果您自行管理用户同意(不使用 CMP),可以直接设置 GDPR 和 CCPA 隐私状态。这些方法可以在 SDK 初始化之前或之后调用。
// GDPR 同意:true、false 或 null(回退到 CMP)
CloudX.setHasUserConsent(true)
// CCPA do-not-sell:true、false 或 null(回退到 CMP)
CloudX.setDoNotSell(true)
当手动设置值和 CMP 信号同时存在时,CMP 信号(GPP/TCF/US Privacy)优先。手动设置值在未集成 CMP 时作为回退使用。
用户定向
// 设置哈希用户 ID 用于定向
CloudX.setHashedUserId("hashed-user-id")
// 设置自定义用户键值对
CloudX.setUserKeyValue("age", "25")
CloudX.setUserKeyValue("gender", "male")
CloudX.setUserKeyValue("location", "US")
// 设置自定义应用键值对
CloudX.setAppKeyValue("app_version", "1.0.0")
CloudX.setAppKeyValue("user_level", "premium")
// 清除所有自定义键值对
CloudX.clearAllKeyValues()
技术支持
如需支持,请联系 mobile@cloudx.io