displayio_sdk 0.0.1
displayio_sdk: ^0.0.1 copied to clipboard
Flutter plugin for the DIO (Display.io) ad SDKs — banner, infeed, interstitial, interscroller, audio and native ads on Android and iOS through one Dart API.
displayio_sdk #
The DIO (Display.io) Flutter plugin. It wraps the native DIO ad SDKs for Android and iOS, so a Flutter app loads and shows DIO ads through a single Dart API — every DIO ad format, one call site.
Status: all formats are implemented and device-verified on both platforms. The package is pre-1.0 — the API may still change.
Requirements #
| Flutter | >= 3.44.1 (Dart SDK ^3.12.1) |
| Android | minSdk 24; pulls com.brandio.ads:sdk from https://maven.display.io/ |
| iOS | DIOSDK via Swift Package Manager |
The Android artifact lives in DIO's own Maven repo, so add it to your app's
settings.gradle.kts (dependencyResolutionManagement) or build.gradle.kts:
repositories {
maven { url = uri("https://maven.display.io/") }
}
You need a DIO app id and placement ids from the DIO dashboard.
Install #
dependencies:
displayio_sdk: ^0.0.1
import 'package:displayio_sdk/displayio_sdk.dart';
Quick start #
Initialize once at startup, then load a placement. The returned DioAd is a
sealed type — switch on it to get the right presentation:
await DioSdk.instance.initialize(appId: 'APP_ID');
final ad = await DioSdk.instance.loadAd('PLACEMENT_ID');
switch (ad) {
case DioInlineAd(): // banner / infeed / inline / interscroller
DioAdView(ad: ad, reveal: true);
case DioInterstitialAd():
await ad.show();
case DioAudioAd(): // InFlowAudio / InRing
ad.play();
ad.pause();
ad.companionView; // DioCompanionView? — null when absent
case DioNativeAd():
DioNativeAdView(ad: ad, child: /* your layout + slot widgets */);
}
The concrete ad type comes from ad.type, not from the placement type — an
inline placement resolves at load time to a banner, infeed, or interscroller.
On iOS the first
initializecall blocks the main thread briefly (the native SDK creates aWKWebViewsynchronously to read the user agent), which stalls Flutter rendering. Call it at startup / on a splash screen, and judge UI smoothness in profile or release builds, not debug.
Formats #
| Format | Presentation |
|---|---|
| Banner (HTML / video / audio) | DioAdView |
| Infeed (video / display / audio) | DioAdView |
| Interscroller (display / video / audio) | DioAdView(reveal: true) — Dart-driven reveal parallax |
| Inline | DioAdView (resolves to one of the above) |
| Interstitial (display / video / audio) | ad.show() |
| InFlowAudio / InRing | ad.play() / ad.pause() + optional companion view |
| Native | DioNativeAdView + slot widgets |
Native ads #
Native ads are publisher-rendered: the SDK gives you the text assets and fills its own media / icon / CTA slots; you build the layout with your own Flutter widgets.
DioNativeAdView(
ad: ad,
child: Column(
children: [
Text(ad.headline ?? ''),
DioNativeIconView(ad: ad, size: 44), // optional
DioNativeMediaView(ad: ad, aspectRatio: 16 / 9), // required — click + viewability root
Text(ad.body ?? ''),
DioNativeCtaView(ad: ad, text: ad.callToAction), // optional, separately tracked CTA
],
),
);
DioNativeAdViewregisters and unregisters the slots for click and impression tracking; wrapping the layout in it is required.- Text (
headline,body,callToAction,advertiser,price,privacy) is plain Flutter. There are no image URLs — icon and main image are rendered by the SDK into native slots, and click/viewability need real native views. - A Flutter-drawn CTA cannot be click-tracked; use
DioNativeCtaViewor rely on the media tap.
Customization — DioAdOptions #
Per-load options span two axes: placement styling and the ORTB ad
request. Every field is nullable and null means leave the native SDK
default untouched.
final ad = await DioSdk.instance.loadAd('PID', options: DioAdOptions(
// placement styling — only the group matching the resolved format applies
audio: DioAudioControls(showSoundControl: false, accentColor: Color(0xFF00A2FF)),
interscroller: DioInterscrollerConfig(headerText: 'Ad', showTapHint: false),
infeed: DioInfeedConfig(fullWidth: true, ctaButtonInfeedColor: Colors.black),
pureAudioAd: DioPureAudioAdConfig(autoRequestEnabled: false),
native: DioNativeRequestConfig(video: DioAssetParams(required: true)),
// ORTB bid request / targeting — always applied
request: DioAdRequestConfig(
user: DioRequestUser(yob: 1990, gender: DioGender.female),
bcat: ['IAB25'],
tmax: 1000,
),
));
Ad metadata #
Each loaded ad carries a read-only snapshot of the bid response:
ad.metadata?.ecpm;
ad.metadata?.advertiserName;
ad.metadata?.creativeId;
ad.description; // "AdUnit: <type>, Placement id: <id>, Request id: <id>"
Server-to-server (ORTB) #
For a mediation / S2S flow, let the SDK build the bid request, POST it to your own exchange, and render the response you get back:
final requestJson = await DioSdk.instance.buildOrtbRequest('PID');
final token = await DioSdk.instance.token(); // DIO user token (user.buyeruid)
// ... POST requestJson to your exchange, receive ortbJson ...
final ad = await DioSdk.instance.loadAdFromOrtb('PID', ortbJson);
The result is an ordinary DioAd — the same widgets, show, events, metadata,
and dispose apply. loadAdFromOrtb takes the raw ORTB JSON string; only
the placement part of options applies (including native asset params, which
the parser needs so asset ids match).
Known limitations #
- iOS interscroller does not auto-pause/resume media on scroll visibility. That logic is scroll-driven inside the native SDK, and the plugin hosts the interscroller in a scroll view whose offset is pinned (the parallax is Dart-driven), so the SDK never sees a visibility change. Android is unaffected.
*TextSizeoptions are Android-only — iOS folds text size into a font the SDK does not expose.- Custom fonts are not exposed. A Flutter-bundled font is invisible to
native
Typeface/UIFontwithout registering it in the native project, which would break the single-Dart-API promise. interscroller/infeedstyling applies only when the placement resolves directly to that format — reached through aninlineplacement, the concrete sub-placement is unknown at config time and the styling is skipped.- Audio output routing is the publisher's job on iOS (a global
AVAudioSession);setAudioOutputis a no-op there. Seeexample/for a demo using theaudio_sessionpackage. - Native ads use up to three platform views (media / icon / CTA) — mind the count in a scrolling feed, and note that viewability is measured on the media slot rather than the whole card.
Example #
example/ is a full test app covering every format, the customization and ORTB
flows, and metadata:
cd example && flutter run
Placement inventory lives in example/lib/test_placements.dart and ad
customization in example/lib/test_ad_config.dart.
License #
MIT — see LICENSE.