Skip to content

Flutter SDK ​

The adbnk_sdk Flutter plugin wraps the ADBNK native SDKs for Android and iOS. The native SDK on each platform does the rendering, click handling and tracking. The Dart API uses the same names as google_mobile_ads: AdRequest, AdLoadCallback, FullScreenContentCallback and so on.

Version: the version of the plugin package you received. AdbnkSdk.sdkVersion returns it.

Requirements ​

ItemRequirement
Flutter3.0+ (Dart 2.19+)
AndroidminSdk 21, compileSdk 34+
iOS12.0+

You also need a zone ID for each placement. Create an App SDK zone in the publisher console, open Zones, then Get code.

Installation ​

The plugin and the native SDKs it depends on are delivered as an SDK package. To get it, contact your ADBNK account manager.

Unpack the plugin into your project (for example packages/adbnk_sdk) and add it as a path dependency:

yaml
# pubspec.yaml
dependencies:
  adbnk_sdk:
    path: packages/adbnk_sdk
bash
flutter pub get

The plugin also needs the native SDK files from your package:

  • Android: put the AAR and POM at adbnk_sdk/android/libs/repo/app/adbnk/adbnk-sdk/<version>/ (file names adbnk-sdk-<version>.aar and .pom). The plugin uses this folder as a local Maven repository. If your settings.gradle sets dependencyResolutionManagement to PREFER_SETTINGS, also add maven { url = uri("<path>/adbnk_sdk/android/libs/repo") } there.
  • iOS: put AdbnkSDK.xcframework at adbnk_sdk/ios/Frameworks/AdbnkSDK.xcframework, set platform :ios, '12.0' or higher in ios/Podfile, then run pod install.

If a native file is missing, the build stops and prints the path it expected.

Initialization ​

dart
import 'package:adbnk_sdk/adbnk_sdk.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final status = await AdbnkSdk.initialize(
    appId: 'com.example.myapp',                 // your app identifier
  );
  // status.ready, status.sdkVersion
  runApp(const MyApp());
}

Every load method throws a StateError if you call it before initialize has completed.

AdbnkConfig fields:

FieldDefaultDescription
testModefalseSee Test mode
gdprConsentnullGDPR consent. null means unknown and is treated as not consented. See Privacy
coppaCompliancefalseTreat all requests as child-directed

Other members: AdbnkSdk.isInitialized, AdbnkSdk.sdkVersion, setGDPRConsent(bool), setCOPPACompliance(bool), setTestMode(bool).

AdRequest ​

dart
final request = AdRequest.builder()
    .addKeyword('sports')
    .setContentUrl('https://example.com/article/123')
    .setNonPersonalizedAds(false)
    .setTagForChildDirectedTreatment(null)   // true / false / null = unspecified
    .setTagForUnderAgeOfConsent(null)
    .putExtra('placement', 'home_feed')
    .build();

const AdRequest.empty() is the default request.

Ad formats ​

FormatDart API
BannerBannerAdWidget (widget)
Float banner (pinned top/bottom)FloatBannerAd
NativeNativeAdWidget (widget) / NativeAd
InterstitialInterstitialAd
RewardedRewardedAd
Rewarded interstitialRewardedInterstitialAd
SplashSplashAd
App openAppOpenAd / AppOpenAdManager
PopupPopupAd

Full-screen formats: common pattern ​

Interstitial, rewarded, rewarded interstitial, splash, app open and popup ads all follow the same pattern:

dart
static Future<void> load(
  String zoneId, {
  AdRequest? adRequest,
  required AdLoadCallback<T> adLoadCallback,
});
  1. In onAdLoaded, set ad.fullScreenContentCallback.
  2. Call ad.show().
  3. Call ad.dispose() after the ad is dismissed.
dart
FullScreenContentCallback<T>(
  onAdShowedFullScreenContent: (ad) {},
  onAdDismissedFullScreenContent: (ad) {},
  onAdFailedToShowFullScreenContent: (ad, error) {},
  onAdImpression: (ad) {},
  onAdClicked: (ad) {},
)

Each ad object can be shown once, and ad.isReady turns false afterwards.

One loaded ad per format

Each format holds only one loaded ad at a time, and events go to the most recently loaded instance. Show an interstitial before you load the next interstitial.

Interstitial ​

dart
InterstitialAd? _interstitial;

void loadInterstitial() {
  InterstitialAd.load(
    'YOUR_ZONE_ID',
    adLoadCallback: AdLoadCallback<InterstitialAd>(
      onAdLoaded: (ad) {
        ad.fullScreenContentCallback = FullScreenContentCallback<InterstitialAd>(
          onAdDismissedFullScreenContent: (ad) {
            ad.dispose();
            _interstitial = null;
            loadInterstitial();           // preload the next one
          },
          onAdFailedToShowFullScreenContent: (ad, error) {
            ad.dispose();
            _interstitial = null;
          },
        );
        _interstitial = ad;
      },
      onAdFailedToLoad: (error) => debugPrint('load failed: $error'),
    ),
  );
}

void showInterstitial() {
  if (_interstitial?.isReady ?? false) _interstitial!.show();
}

Rewarded and rewarded interstitial ​

RewardedAd and RewardedInterstitialAd share the same API. Pass the reward callback to show(). It is called at most once per ad.

dart
RewardedAd.load(
  'YOUR_ZONE_ID',
  adLoadCallback: AdLoadCallback<RewardedAd>(
    onAdLoaded: (ad) {
      ad.fullScreenContentCallback = FullScreenContentCallback<RewardedAd>(
        onAdDismissedFullScreenContent: (ad) => ad.dispose(),
      );
      ad.show(onUserEarnedReward: (RewardItem reward) {
        grantReward(reward.amount, reward.type);
      });
    },
    onAdFailedToLoad: (error) {},
  ),
);

You configure the reward amount and type on the zone in the publisher console.

Splash ​

dart
SplashAd.load(
  'YOUR_ZONE_ID',
  adLoadCallback: AdLoadCallback<SplashAd>(
    onAdLoaded: (ad) {
      ad.fullScreenContentCallback = FullScreenContentCallback<SplashAd>(
        onAdDismissedFullScreenContent: (ad) { ad.dispose(); goToHome(); },
        onAdFailedToShowFullScreenContent: (ad, _) { ad.dispose(); goToHome(); },
      );
      ad.show();
    },
    onAdFailedToLoad: (_) => goToHome(),
  ),
);

App open ​

AppOpenAd.load(...) works the same way as the other full-screen formats. To show an app open ad whenever the app returns to the foreground, use AppOpenAdManager and call it from your lifecycle observer:

dart
class _AppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    AppOpenAdManager.instance.setup(zoneId: 'YOUR_ZONE_ID');
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      AppOpenAdManager.instance.showAdIfAvailable();
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    AppOpenAdManager.instance.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => const MaterialApp(home: HomePage());
}

The manager preloads the next ad after each one is dismissed, and retries if a load fails.

dart
PopupAd.load(
  'YOUR_ZONE_ID',
  adLoadCallback: AdLoadCallback<PopupAd>(
    onAdLoaded: (ad) {
      ad.fullScreenContentCallback = FullScreenContentCallback<PopupAd>(
        onAdDismissedFullScreenContent: (ad) => ad.dispose(),
      );
      ad.show();
    },
  ),
);

BannerAdWidget is a platform view. It loads its ad when it is created.

dart
BannerAdWidget(
  zoneId: 'YOUR_ZONE_ID',
  size: BannerSize.banner,              // 320x50
  adRequest: AdRequest.empty(),         // optional
  callback: BannerAdCallbackWrapper(
    onLoaded: () {},
    onFailed: (AdError e) {},
    onImpression: () {},
    onClicked: () {},
  ),
)

BannerSize values:

ValueSize
banner320×50
largeBanner320×100
mediumRectangle300×250
fullBanner468×60
leaderboard728×90
adaptiveScreen width × 50

Choose the size that matches your zone. You can have several banners on screen at once.

Float banner ​

A float banner shows automatically as soon as it loads.

dart
final floatBanner = FloatBannerAd(
  zoneId: 'YOUR_ZONE_ID',
  position: FloatBannerPosition.bottom,
  height: 50,
  margin: 0,
  showCloseButton: true,
  refreshInterval: 0,                   // seconds, 0 = no refresh
);
await floatBanner.load(callback: BannerAdCallbackWrapper(onFailed: (e) {}));

// floatBanner.hide();  floatBanner.show();  floatBanner.isShowing
// When you no longer need it:
floatBanner.dispose();

Native ​

With NativeAdWidget, you supply the layout and the widget takes care of loading, recording the impression and handling taps:

dart
NativeAdWidget(
  zoneId: 'YOUR_ZONE_ID',
  builder: (context, NativeAdData? ad, bool isLoaded) {
    if (!isLoaded || ad == null) return const SizedBox.shrink();
    return Card(
      child: ListTile(
        leading: ad.iconUrl != null ? Image.network(ad.iconUrl!) : null,
        title: Text(ad.headline ?? ''),
        subtitle: Text(ad.body ?? ''),
        trailing: Text(ad.callToAction ?? ''),
      ),
    );
  },
)

Tapping the widget opens the ad. Always show ad.sponsoredLabel (the "Ad" label) in your layout.

NativeAdData fields:

FieldDescription
headlineAd headline
bodyAd body text
callToActionCall-to-action text
iconUrlIcon image URL
imageUrlMain image URL
advertiserAdvertiser name
ratingRating
pricePrice
storeStore
sponsoredLabel"Ad" label text

For full control, use NativeAd directly:

  1. Call await ad.load(callback: ...).
  2. Read ad.adData.
  3. Call ad.recordImpression() when the ad is actually shown to the user.
  4. Call ad.recordClick() only on a real user tap.
  5. Call ad.dispose() when you're done.

Click handling ​

You don't need to handle clicks yourself. The native SDK records the click, then opens the ad's deep link if it has one. If there's no deep link, or it can't be opened, it opens the landing page instead.

Privacy and compliance ​

The SDK never shows consent or permission dialogs. Your app collects consent and passes the result to the SDK.

GDPR (EEA/UK users). Collect consent with your CMP, then call:

dart
await AdbnkSdk.setGDPRConsent(userConsented);

Do this before loading ads. Until you set it, consent is unknown and the SDK treats it as not consented.

Non-personalized ads:

dart
AdRequest.builder().setNonPersonalizedAds(true)

COPPA / child-directed apps:

dart
await AdbnkSdk.setCOPPACompliance(true);                   // whole app
AdRequest.builder().setTagForChildDirectedTreatment(true); // per request
AdRequest.builder().setTagForUnderAgeOfConsent(true);

iOS ATT. The SDK doesn't show the ATT prompt. If you want the user to authorize tracking, do the following:

  1. Add NSUserTrackingUsageDescription to ios/Runner/Info.plist.
  2. Request authorization with an ATT plugin of your choice.

If the user doesn't authorize tracking, the SDK doesn't read the IDFA. Ads still serve normally. See iOS privacy.

Store disclosures. Google Play Data safety and App Store privacy labels follow the native SDKs. See the Android and iOS pages.

Test mode ​

  • testMode: true (or AdbnkSdk.setTestMode(true)) marks requests as test requests. ADBNK does not currently serve dedicated test creatives, so the ads you see during development are live. Don't repeatedly click ads on your own devices.
  • The SDK applies traffic-quality protection automatically. You don't need to configure anything.

Error codes ​

AdError has a code and a message.

Errors from the native SDK keep their platform codes:

Errors raised by the Dart layer itself:

CodeMeaning
1001Invalid zone ID
1002No fill (also used when a native ad returns no assets)
1003Network error
1004Internal error (the message includes the native error code)
1005Ad expired or not ready, for example show() was called before the ad loaded or after it was already shown
1006Ad already shown
1007Ad already loading
1008Unsupported ad format
1009Native plugin not available on this platform

FAQ ​

Banners don't show on desktop or web. The plugin supports Android and iOS only. On other platforms, BannerAdWidget renders an empty box, no ad loads, and calls into the native SDK fail (error 1009 where an AdError is returned).

My callback fired for the wrong ad. Each full-screen format keeps only one loaded ad. Load the next ad only after the previous one has been shown or disposed.

Can I still use loadWithCallback and the *AdCallback classes? They still work, but they're deprecated. Use the static load(..., adLoadCallback:) together with FullScreenContentCallback instead.

Diagnostics. Full-screen ads expose ad.responseInfo?.responseId. Include this ID when you contact support.

Documentation released under the MIT License.