Android SDK
Publisher-first AMOS SDK integration for Android apps.
This page is a practical onboarding guide for publishers integrating AMOS for the first time. It explains which artifact to choose, how to configure AdMob groups, and how to wire interstitial, banner, rewarded, native, and app-open flows with copy-pasteable examples.
Step 1
Choose the right SDK
- Use `amos-sdk-admob` if you want the SDK to handle most AdMob load and show plumbing for you.
- Use `amos-sdk` if your app already has its own ads layer or if you want tighter control over the timing of ad loading and showing.
- Most first-time publishers integrating only AdMob should start with `amos-sdk-admob`.
- In decision policy setup, use provider `admob` for wrapper serving and provider `none` for manual or hybrid serving.
Dependency Setup
Add Maven Central and the SDK
Configure repositories once in your Android project, then add the SDK artifact that matches your integration style.
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
dependencies {
// Wrapper-serving AdMob integration
implementation("com.yuktinai:amos-sdk-admob:1.0.4")
// Or manual / hybrid serving
// implementation("com.yuktinai:amos-sdk:1.0.4")
// implementation("com.google.android.gms:play-services-ads:25.4.0")
}
Step 2
Prepare the app basics
- Add Android Internet permission in the manifest.
- Keep your AMOS `API_KEY`, `APP_ID`, and publisher user ID ready.
- If you use `amos-sdk-admob`, also keep your AdMob application ID ready.
Manifest
Add required app entries
<uses-permission android:name="android.permission.INTERNET" />
android {
defaultConfig {
// Only for amos-sdk-admob
manifestPlaceholders["amosAdMobAppId"] =
"ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"
}
}
Step 3
Initialize AMOS in your app
The first integration step in code is to initialize `Monetization` with your AMOS credentials and the current app user ID.
Monetization.init(
context = applicationContext,
apiKey = "YOUR_API_KEY",
appId = "YOUR_APP_ID",
userId = "publisher-user-123"
) {
// Ready to use SDK helpers here
}
Important: `Monetization.init(...)` is required. Reading `Monetization.getState()` is optional. AMOS already uses the resolved allowlists internally when you call helper methods like `trackEventIfAllowed(...)`, `trackMetricIfAllowed(...)`, `isEventAllowed(...)`, and `isMetricAllowed(...)`.
QA tip: if you change a backend decision policy and want a fresh evaluation immediately, end the active session and initialize again. The AMOS sample app exposes this as a `Restart Session` action.
What this does
What publishers should know
- Initialization should happen early in app startup.
- The same app user should keep the same `userId` for consistent tracking.
- The callback is a good place to begin optional ad wrapper initialization.
- You can safely keep app-side reward and placement decisions in your own UI code.
Step 4A
Choose how AdMob config is sourced
- `LOCAL` is the default path for all publishers. The app provides `AdMobConfig` and the SDK uses only that config.
- `REMOTE` and `REMOTE_WITH_LOCAL_FALLBACK` are managed rollout options enabled by Yuktinai.
- `REMOTE` means the SDK uses backend-managed app AdMob config.
- `REMOTE_WITH_LOCAL_FALLBACK` means backend config is preferred and local config is used only when remote config is empty or unavailable.
- If you want remote-managed AdMob config for your app, contact Yuktinai to enable that setup.
App Settings
Remote config can be managed outside the app
Admin UI app settings
- admobConfigMode = LOCAL | REMOTE | REMOTE_WITH_LOCAL_FALLBACK
- guided remote AdMob group editor
- optional publisher self-service enable
Publisher self-service portal
- app-scoped admin-domain link
- registered publisher email + OTP
- guided remote AdMob group CRUD for one app
Remote modes are enabled only for managed publisher rollouts.
Step 4B
Define AdMob groups clearly
Groups let you separate ad inventory by app surface or UX moment. A publisher can keep one default group and add custom groups such as level-end, content banners, rewarded bonus screens, native feed cards, or app-open starts.
val adMobConfig = AdMobConfig(
interstitialGroups = mapOf(
AdMobConfig.DEFAULT_GROUP_REF to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/111"),
preloadOnInit = true
),
"interstitial_level_end" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/112", "ca-app-pub-xxx/113"),
allowFallbackToDefault = true
),
"interstitial_store_entry" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/114")
)
),
bannerGroups = mapOf(
AdMobConfig.DEFAULT_GROUP_REF to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/221")
),
"banner_content" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/222", "ca-app-pub-xxx/223"),
allowFallbackToDefault = true
),
"banner_home_header" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/224")
)
),
rewardedGroups = mapOf(
AdMobConfig.DEFAULT_GROUP_REF to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/331"),
preloadOnInit = true
),
"rewarded_bonus_claim" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/332"),
preloadOnInit = true,
allowFallbackToDefault = true
)
),
nativeGroups = mapOf(
AdMobConfig.DEFAULT_GROUP_REF to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/441")
),
"native_feed_card" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/442", "ca-app-pub-xxx/443"),
allowFallbackToDefault = true
)
),
appOpenGroups = mapOf(
AdMobConfig.DEFAULT_GROUP_REF to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/551"),
preloadOnInit = true
),
"app_open_cold_start" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/552"),
preloadOnInit = true,
allowFallbackToDefault = true
)
)
)
How to think about groups
Keep naming based on app surfaces
- Use `default` as the safe generic fallback for each ad type.
- Use `interstitial_level_end` when the app wants an interstitial after gameplay or a finished task.
- Use `banner_content` when the app wants banner inventory inside feed or content surfaces.
- Use `rewarded_bonus_claim` when the app wants a bonus or reward claim flow.
- Use `native_feed_card` when the app renders native ad inventory inside a feed or card layout.
- Use `app_open_cold_start` when the app wants app-open inventory during a cold-start or return-to-app moment.
- One group can contain multiple unit IDs, which makes rotation easier later.
Optional Setup
Externalize AdMobConfig if you want
A publisher does not have to hardcode all groups directly in one Activity. You can keep the config in a local provider class, asset, or remote app config layer and build `AdMobConfig` before passing it to the SDK.
object PublisherAdMobConfigProvider {
fun build(): AdMobConfig {
return AdMobConfig(
interstitialGroups = mapOf(
AdMobConfig.DEFAULT_GROUP_REF to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/111"),
preloadOnInit = true
),
"interstitial_level_end" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/112"),
allowFallbackToDefault = true
)
),
bannerGroups = mapOf(
"banner_content" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/222")
)
),
rewardedGroups = mapOf(
"rewarded_bonus_claim" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/332"),
preloadOnInit = true
)
),
nativeGroups = mapOf(
"native_feed_card" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/442")
)
),
appOpenGroups = mapOf(
"app_open_cold_start" to AdMobGroupConfig(
unitIds = listOf("ca-app-pub-xxx/552"),
preloadOnInit = true
)
)
)
}
}
Good practice
When to externalize config
- Keep it inline if you have only a few unit IDs and a single app.
- Move it into a provider object if you want cleaner app architecture.
- Move it into assets or remote config only if your publishing operations really need it.
- Use readable group names so developers know what each group is for without cross-checking spreadsheets.
Wrapper Path
Integrate with `amos-sdk-admob`
This is the simpler path for first-time publishers using AdMob.
val adMobConfig = PublisherAdMobConfigProvider.build()
// Required for LOCAL
// Optional only if Yuktinai has enabled REMOTE for your app
AmosAdMob.configure(adMobConfig)
Monetization.init(this, "YOUR_API_KEY", "YOUR_APP_ID", "publisher-user-123") {
AmosAdMob.initialize(this)
}
// Interstitial using a custom group
AmosAdMob.showInterstitial(
activity = this,
groupRef = "interstitial_level_end",
onShown = { },
onDismissed = { },
onFailed = { error -> }
)
// Rewarded using a custom group
AmosAdMob.showRewarded(
activity = this,
groupRef = "rewarded_bonus_claim",
onRewardEarned = {
grantCoinsToUser()
}
)
// Banner using a custom group
AmosAdMob.createBannerView(
context = this,
groupRef = "banner_content",
container = bannerContainer
)
// Native request planning using a custom group.
// Your app still owns the NativeAd layout and rendering.
val nativeRequest = AmosAdMob.getNativeRequest("native_feed_card")
if (nativeRequest != null) {
loadNativeAdWithYourRenderer(nativeRequest.unitId)
}
// App-open request planning using a custom group.
// Record when the app-open ad is shown so AMOS can respect cooldown/session limits.
val appOpenRequest = AmosAdMob.getAppOpenRequest("app_open_cold_start")
if (appOpenRequest != null) {
loadAndShowAppOpenAd(appOpenRequest.unitId)
AmosAdMob.recordAppOpenShown(appOpenRequest.groupRef)
}
Wrapper flow
How publishers typically use it
- Choose `LOCAL`, `REMOTE`, or `REMOTE_WITH_LOCAL_FALLBACK` in app settings.
- `LOCAL` is the standard publisher setup.
- Build `AdMobConfig` for the normal app integration path.
- Ask Yuktinai before using `REMOTE` or `REMOTE_WITH_LOCAL_FALLBACK`.
- Call `AmosAdMob.configure(...)` when local config is being used.
- Initialize `Monetization` and then `AmosAdMob.initialize(...)`.
- Use group refs such as `interstitial_level_end`, `banner_content`, `native_feed_card`, or `app_open_cold_start` from your app screens.
- Keep reward grants and UX decisions in your own app code.
Manual Or Hybrid
Integrate with `amos-sdk`
Use this if your app already owns the AdMob objects and serving flow.
val request = Monetization.getAdMobInterstitialRequest("interstitial_level_end")
if (request != null) {
InterstitialAd.load(
context,
request.unitId,
AdRequest.Builder().build(),
object : InterstitialAdLoadCallback() {
override fun onAdLoaded(ad: InterstitialAd) {
Monetization.markAdMobInterstitialLoaded(request.groupRef, ad)
}
override fun onAdFailedToLoad(error: LoadAdError) {
Monetization.markAdMobInterstitialLoadFailed(request.groupRef)
}
}
)
}
val rewarded = Monetization.preloadAdMobRewarded("rewarded_bonus_claim")
val banner = Monetization.getAdMobBannerRequest("banner_content")
val native = Monetization.getAdMobNativeRequest("native_feed_card")
val appOpen = Monetization.getAdMobAppOpenRequest("app_open_cold_start")
if (native != null) {
loadNativeAdWithYourRenderer(native.unitId)
Monetization.markAdMobNativeLoaded(native.groupRef, nativeAd)
}
if (appOpen != null) {
loadAndShowAppOpenAd(appOpen.unitId)
Monetization.recordAdMobAppOpenShown(appOpen.groupRef)
}
When to choose this
Best fit for advanced publishers
- Your app already has a reusable ads abstraction layer.
- You want your app to decide the exact load and show timing.
- You still want helper methods and group-aware request planning from AMOS.
- You want to adopt AMOS gradually without replacing your existing ad-serving code immediately.
Tracking
Track events and metrics during runtime
Publishers can use AMOS tracking helpers throughout the session.
Monetization.trackEventIfAllowed("session_home_opened")
Monetization.trackEventIfAllowed("rewarded_granted")
Monetization.trackMetricIfAllowed("coins_balance", 1250)
Monetization.trackMetricIfAllowed("user_level", 19)
Monetization.trackMetricsIfAllowed(
mapOf(
"country_code" to "US",
"device_name" to Build.MODEL
)
)
Session flow
Keep the integration tidy
- Initialize once when the app session starts.
- Track meaningful app events and app metrics during usage.
- Use group refs only where the app truly needs different inventory treatment.
- Call `Monetization.endSession()` from your own session lifecycle manager when appropriate.
Recommended rollout order
First-time publisher checklist
- Start with `amos-sdk-admob` if AdMob is your only provider right now.
- Define `default` plus a few meaningful custom groups only where needed.
- Validate one interstitial, one banner, one rewarded, one native, and one app-open flow first.
- Externalize `AdMobConfig` only after the initial integration is stable.
- Keep reward granting and screen timing in your app code.
Useful links