CloudX Flutter SDK
The CloudX Flutter SDK enables monetization of your Flutter apps with banner, MREC, interstitial, and rewarded ads on iOS and Android.
Installation
Requirements
These match the published package constraints on pub.dev:
| Requirement | Version |
|---|
| Dart SDK | >=2.17.1 <4.0.0 |
| Flutter | >=3.0.0 |
| iOS | 13.0+ |
| Android | minSdk 23 (API 23) |
The Dart range is intentionally wide so apps on older Flutter LTS lines can add cloudx_flutter without upgrading the whole toolchain.
Add the SDK to your pubspec.yaml:
dependencies:
cloudx_flutter: ^2.2.3
Then run:
iOS Setup
Add ad network adapter pods to your ios/Podfile:
target 'Runner' do
# ... existing config ...
# CloudX ad network adapters (add as needed; match your native stack version)
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
Then install pods:
The CloudXCore pod is automatically included as a dependency of the cloudx_flutter package. You only need to add the adapter pods you want.
App Transport Security
If your ads use HTTP URLs, add the following to your ios/Runner/Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Android Setup
Add CloudX SDK and adapter dependencies to your app module — typically android/app/build.gradle or android/app/build.gradle.kts:
dependencies {
// CloudX Android SDK (version should match cloudx_flutter’s pinned native release)
implementation("io.cloudx:sdk:2.2.3")
// Adapters for ad networks (add as needed)
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")
}
At least one adapter is required for the SDK to serve ads. Remove adapter lines you do not use.
Mintegral adapter and Maven repository
If you include io.cloudx:adapter-mintegral, Gradle must resolve Mintegral’s SDK from Mintegral’s own Maven server (not Maven Central). Add their repository in your Android Gradle repositories configuration (usually the project-level build.gradle / build.gradle.kts, e.g. inside allprojects { repositories { … } } in Flutter apps).
Full steps, Kotlin/Groovy snippets, and troubleshooting are in the Android integration guide — Mintegral Maven repository.
Initialization
Initialize the SDK before loading any ads. Typically in your main widget’s initState:
import 'package:cloudx_flutter/cloudx.dart';
// Optional: enable verbose logging (development only)
CloudX.setMinLogLevel(CloudXLogLevel.verbose);
// Initialize with your app key
final config = await CloudX.initialize(appKey: 'YOUR_APP_KEY');
if (config != null) {
print('CloudX initialized');
} else {
print('CloudX init failed');
}
CloudX.initialize() returns a non-null CloudXConfiguration on success, or null on failure. The configuration object has no properties today—use the return value only as a success signal.
Other initialization utilities:
final initialized = await CloudX.isInitialized();
final version = await CloudX.getVersion();
Ad Integration
Banner Ads (320x50)
Banners use the programmatic overlay approach — they overlay your content at a fixed screen position.
import 'package:cloudx_flutter/cloudx.dart';
const adUnitId = 'home_banner';
// Set up event listener
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}');
},
));
// Create and show
CloudX.createBanner(adUnitId: adUnitId, position: CloudXAdViewPosition.bottomCenter);
CloudX.showBanner(adUnitId: adUnitId);
// Hide / destroy when done
CloudX.hideBanner(adUnitId: adUnitId);
CloudX.destroyBanner(adUnitId: adUnitId);
Auto-refresh is enabled by default. To control it manually:
CloudX.stopBannerAutoRefresh(adUnitId: adUnitId);
CloudX.startBannerAutoRefresh(adUnitId: adUnitId);
Banner Position
Use CloudXAdViewPosition to place the banner:
topLeft, topCenter, topRight, centerLeft, centered, centerRight, bottomLeft, bottomCenter, bottomRight
To update the position after creation:
CloudX.updateBannerPosition(adUnitId: adUnitId, position: CloudXAdViewPosition.topCenter);
Additional Banner APIs
CloudX.setBannerPlacement(adUnitId: adUnitId, placement: 'home_screen');
CloudX.setBannerCustomData(adUnitId: adUnitId, customData: 'custom_data');
CloudX.loadBanner(adUnitId: adUnitId); // manual reload
Banner Events
| Callback | Type |
|---|
onAdLoaded | CloudXAd |
onAdLoadFailed | String adUnitId, CloudXError |
onAdClicked | CloudXAd |
onAdExpanded | CloudXAd (optional) |
onAdCollapsed | CloudXAd (optional) |
onAdRevenuePaid | CloudXAd (optional) |
MREC Ads (300x250)
MRECs work identically to banners but with a 300x250 size. Use the MREC methods:
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);
// Destroy when done
CloudX.destroyMREC(adUnitId: adUnitId);
The MREC API is identical to the Banner API — all the same methods and events are available, including updateMRECPosition, setMRECPlacement, setMRECCustomData, auto-refresh control, and all event listeners.
Interstitial Ads
Full-screen ads shown at natural transition points.
import 'package:cloudx_flutter/cloudx.dart';
const adUnitId = 'level_complete';
// Set up event listener
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) {
// Reload for next use
CloudX.loadInterstitial(adUnitId: adUnitId);
},
onAdClicked: (ad) {
print('Interstitial clicked');
},
onAdRevenuePaid: (ad) {
print('Revenue: ${ad.revenue}');
},
));
// Load
CloudX.loadInterstitial(adUnitId: adUnitId);
// Show when ready (with optional placement and custom data)
final isReady = await CloudX.isInterstitialReady(adUnitId: adUnitId);
if (isReady) {
CloudX.showInterstitial(adUnitId: adUnitId);
// or: CloudX.showInterstitial(adUnitId: adUnitId, placement: 'placement_name', customData: 'custom_data');
}
// Destroy when done
CloudX.destroyInterstitial(adUnitId: adUnitId);
Interstitial Events
| Callback | Type |
|---|
onAdLoaded | CloudXAd |
onAdLoadFailed | String adUnitId, CloudXError |
onAdDisplayed | CloudXAd |
onAdDisplayFailed | CloudXAd, CloudXError |
onAdClicked | CloudXAd |
onAdHidden | CloudXAd |
onAdRevenuePaid | CloudXAd (optional) |
Rewarded Ads
Full-screen ads that grant users a reward upon completion.
import 'package:cloudx_flutter/cloudx.dart';
const adUnitId = 'rewarded_coins';
// Set up event listener
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) {
// Reload for next use
CloudX.loadRewardedAd(adUnitId: adUnitId);
},
onAdClicked: (ad) {
print('Rewarded clicked');
},
onAdRevenuePaid: (ad) {
print('Revenue: ${ad.revenue}');
},
));
// Load
CloudX.loadRewardedAd(adUnitId: adUnitId);
// Show when ready (with optional placement and custom data)
final isReady = await CloudX.isRewardedAdReady(adUnitId: adUnitId);
if (isReady) {
CloudX.showRewardedAd(adUnitId: adUnitId);
// or: CloudX.showRewardedAd(adUnitId: adUnitId, placement: 'placement_name', customData: 'custom_data');
}
// Destroy when done
CloudX.destroyRewardedAd(adUnitId: adUnitId);
Rewarded Events
| Callback | Type |
|---|
onAdLoaded | CloudXAd |
onAdLoadFailed | String adUnitId, CloudXError |
onAdDisplayed | CloudXAd |
onAdDisplayFailed | CloudXAd, CloudXError |
onAdClicked | CloudXAd |
onAdHidden | CloudXAd |
onAdReceivedReward | CloudXAd, CloudXReward |
onAdRevenuePaid | CloudXAd (optional) |
The CloudXReward object contains:
label — the label of the reward (e.g., “coins”)
amount — the reward quantity
In addition to the programmatic overlay approach, you can embed banner and MREC ads directly in your widget tree using CloudXAdView:
CloudXAdView(
adUnitId: 'home_banner',
adFormat: CloudXAdFormat.banner,
listener: CloudXAdViewListener(
onAdLoaded: (ad) => print('Widget banner loaded'),
onAdLoadFailed: (adUnitId, error) => print('Widget banner failed'),
),
)
This uses Flutter’s platform view system (AndroidView / UiKitView) to embed the native ad view inline with your Flutter widgets.
Advanced Features
Error Handling
All error callbacks receive a CloudXError with code and message properties:
| Range | Category | Common Codes |
|---|
| 0 | General | internalError |
| 100-199 | Network | networkError, networkTimeout, networkServerError, networkNoConnection |
| 200-299 | Initialization | notInitialized, noAdaptersFound, sdkDisabled, invalidAppKey |
| 300-399 | Ad Loading | noFill, invalidAdUnit, adsDisabled |
| 400-499 | Display | adNotReady, adAlreadyShowing, dontKeepActivitiesEnabled |
| 600-699 | Adapter | adapterNoFill, adapterLoadTimeout, adapterTimeout, adapterInitializationError |
See CloudXErrorCode for the full list of error codes.
Revenue Tracking
All ad formats provide revenue callbacks. CloudXAd includes adUnitId, adFormat, networkName, revenue (USD), optional placement, and optional networkPlacement:
CloudX.setInterstitialListener(CloudXInterstitialListener(
onAdRevenuePaid: (ad) {
trackRevenue(ad.revenue, ad.networkName, ad.adUnitId);
},
// ... other callbacks
));
User Targeting
import 'package:cloudx_flutter/cloudx.dart';
// Set hashed user ID (pass null to clear)
CloudX.setHashedUserId('hashed-user-id');
// Set custom key-value pairs
CloudX.setUserKeyValue('age_group', '25-34');
CloudX.setAppKeyValue('app_version', '1.0.0');
// Clear all custom key-values
CloudX.clearAllKeyValues();
Privacy Compliance
Reads IAB GPP, TCF v2, and US Privacy strings from NSUserDefaults / SharedPreferences (typically set by a CMP).
| Key | Standard | Description |
|---|
IABGPP_HDR_GppString | GPP | Global Privacy Platform string |
IABGPP_GppSID | GPP | Section IDs |
IABTCF_TCString | TCF v2 | GDPR consent string |
IABUSPrivacy_String | US Privacy | CCPA string |
Manual APIs: CloudX.setHasUserConsent(bool?) and CloudX.setDoNotSell(bool?) when you do not use a CMP, or to override until cleared. null removes the override; resolution order matches the native SDK (stored IAB strings and these overrides). Callable before CloudX.initialize().
CloudX.setHasUserConsent(true);
CloudX.setDoNotSell(false);
CloudX.setHasUserConsent(null);
Test Mode
Test mode is server-controlled via device whitelisting:
- Initialize the SDK with verbose logging enabled
- Find your device advertising ID in the console logs
- Add the device to your whitelist on the CloudX dashboard
Debug Logging
import 'package:cloudx_flutter/cloudx.dart';
// Enable verbose logging (call before initialize)
CloudX.setMinLogLevel(CloudXLogLevel.verbose);
// Available levels: verbose, debug, info, warn, error, none
Visual Debugging
Enable visual debugging overlays to see ad unit boundaries and network info (iOS only):
CloudX.setVisualDebuggingEnabled(true);
Support
For support, contact mobile@cloudx.io