Android SDK
The ADBNK Android SDK serves ads into native Android apps. Its API follows Google Mobile Ads (AdMob) naming: AdRequest, AdLoadCallback, FullScreenContentCallback, OnUserEarnedRewardListener.
Version: the version of the SDK package you received. At runtime, AdbnkSdk.getVersion() returns it.
Requirements
| Item | Requirement |
|---|---|
| minSdk | 21 (Android 5.0) |
| compileSdk | 34 or later |
| Language | Kotlin or Java (Java 8 bytecode) |
| Permissions | INTERNET and ACCESS_NETWORK_STATE are merged in from the SDK manifest. You don't need to declare them. |
You also need a zone ID for every placement. Create an App SDK zone in the publisher console, open Zones, and click Get code to copy its zone ID.
Installation
The SDK is delivered as a binary AAR. To get the SDK package, contact your ADBNK account manager.
Copy the AAR into app/libs/, then add it together with the libraries the SDK depends on:
// app/build.gradle.kts
dependencies {
implementation(files("libs/adbnk-sdk.aar")) // use the file name from your package
// Required by the ADBNK SDK
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.browser:browser:1.7.0")
}These are standard AndroidX and Kotlin libraries; new Android projects already resolve them. The AAR includes its own consumer ProGuard/R8 rules, so you don't need extra keep rules when you enable minification.
Initialization
Initialize the SDK once, in Application.onCreate(), before you load any ad.
import android.app.Application
import app.adbnk.sdk.AdbnkSdk
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
AdbnkSdk.init(
application = this,
appId = "com.example.myapp" // your app identifier
) { success, error ->
// success == true once the SDK is ready
}
}
}AdbnkSdk.AdConfig fields:
| Field | Default | Description |
|---|---|---|
testMode | false | See Test mode |
gdprConsent | null | GDPR consent. null means unknown and is treated as not consented. See Privacy |
coppaCompliance | false | Treats all requests as child-directed |
Other AdbnkSdk methods: isInitialized(), getVersion(), getAppId(), getConfig(), setGdprConsent(Boolean), setCoppaCompliance(Boolean) and setTestMode(Boolean).
Java callers
Ad load methods live on each class's companion object. From Java, call them as InterstitialAd.Companion.load(...). AdbnkSdk is a Kotlin object, so you reach it through AdbnkSdk.INSTANCE.
AdRequest
Every ad format accepts an optional AdRequest. All of its fields are optional.
val request = AdRequest.Builder()
.addKeyword("sports")
.setContentUrl("https://example.com/article/123")
.setNonPersonalizedAds(false)
.setTagForChildDirected(null) // true / false / null = not specified
.setTagForUnderAgeOfConsent(null)
.putExtra("placement", "home_feed")
.build()AdRequest.empty() returns a request with default values. Loading without an AdRequest is the same as passing an empty one.
Ad formats
| Format | Class | Style |
|---|---|---|
| Banner | BannerAdView | View in your layout |
| Float banner (pinned to the top or bottom of the screen) | FloatBannerAd | Overlay |
| Native | NativeAd | You render the assets |
| Interstitial | InterstitialAd | Full screen |
| Rewarded | RewardedAd | Full screen + reward |
| Rewarded interstitial | RewardedInterstitialAd | Full screen + reward |
| Splash | SplashAd | Full screen at app launch |
| App open | AppOpenAd | Full screen when the app returns to the foreground |
| Popup | PopupAd | Dialog-style overlay |
Use a zone whose format matches the class. If a zone returns a format this SDK version can't render, loading fails with ERROR_CODE_UNSUPPORTED_FORMAT; the app doesn't crash.
Full-screen formats: shared pattern
Interstitial, rewarded, rewarded interstitial, splash, app open and popup ads all work the same way:
XxxAd.load(zoneId, adRequest, AdLoadCallback<XxxAd>). You can also callload(zoneId, callback).- In
onAdLoaded, attachsetFullScreenContentCallback(...). - Call
ad.show(activity)when you're ready.
Each loaded ad object can be shown once. isReady() returns false after the ad has been shown or after it expires. Load a new ad for the next impression.
interface FullScreenContentCallback {
fun onAdShowedFullScreenContent() {}
fun onAdDismissedFullScreenContent() {}
fun onAdFailedToShowFullScreenContent(error: AdError) {}
fun onAdImpression() {}
fun onAdClicked() {}
}All of these methods have default implementations, so override only the ones you need.
Interstitial
import app.adbnk.sdk.*
import app.adbnk.sdk.ads.InterstitialAd
import app.adbnk.sdk.listener.AdError
private var interstitial: InterstitialAd? = null
fun loadInterstitial() {
InterstitialAd.load("YOUR_ZONE_ID", AdRequest.empty(), object : AdLoadCallback<InterstitialAd> {
override fun onAdLoaded(ad: InterstitialAd) {
ad.setFullScreenContentCallback(object : FullScreenContentCallback {
override fun onAdDismissedFullScreenContent() {
interstitial = null
loadInterstitial() // preload the next one
}
override fun onAdFailedToShowFullScreenContent(error: AdError) {
interstitial = null
}
})
interstitial = ad
}
override fun onAdFailedToLoad(error: AdError) {
interstitial = null
}
})
}
fun showInterstitial(activity: Activity) {
interstitial?.takeIf { it.isReady() }?.show(activity)
}Rewarded and rewarded interstitial
RewardedAd and RewardedInterstitialAd share the same API. Grant the reward in OnUserEarnedRewardListener. The SDK fires this callback at most once per ad.
import app.adbnk.sdk.ads.RewardedAd
import app.adbnk.sdk.models.RewardItem
RewardedAd.load("YOUR_ZONE_ID", object : AdLoadCallback<RewardedAd> {
override fun onAdLoaded(ad: RewardedAd) {
ad.setOnUserEarnedRewardListener { reward: RewardItem ->
grantReward(reward.amount, reward.type)
}
ad.setFullScreenContentCallback(object : FullScreenContentCallback {
override fun onAdDismissedFullScreenContent() { /* resume the game */ }
})
ad.show(activity)
}
override fun onAdFailedToLoad(error: AdError) { /* hide the reward button */ }
})You configure the reward amount and type on the zone in the publisher console. They reach your app as RewardItem(amount: Int, type: String).
Splash
Load the splash ad as early as possible in your launch activity. Show it as soon as it loads, then continue to your main screen when the ad is dismissed or fails.
import app.adbnk.sdk.ads.SplashAd
SplashAd.load("YOUR_ZONE_ID", object : AdLoadCallback<SplashAd> {
override fun onAdLoaded(ad: SplashAd) {
ad.setFullScreenContentCallback(object : FullScreenContentCallback {
override fun onAdDismissedFullScreenContent() = goToMain()
override fun onAdFailedToShowFullScreenContent(error: AdError) = goToMain()
})
ad.show(this@SplashActivity)
}
override fun onAdFailedToLoad(error: AdError) = goToMain()
})Splash ads show a countdown with a skip button.
App open
Manual: load and show the ad yourself, the same way as an interstitial:
import app.adbnk.sdk.ads.AppOpenAd
AppOpenAd.load("YOUR_ZONE_ID", object : AdLoadCallback<AppOpenAd> {
override fun onAdLoaded(ad: AppOpenAd) { appOpenAd = ad }
override fun onAdFailedToLoad(error: AdError) {}
})
// later, when the app comes back to the foreground:
appOpenAd?.takeIf { it.isReady() }?.show(activity)Automatic: call setup once in Application.onCreate() (after init). The SDK preloads an ad and shows it whenever the app returns to the foreground.
AppOpenAd.setup(this, "YOUR_ZONE_ID")Popup
import app.adbnk.sdk.ads.PopupAd
PopupAd.load("YOUR_ZONE_ID", object : AdLoadCallback<PopupAd> {
override fun onAdLoaded(ad: PopupAd) { ad.show(activity) }
override fun onAdFailedToLoad(error: AdError) {}
})The close-button behavior is configured on the zone in the publisher console.
Banner
BannerAdView is a FrameLayout. Create it in code, add it to your layout, and call loadAd().
import app.adbnk.sdk.ads.BannerAdView
import app.adbnk.sdk.ads.BannerSize
import app.adbnk.sdk.listener.AdError
import app.adbnk.sdk.listener.BannerAdListener
val banner = BannerAdView(context).apply {
zoneId = "YOUR_ZONE_ID"
bannerSize = BannerSize.BANNER // 320x50
adListener = object : BannerAdListener {
override fun onAdLoaded() {}
override fun onAdFailedToLoad(error: AdError) {}
override fun onAdClicked() {}
}
setAdRequest(AdRequest.empty()) // optional
}
container.addView(banner)
banner.loadAd()Forward the lifecycle from your Activity or Fragment:
override fun onPause() { banner.pause(); super.onPause() }
override fun onResume() { super.onResume(); banner.resume() }
override fun onDestroy() { banner.destroy(); super.onDestroy() }BannerSize values: BANNER (320×50), LARGE_BANNER (320×100), MEDIUM_RECTANGLE (300×250), FULL_BANNER (468×60), LEADERBOARD (728×90) and ADAPTIVE (fills the container width). Pick the size that matches your zone.
Auto-refresh: if the zone has a refresh interval set in the console, that interval is used. Otherwise refreshInterval applies (in seconds; 0 turns refresh off).
WARNING
Create BannerAdView in code. XML attributes such as app:adbnk_zone_id are not read in this version.
Float banner
FloatBannerAd pins a banner to the top or bottom of the screen as an overlay, so it doesn't take up layout space. It shows itself as soon as it loads.
import app.adbnk.sdk.ads.FloatBannerAd
import app.adbnk.sdk.ads.FloatBannerPosition
val floatBanner = FloatBannerAd(activity).apply {
zoneId = "YOUR_ZONE_ID"
position = FloatBannerPosition.BOTTOM
showCloseButton = true
marginDp = 0
autoHideAfter = 0 // seconds, 0 = never
adListener = object : BannerAdListener {
override fun onAdLoaded() {}
override fun onAdFailedToLoad(error: AdError) {}
}
}
floatBanner.loadAd()
// floatBanner.hide() / floatBanner.show() / floatBanner.isShowing() / floatBanner.isLoaded()
// In onPause/onResume/onDestroy: floatBanner.pause() / resume() / destroy()Native
With native ads, the SDK returns the ad assets and you lay them out in your own views.
import app.adbnk.sdk.ads.NativeAd
NativeAd.load("YOUR_ZONE_ID", object : AdLoadCallback<NativeAd> {
override fun onAdLoaded(ad: NativeAd) {
headlineView.text = ad.getHeadline()
bodyView.text = ad.getBody()
ctaButton.text = ad.getCallToAction()
advertiserView.text = ad.getAdvertiser()
sponsoredLabel.text = ad.getSponsoredLabel() // always show an ad label
ad.loadIcon { bmp -> iconView.setImageBitmap(bmp) }
ad.loadMainImage { bmp -> imageView.setImageBitmap(bmp) }
// Required: lets the SDK measure impressions and handle clicks
ad.registerViewForInteraction(adContainer, listOf(ctaButton, imageView))
nativeAd = ad
}
override fun onAdFailedToLoad(error: AdError) {}
})
// When the view is recycled or the screen closes:
nativeAd?.unregisterView()
nativeAd?.destroy()| Getter | Content |
|---|---|
getHeadline() | Title |
getBody() | Description |
getCallToAction() | Button text |
getAdvertiser() | Advertiser or sponsor name |
getIconUrl() / loadIcon {} | Icon |
getMainImageUrl() / loadMainImage {} | Main image |
getStarRating() | Rating, 1–5 (nullable) |
getPrice() | Price (nullable) |
getSponsoredLabel() | Ad label text |
getAssets() | All assets as a NativeAdAssets object |
How native ads behave:
- Call
registerViewForInteractionso the SDK can measure impressions and handle clicks. - When
clickableViewsis empty, the whole container is clickable. - To be notified of clicks, call
ad.setListener(object : NativeAdListener { override fun onAdClicked() {} }).
Click handling
You don't need to write any click-handling code. On a click, the SDK records the click and opens the ad's app deep link, if it has one. If the deep link can't be opened, or the ad has none, it opens the landing page.
Privacy and compliance
The ADBNK SDK does not show any consent or permission dialog itself. Your app collects consent and passes the result to the SDK.
GDPR / EEA and UK users: collect consent with your own CMP, then pass the result to the SDK:
AdbnkSdk.setGdprConsent(userConsented)WARNING
Until you set it, consent is unknown and the SDK treats it as not consented. Once you have the user's choice, call setGdprConsent(true) or setGdprConsent(false) before you load ads.
Non-personalized ads: use AdRequest.Builder().setNonPersonalizedAds(true).
COPPA and child-directed apps:
AdbnkSdk.setCoppaCompliance(true) // whole app
AdRequest.Builder().setTagForChildDirected(true) // per request
AdRequest.Builder().setTagForUnderAgeOfConsent(true) // users under the age of consentWhen consent is withheld, or for child-directed or non-personalized requests, the SDK does not use advertising identifiers. Limited technical data is still processed to keep traffic safe.
Google Play Data safety: declare the SDK's data use in your Data safety form. Contact ADBNK support for the SDK's data disclosure.
Test mode
testMode/setTestMode(true)marks requests as test traffic. ADBNK does not currently serve dedicated test creatives, so the ads you see while developing are live. Don't repeatedly click ads on your own devices.- The SDK handles traffic-quality protection automatically. You don't need to configure anything.
Error codes
AdError has code, message and domain ("app.adbnk.sdk"). The code constants are on AdError.Companion:
| Code | Constant | Meaning |
|---|---|---|
| 0 | ERROR_CODE_INTERNAL | Internal error |
| 1 | ERROR_CODE_INVALID_REQUEST | Invalid request |
| 2 | ERROR_CODE_NETWORK | Network error |
| 3 | ERROR_CODE_NO_FILL | No ad available right now. Retry later and avoid tight retry loops |
| 4 | ERROR_CODE_TIMEOUT | Request timed out |
| 5 | ERROR_CODE_NOT_INITIALIZED | AdbnkSdk.init() was not called |
| 6 | ERROR_CODE_INVALID_ZONE_ID | Zone ID is empty or invalid |
| 7 | ERROR_CODE_AD_EXPIRED | Ad expired or isn't ready. Load a new one |
| 8 | ERROR_CODE_AD_ALREADY_SHOWN | This ad object has already been shown |
| 9 | ERROR_CODE_AD_NOT_READY | Ad not ready to show |
| 10 | ERROR_CODE_AD_ALREADY_LOADING | A load is already in progress |
| 11 | ERROR_CODE_UNSUPPORTED_FORMAT | The zone's ad format isn't supported by this SDK version |
FAQ
I always get no fill (3). Check three things: the zone ID was copied from Get code; the zone is an App SDK zone whose format matches the class you're loading; and the zone is active in the console. New zones may have low fill at first.
Ads load but show() does nothing. Make sure isReady() returns true. Each ad object shows only once and expires after a while. Load a fresh ad for every impression.
Can I use the old lambda load(zoneId) { ad, error -> } and AdListener-style APIs? They still work but are deprecated. Use AdLoadCallback with FullScreenContentCallback instead.
Diagnostics: every ad object exposes getResponseInfo().responseId. Include it when you contact support.