概览
CloudX Flutter SDK 设置和核心功能概览
CloudX Flutter SDK 可让您通过横幅、MREC、插屏和激励视频广告,在 iOS 和 Android 上为 Flutter 应用变现。
安装
要求
以下版本与 pub.dev 上已发布的软件包约束一致:
| 要求 | 版本 |
|---|---|
| Dart SDK | >=2.17.1 <4.0.0 |
| Flutter | >=3.0.0 |
| iOS | 13.0+ |
| Android | minSdk 23 (API 23) |
Dart 版本范围刻意放宽,以便仍在较旧 Flutter LTS 线上的应用可以添加 cloudx_flutter,而不必升级整套工具链。
在 pubspec.yaml 中添加 SDK:
dependencies:
cloudx_flutter: ^2.2.3然后运行:
flutter pub getiOS 设置
在 ios/Podfile 中添加广告网络适配器 Pod:
target 'Runner' do
# ... 现有配置 ...
# CloudX 广告网络适配器(按需添加;版本需与原生栈一致)
pod 'CloudXMetaAdapter', '~> 2.2.3'
pod 'CloudXVungleAdapter', '~> 2.2.3'
pod 'CloudXInMobiAdapter', '~> 2.2.3'
pod 'CloudXMintegralAdapter', '~> 2.2.3'
pod 'CloudXUnityAdsAdapter', '~> 2.2.3'
pod 'CloudXRenderer', '~> 2.2.3'
end然后安装 Pod:
cd ios && pod installApp Transport Security
CloudX SDK 不需要禁用应用传输安全(App Transport Security)。如果某个聚合广告网络通过特定域名的纯 HTTP 提供素材,请在 ios/Runner/Info.plist 中为该域名单独配置例外,而不要在整个应用范围允许任意加载(全局 NSAllowsArbitraryLoads 会削弱应用的传输安全,并可能引起 App Store 审核关注):
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>example-ad-network.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>Android 设置
将 CloudX SDK 和适配器依赖添加到应用模块 —— 通常是 android/app/build.gradle 或 android/app/build.gradle.kts:
dependencies {
// CloudX Android SDK(版本应与 cloudx_flutter 锁定的原生发行版一致)
implementation("io.cloudx:sdk:2.2.3")
// 广告网络适配器(按需添加)
implementation("io.cloudx:adapter-meta:2.2.3")
implementation("io.cloudx:adapter-vungle:2.2.3")
implementation("io.cloudx:adapter-inmobi:2.2.3")
implementation("io.cloudx:adapter-mintegral:2.2.3")
implementation("io.cloudx:adapter-unityads:2.2.3")
}Mintegral 适配器与 Maven 仓库
如果您引入 io.cloudx:adapter-mintegral,Gradle 必须从 Mintegral 自己的 Maven 服务器(而不是 Maven Central)解析 Mintegral SDK。请在 Android Gradle 的 repositories 配置中添加该仓库(通常是项目级 build.gradle / build.gradle.kts,例如 Flutter 应用里的 allprojects { repositories { … } })。
完整步骤、Kotlin/Groovy 代码片段和排障说明见 Android Mintegral 适配器 — Maven 仓库。
初始化
在加载任何广告之前初始化 SDK。通常放在主 Widget 的 initState 中:
import 'package:cloudx_flutter/cloudx.dart';
// 可选:启用详细日志(仅用于开发)
CloudX.setMinLogLevel(CloudXLogLevel.verbose);
// 使用您的应用密钥初始化
final config = await CloudX.initialize(appKey: 'YOUR_APP_KEY');
if (config != null) {
print('CloudX initialized');
} else {
print('CloudX init failed');
}CloudX.initialize() 成功时返回非空的 CloudXConfiguration,失败时返回 null。该配置对象目前没有属性——返回值仅作为成功信号。
其他初始化工具方法:
final initialized = await CloudX.isInitialized();
final version = await CloudX.getVersion();广告集成
横幅广告(320x50)
横幅采用程序化浮层方式 —— 以固定屏幕位置覆盖在您的内容之上。
import 'package:cloudx_flutter/cloudx.dart';
const adUnitId = 'home_banner';
// 设置事件监听器
CloudX.setBannerListener(CloudXAdViewListener(
onAdLoaded: (ad) {
print('Banner loaded from ${ad.networkName}');
},
onAdLoadFailed: (adUnitId, error) {
print('Banner failed: ${error.code} ${error.message}');
},
onAdClicked: (ad) {
print('Banner clicked');
},
onAdRevenuePaid: (ad) {
print('Banner revenue: ${ad.revenue}');
},
));
// 创建并展示
CloudX.createBanner(adUnitId: adUnitId, position: CloudXAdViewPosition.bottomCenter);
CloudX.showBanner(adUnitId: adUnitId);
// 完成后隐藏 / 销毁
CloudX.hideBanner(adUnitId: adUnitId);
CloudX.destroyBanner(adUnitId: adUnitId);默认启用自动刷新。如需手动控制:
CloudX.stopBannerAutoRefresh(adUnitId: adUnitId);
CloudX.startBannerAutoRefresh(adUnitId: adUnitId);横幅位置
使用 CloudXAdViewPosition 放置横幅:
topLeft、topCenter、topRight、centerLeft、centered、centerRight、bottomLeft、bottomCenter、bottomRight
创建后如需更新位置:
CloudX.updateBannerPosition(adUnitId: adUnitId, position: CloudXAdViewPosition.topCenter);其他横幅 API
CloudX.setBannerPlacement(adUnitId: adUnitId, placement: 'home_screen');
CloudX.setBannerCustomData(adUnitId: adUnitId, customData: 'custom_data');
CloudX.loadBanner(adUnitId: adUnitId); // 手动重新加载横幅事件
| 回调 | 类型 |
|---|---|
onAdLoaded | CloudXAd |
onAdLoadFailed | String adUnitId, CloudXError |
onAdClicked | CloudXAd |
onAdExpanded | CloudXAd(可选) |
onAdCollapsed | CloudXAd(可选) |
onAdRevenuePaid | CloudXAd(可选) |
MREC 广告(300x250)
MREC 与横幅用法相同,只是尺寸为 300x250。请使用 MREC 方法:
const adUnitId = 'home_mrec';
CloudX.setMRecListener(CloudXAdViewListener(
onAdLoaded: (ad) {
print('MREC loaded from ${ad.networkName}');
},
onAdLoadFailed: (adUnitId, error) {
print('MREC failed: ${error.code} ${error.message}');
},
));
CloudX.createMREC(adUnitId: adUnitId, position: CloudXAdViewPosition.centered);
CloudX.showMREC(adUnitId: adUnitId);
// 完成后销毁
CloudX.destroyMREC(adUnitId: adUnitId);MREC API 与横幅 API 相同 —— 同样的方法和事件都可用,包括 updateMRECPosition、setMRECPlacement、setMRECCustomData、自动刷新控制以及全部事件监听器。
插屏广告
在自然过渡点展示的全屏广告。
import 'package:cloudx_flutter/cloudx.dart';
const adUnitId = 'level_complete';
// 设置事件监听器
CloudX.setInterstitialListener(CloudXInterstitialListener(
onAdLoaded: (ad) {
print('Interstitial loaded');
},
onAdLoadFailed: (adUnitId, error) {
print('Interstitial load failed: ${error.code} ${error.message}');
},
onAdDisplayed: (ad) {
print('Interstitial displayed');
},
onAdDisplayFailed: (ad, error) {
print('Interstitial display failed: ${error.code} ${error.message}');
},
onAdHidden: (ad) {
// 为下次使用重新加载
CloudX.loadInterstitial(adUnitId: adUnitId);
},
onAdClicked: (ad) {
print('Interstitial clicked');
},
onAdRevenuePaid: (ad) {
print('Revenue: ${ad.revenue}');
},
));
// 加载
CloudX.loadInterstitial(adUnitId: adUnitId);
// 就绪后展示(可选 placement 和 custom data)
final isReady = await CloudX.isInterstitialReady(adUnitId: adUnitId);
if (isReady) {
CloudX.showInterstitial(adUnitId: adUnitId);
// 或:CloudX.showInterstitial(adUnitId: adUnitId, placement: 'placement_name', customData: 'custom_data');
}
// 完成后销毁
CloudX.destroyInterstitial(adUnitId: adUnitId);插屏事件
| 回调 | 类型 |
|---|---|
onAdLoaded | CloudXAd |
onAdLoadFailed | String adUnitId, CloudXError |
onAdDisplayed | CloudXAd |
onAdDisplayFailed | CloudXAd, CloudXError |
onAdClicked | CloudXAd |
onAdHidden | CloudXAd |
onAdRevenuePaid | CloudXAd(可选) |
激励视频广告
完成后向用户发放奖励的全屏广告。
import 'package:cloudx_flutter/cloudx.dart';
const adUnitId = 'rewarded_coins';
// 设置事件监听器
CloudX.setRewardedAdListener(CloudXRewardedListener(
onAdLoaded: (ad) {
print('Rewarded loaded');
},
onAdLoadFailed: (adUnitId, error) {
print('Rewarded load failed: ${error.code} ${error.message}');
},
onAdDisplayed: (ad) {
print('Rewarded displayed');
},
onAdDisplayFailed: (ad, error) {
print('Rewarded display failed: ${error.code} ${error.message}');
},
onAdReceivedReward: (ad, reward) {
print('Earned ${reward.amount} ${reward.label}');
},
onAdHidden: (ad) {
// 为下次使用重新加载
CloudX.loadRewardedAd(adUnitId: adUnitId);
},
onAdClicked: (ad) {
print('Rewarded clicked');
},
onAdRevenuePaid: (ad) {
print('Revenue: ${ad.revenue}');
},
));
// 加载
CloudX.loadRewardedAd(adUnitId: adUnitId);
// 就绪后展示(可选 placement 和 custom data)
final isReady = await CloudX.isRewardedAdReady(adUnitId: adUnitId);
if (isReady) {
CloudX.showRewardedAd(adUnitId: adUnitId);
// 或:CloudX.showRewardedAd(adUnitId: adUnitId, placement: 'placement_name', customData: 'custom_data');
}
// 完成后销毁
CloudX.destroyRewardedAd(adUnitId: adUnitId);激励视频事件
| 回调 | 类型 |
|---|---|
onAdLoaded | CloudXAd |
onAdLoadFailed | String adUnitId, CloudXError |
onAdDisplayed | CloudXAd |
onAdDisplayFailed | CloudXAd, CloudXError |
onAdClicked | CloudXAd |
onAdHidden | CloudXAd |
onAdReceivedReward | CloudXAd, CloudXReward |
onAdRevenuePaid | CloudXAd(可选) |
CloudXReward 对象包含:
label— 奖励标签(例如"coins")amount— 奖励数量
基于 Widget 的广告视图
除程序化浮层外,您还可以使用 CloudXAdView 将横幅和 MREC 直接嵌入 Widget 树:
CloudXAdView(
adUnitId: 'home_banner',
adFormat: CloudXAdFormat.banner,
listener: CloudXAdViewListener(
onAdLoaded: (ad) => print('Widget banner loaded'),
onAdLoadFailed: (adUnitId, error) => print('Widget banner failed'),
),
)这会通过 Flutter 的平台视图系统(AndroidView / UiKitView)把原生广告视图内嵌到 Flutter Widget 中。
高级功能
错误处理
所有错误回调都会收到带有 code 和 message 属性的 CloudXError:
| 范围 | 类别 | 常见错误码 |
|---|---|---|
| 0 | 通用 | internalError |
| 100-199 | 网络 | networkError, networkTimeout, networkServerError, networkNoConnection |
| 200-299 | 初始化 | notInitialized, noAdaptersFound, sdkDisabled, invalidAppKey |
| 300-399 | 广告加载 | noFill, invalidAdUnit, adsDisabled |
| 400-499 | 展示 | adNotReady, adAlreadyShowing, dontKeepActivitiesEnabled |
| 600-699 | 适配器 | adapterNoFill, adapterLoadTimeout, adapterTimeout, adapterInitializationError |
完整错误码列表见 CloudXErrorCode。
收入追踪
所有广告格式都提供收入回调。CloudXAd 包含 adUnitId、adFormat、networkName、revenue(美元)、可选 placement 以及可选 networkPlacement:
CloudX.setInterstitialListener(CloudXInterstitialListener(
onAdRevenuePaid: (ad) {
trackRevenue(ad.revenue, ad.networkName, ad.adUnitId);
},
// ... 其他回调
));用户定向
import 'package:cloudx_flutter/cloudx.dart';
// 设置哈希用户 ID(传 null 可清除)
CloudX.setHashedUserId('hashed-user-id');
// 设置自定义键值对
CloudX.setUserKeyValue('age_group', '25-34');
CloudX.setAppKeyValue('app_version', '1.0.0');
// 清除所有自定义键值对
CloudX.clearAllKeyValues();哈希用户 ID 是由发布商提供的假名标识符。当适用的隐私信号允许时,CloudX 会在竞价时记录该值,并在展示级收入导出中以 hashed_user_id 返回。您可以使用该值将 CloudX 收入与自己的用户数据分群关联。未设置 ID、隐私信号阻止持久化或值超过 128 个字符时,导出值为空。请勿传递未经哈希的个人数据。
身份透传
通过 setUserKeyValue 传入 UID 2.0、LiveRamp 和 ID5。有值时设置一次,刷新后再设一次。
| 键 | 传入内容 |
|---|---|
uidapi.com | UID2 广告 token,不要传 refresh token。不要解密。UID2 文档 |
liveramp.com | LiveRamp ATS 信封,不要传 RampID。LiveRamp 文档 |
id5-sync.com | ID5 通用 UID。不要传 0。ID5 文档 |
CloudX 不会生成这些 ID。请先用 UID2、LiveRamp ATS 或 ID5 生成,再把字符串传进来。这与哈希用户 ID 不是同一回事。
CloudX.setUserKeyValue('uidapi.com', uid2Token);
CloudX.setUserKeyValue('liveramp.com', liveRampEnvelope);
CloudX.setUserKeyValue('id5-sync.com', id5Id);隐私合规
从 NSUserDefaults / SharedPreferences 读取 IAB GPP、TCF v2 和 US Privacy 字符串(通常由 CMP 写入)。
| 键 | 标准 | 说明 |
|---|---|---|
IABGPP_HDR_GppString | GPP | 全球隐私平台字符串 |
IABGPP_GppSID | GPP | 部分 ID |
IABTCF_TCString | TCF v2 | GDPR 同意字符串 |
IABUSPrivacy_String | US Privacy | CCPA 字符串 |
手动 API: 当您不使用 CMP,或需要覆盖直到清除时,使用 CloudX.setHasUserConsent(bool?) 和 CloudX.setDoNotSell(bool?)。null 会移除覆盖;解析顺序与原生 SDK 一致(已存储的 IAB 字符串以及这些覆盖)。可在 CloudX.initialize() 之前调用。
CloudX.setHasUserConsent(true);
CloudX.setDoNotSell(false);
CloudX.setHasUserConsent(null);测试模式
测试模式由服务端控制,通过设备白名单实现:
- 启用详细日志后初始化 SDK
- 在控制台日志中找到设备广告 ID
- 在 CloudX 控制台将该设备加入白名单
调试日志
import 'package:cloudx_flutter/cloudx.dart';
// 启用详细日志(在 initialize 之前调用)
CloudX.setMinLogLevel(CloudXLogLevel.verbose);
// 可用级别:verbose、debug、info、warn、error、none可视化调试
启用可视化调试叠加层,以查看广告单元边界和广告网络信息(仅 iOS):
CloudX.setVisualDebuggingEnabled(true);技术支持
如需支持,请联系 support@cloudx.io