md2link

Partner — SDK 1.1.0 Code Integration Guide

DraftMay 12, 2026

Partner — SDK 1.1.0 Code Integration Guide

Audience: partner developers integrating MonetizeD7 SDK into their app. Purpose: step-by-step integration — from Gradle setup to verification on a QA build. Code reconciled: 2026-05-12.


Table of contents

  1. Environment requirements
  2. Step 1 — Add the SDK
  3. Step 2 — Initialize the SDK
  4. Step 3 — Set up Splash config
  5. Step 4 — Set up Onboarding
  6. Step 5 — Set up Resume Ad
  7. Step 6 — Register InApp touchpoints
  8. Step 7 — Set up Splash screen
  9. Step 8 — Customize UI (Splash + Onboarding)
  10. Step 9 — Show ads at touchpoints
  11. Premium user
  12. Verifying with logs
  13. Pre-release checklist

1. Environment requirements

Item Requirement
minSdk 24
compileSdk 35
JDK 11
Kotlin 1.9+
Google Mobile Ads SDK Transitive dependency (already included)
Maven repo apero-inhouse (credentials provided by the team)

2. Step 1 — Add the SDK

2.1 settings.gradle.kts

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("<apero-inhouse maven repo URL>")
            credentials {
                username = "<provided>"
                password = "<provided>"
            }
        }
    }
}

2.2 Module app/build.gradle.kts

dependencies {
    implementation("apero-inhouse:monetize-d7:1.1.0")
}

3. Step 2 — Initialize the SDK

3.1 Provider class — overview

Create a class implementing FirstOpenConfigProvider. This is the single entry point the SDK uses to read every ad config. Treat the helper methods (buildSplashConfig, buildOnboardingConfig, buildResumeConfig, buildInAppConfig) and MyNextActionListener as a contract — the rest of this guide details each one.

class MyFirstOpenProvider : FirstOpenConfigProvider {

    override fun provideFirstOpenConfig(): FirstOpenConfig =
        FirstOpenConfig.Builder(MyNextActionListener())             // → §3.3
            .setDevelopment(BuildConfig.DEBUG)                      // → §3.4
            .setSplashAdConfig(                                     // → Step 3
                firstOpen  = buildSplashConfigFirstOpen(),
                returnUser = buildSplashConfigReturnUser(),
            )
            .setOnboardingAdConfig(buildOnboardingConfig())         // → Step 4
            .setResumeAdConfig(buildResumeConfig())                 // → Step 5
            .setInAppAd(buildInAppConfig())                         // → Step 6
            .build()

    private fun buildSplashConfigFirstOpen():  FirstOpenConfig.SplashAdConfig      = TODO("see §4")
    private fun buildSplashConfigReturnUser(): FirstOpenConfig.SplashAdConfig      = TODO("see §4")
    private fun buildOnboardingConfig():       FirstOpenConfig.OnboardingAdConfig  = TODO("see §5")
    private fun buildResumeConfig():           FirstOpenConfig.ResumeAdConfig      = TODO("see §6")
    private fun buildInAppConfig():            InAppAdConfig                       = TODO("see §7")
}
Dependency Type Detailed in
MyNextActionListener() FONextActionListener §3.3 — dispatch after onboarding
setDevelopment(BuildConfig.DEBUG) Boolean §3.4 — development flag
buildSplashConfigFirstOpen() FirstOpenConfig.SplashAdConfig §4 — Step 3
buildSplashConfigReturnUser() FirstOpenConfig.SplashAdConfig §4 — Step 3
buildOnboardingConfig() FirstOpenConfig.OnboardingAdConfig §5 — Step 4
buildResumeConfig() FirstOpenConfig.ResumeAdConfig §6 — Step 5
buildInAppConfig() InAppAdConfig §7 — Step 6

The Splash setup ships two configs so BA can ship different strategies for FO (new users) and RU (returning users). They must both be FirstOpenConfig.SplashAdConfig — same shape, independent values.

3.2 Register the provider in Application.onCreate

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        FirstOpenSDK.setFirstOpenConfig(MyFirstOpenProvider())
    }
}

3.3 FONextActionListener — dispatch after onboarding

class MyNextActionListener : FONextActionListener {
    override fun dispatch(activity: ComponentActivity, intent: Intent) {
        val mainIntent = Intent(activity, MainActivity::class.java)
        activity.startActivity(mainIntent)
    }
}

3.4 .setDevelopment(BuildConfig.DEBUG) — development flag

Binds the SDK's dev flag to the app's build type. On debug builds, the Apero Ads tester overlay surfaces load / fail / impression events on top of every ad — pairs with the logcat output in §12. Release builds stay clean.


4. Step 3 — Set up Splash config

Splash takes two configs — one for first-open users, one for returning users — so BA can ship different strategies per segment. Both have the same shape (FirstOpenConfig.SplashAdConfig).

private fun buildSplashConfigFirstOpen(): FirstOpenConfig.SplashAdConfig {
    return FirstOpenConfig.SplashAdConfig(
        nativeSplash2ID = NativeAd2Id("ca-app-pub-xxx/fo-native-hf"),
        interSplash2ID  = InterAd2Id("ca-app-pub-xxx/fo-inter-hf"),
        interSplash     = InterAdId("ca-app-pub-xxx/fo-inter-standard"),
        bannerSplash    = BannerAdDouble(
            hf       = "ca-app-pub-xxx/fo-banner-hf",
            standard = "ca-app-pub-xxx/fo-banner-standard",
        ),
        nativeSplash    = NativeAdId("ca-app-pub-xxx/fo-native-standard"),
    )
}

private fun buildSplashConfigReturnUser(): FirstOpenConfig.SplashAdConfig {
    return FirstOpenConfig.SplashAdConfig(
        nativeSplash2ID = NativeAd2Id("ca-app-pub-xxx/ru-native-hf"),
        interSplash2ID  = InterAd2Id("ca-app-pub-xxx/ru-inter-hf"),
        interSplash     = InterAdId("ca-app-pub-xxx/ru-inter-standard"),
        bannerSplash    = BannerAdDouble(
            hf       = "ca-app-pub-xxx/ru-banner-hf",
            standard = "ca-app-pub-xxx/ru-banner-standard",
        ),
        nativeSplash    = NativeAdId("ca-app-pub-xxx/ru-native-standard"),
    )
}

5. Step 4 — Set up Onboarding

private fun buildOnboardingConfig(): FirstOpenConfig.OnboardingAdConfig {
    return FirstOpenConfig.OnboardingAdConfig(
        nativeOnboarding = NativeAdDouble(
            hf = "ca-app-pub-xxx/native-onboarding-hf",
            standard = "ca-app-pub-xxx/native-onboarding-standard",
        ),
    )
}

6. Step 5 — Set up Resume Ad

private fun buildResumeConfig(): FirstOpenConfig.ResumeAdConfig {
    return FirstOpenConfig.ResumeAdConfig(
        appOpenResume = AppOpenAdId("ca-app-pub-xxx/app-open"),
        nativeResume = NativeAdId("ca-app-pub-xxx/native-resume"),
    )
}

Which ad type is shown (AppOpen or Native) is controlled by BA via Firebase key fo_config_ad_resume.type.


7. Step 6 — Register InApp touchpoints

Every place in the app that needs to show an ad must register one touchpoint with a unique name.

private fun buildInAppConfig(): InAppAdConfig {
    return InAppAdConfig.Builder()
        .register(
            tp = "home",
            nativeAd2Id = NativeAd2Id("ca-app-pub-xxx/home-native-hf"),
            nativeAdId = NativeAdId("ca-app-pub-xxx/home-native-standard"),
            inter = InterAdId("ca-app-pub-xxx/home-inter"),
        )
        .register(
            tp = "save",
            nativeAd2Id = NativeAd2Id("ca-app-pub-xxx/save-native-hf"),
            nativeAdId = NativeAdId(""),
            inter = InterAdId("ca-app-pub-xxx/save-inter"),
        )
        .build()
}
Convention
Touchpoint name is lowercase snake_case (e.g. home, save, share, settings)
Matching Firebase key: inapp_ad_<tp> (e.g. inapp_ad_home)
Empty ID "" opts out of that tier

8. Step 7 — Set up Splash screen

8.1 Subclass FOSplashActivity

Extend the SDK's splash activity to set partner-side behavior.

class MySplashActivity : FOSplashActivity()

The Activity reads FirstOpenSDK.config?.splashAdFirstOpen / splashAdReturnUser at runtime — the ad configs from Step 3 wire in automatically. No additional binding needed.

8.2 Register as the launcher (AndroidManifest.xml)

<activity
    android:name=".MySplashActivity"
    android:exported="true"
    android:theme="@style/Theme.App.Splash">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

8.3 Override functions if needed

Hook When to override
updateUI(savedInstanceState) Programmatic UI override (rarely needed — prefer XML resources in Step 8). Call super first.
afterFetchRemote() Runs once the Firebase remote config snapshot for this session has been fetched and parsed. Use it to kick off any partner-side work that depends on remote flags — e.g. configure feature flags, choose an experiment branch, init A/B-test SDKs, or refresh paywall offers.
suspend interceptorShowFullScreenAd() Suspend the splash until a prerequisite action finishes — e.g. wait for a consent dialog, billing handshake, force-update prompt, or A/B-test flag fetch. The SDK runs this concurrently with the ad load and only proceeds to show the fullscreen ad → navigate to the next screen after this function returns.

Example — afterFetchRemote to apply a remote feature flag:

class MySplashActivity : FOSplashActivity() {

    override fun afterFetchRemote() {
        super.afterFetchRemote()
        FeatureFlags.applyFrom(FirebaseRemoteConfig.getInstance())
    }
}

Example — interceptorShowFullScreenAd to block until a consent dialog is dismissed:

class MySplashActivity : FOSplashActivity() {

    override suspend fun interceptorShowFullScreenAd() {
        ConsentManager.awaitDecision(this)   // suspends until user picks accept / decline
    }
}

If a prerequisite never completes, the SDK still respects its splash timeout — the splash will not hang forever.


9. Step 8 — Customize UI (Splash + Onboarding)

All visual customization is driven by XML resources dropped into app/src/main/res/. The SDK looks them up by exact name — a typo makes the SDK silently fall back to its default. There is no compile-time check.

This step is split into three parts:

  • §9.1 Overall — shared color tokens that apply to both Splash and Onboarding.
  • §9.2 Splash — strings, images, and Lottie animations specific to the Splash screen.
  • §9.3 Onboarding — strings, images, and Lottie animations specific to Onboarding.

9.1 Overall — res/values/colors.xml

The entire SDK UI (Splash + Onboarding) derives from these 4 tokens:

<resources>
    <color name="fo_color_primary">#3B86FF</color>
    <color name="fo_color_background">#FFFFFF</color>
    <color name="fo_color_text_title">#202020</color>
    <color name="fo_color_text_sub_title">#494656</color>
</resources>
Token What it tints
fo_color_primary Brand accent — onboarding Next / Get Started button, progress dots, loading indicator
fo_color_background Window background of the Splash and Onboarding screens
fo_color_text_title Title text on the Splash and on each Onboarding slide
fo_color_text_sub_title Subtitle / description text on Splash and Onboarding

9.2 Splash

Strings — res/values/strings.xml:

Resource name Default Partner must set?
fo_splash_title @string/app_name optional
fo_splash_subtitle (empty) optional
fo_splash_describe_load_ad (This action can contain ads) optional

Images — res/drawable/ (valid extensions: webp, png, jpg):

Resource name Partner must set? Purpose
fo_ic_logo_app yes (unless Lottie supplied) Splash logo
fo_img_splash_bg optional Splash background

Animations — res/raw/ (optional Lottie override):

Resource name Takes precedence over
fo_anim_logo_app fo_ic_logo_app

9.3 Onboarding

Strings — res/values/strings.xml:

Resource name Default Partner must set?
fo_onboarding_title_1, _2, _3 (empty) yes — one per slide
fo_onboarding_description_1, _2, _3 (empty) yes — one per slide
fo_onboarding_button_next Next optional
fo_onboarding_button_start Get Started optional — shown on the last slide

Images — res/drawable/ (valid extensions: webp, png, jpg):

Resource name Partner must set? Purpose
fo_img_onboarding_1, _2, _3 yes (unless Lottie supplied) One image per onboarding slide

Animations — res/raw/ (optional Lottie override):

Resource name Takes precedence over
fo_anim_onboarding_1, _2, _3 fo_img_onboarding_1, _2, _3

10. Step 9 — Show ads at touchpoints

10.1 Preload — how it works

InAppAdManager.bindPreload(owner, tp) is lifecycle-aware: it triggers a preload on every ON_START of owner if the pool is empty for that touchpoint, and auto-unregisters on ON_DESTROY.

When the same touchpoint is triggered from several screens, wrap InAppAdManager in a per-touchpoint helper object:

object ToolAdManager {

    fun bindPreloadToolAd(activity: FragmentActivity) {
        InAppAdManager.bindPreload(activity, "tool")
    }

    fun showToolAd(activity: FragmentActivity, onNextAction: () -> Unit) {
        InAppAdManager.show(activity, "tool", onNextAction)
    }
}

Bind once in the host screen (e.g. MainActivity.onCreate):

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ToolAdManager.bindPreloadToolAd(this)
}

Show at every trigger site — put the navigation / business action in the onNextAction lambda:

ToolAdManager.showToolAd(activity) {
    context.startActivity(SelectPhotoActivity.newIntent(context, /* … */))
}
Guarantees
onNextAction is guaranteed to be called — even when the ad fails, enabled=false, or rule-show skips
Do not run the action outside the lambda — it would run twice
activity must be alive at show time

11. Premium user

The SDK checks premium state via AppPurchase (from com.ads.control.billing).

import com.ads.control.billing.AppPurchase

fun onUserUpgradedToPremium() {
    AppPurchase.getInstance().setPurchase(true)
}

fun onUserDowngraded() {
    AppPurchase.getInstance().setPurchase(false)
}
Rule
Set state before the SDK initializes, or immediately when the user completes purchase
Premium → the SDK skips every ad call and still invokes onNextAction normally
No Firebase key needs to change — premium overrides everything

12. Verifying with logs

On a debug build, enable logging:

adb logcat -s SplashAd InAppAd ResumeAd NativeOnboarding BannerSplash FirstOpenSDK

Or enable via Firebase: fo_allow_log_tester=true.

Pair this with .setDevelopment(BuildConfig.DEBUG) in the provider (§3.4). On debug builds the Apero Ads tester overlay surfaces load / fail / impression events on the ad itself — the overlay messages line up with the logcat lines above, so QA can verify ad behavior visually and via logs at the same time.

Sample log when the SDK initializes successfully:

FirstOpenSDK: FirstOpenSDK configured via FirstOpenConfigProvider (sdk=1.1.0)
FirstOpenSDK: Fetch firebase started
FirstOpenSDK: Fetch firebase in config debug (minInterval=30s)
FirstOpenSDK: Fetch firebase successfully in 412ms
FirstOpenSDK: Handle remote config in 18ms
FirstOpenSDK: [InAppAd] ═══════ Registered 4 touchpoint(s) ═══════
FirstOpenSDK: [InAppAd] ✓ tp=home         native=[hf=ca-app-pub.../home-hf, std=ca-app-pub.../home-std]  inter=[ca-app-pub.../home-int]
FirstOpenSDK: [InAppAd] ✓ tp=save         native=[hf=ca-app-pub.../save-hf]                              inter=[ca-app-pub.../save-int]
FirstOpenSDK: [InAppAd] ✓ tp=share        native=[hf=ca-app-pub.../share-hf, std=ca-app-pub.../share-std]  inter=✗
FirstOpenSDK: [InAppAd] ✓ tp=settings     native=✗                                                       inter=[ca-app-pub.../settings-int]
FirstOpenSDK: [InAppAd] ═══════ End registration ═══════

What to look for:

Line Confirms
FirstOpenSDK configured … (sdk=1.1.0) SDK version is 1.1.0 and setFirstOpenConfig(...) ran exactly once
Fetch firebase successfully in <ms> Remote Config snapshot for this session was retrieved
[InAppAd] Registered N touchpoint(s) Every touchpoint passed to register(...) was accepted; N matches your code
native=[hf=…, std=…], inter=[…] Tier-by-tier ID check — marks a tier you opted out of

13. Pre-release checklist

# Check How to verify
1 SDK version is exactly 1.1.0 Gradle dependency
2 All Ad Unit IDs match the right environment (test vs prod) Read registration log
3 FirstOpenSDK.setFirstOpenConfig() called exactly once in Application.onCreate Log FirstOpenSDK configured...
4 FONextActionListener.dispatch() starts the correct MainActivity Run the FO flow
5 Every InAppAdManager.show() has the onNextAction lambda Code review
6 Premium state set correctly before any ad trigger Test with a premium account
7 Touchpoint names match between code and Firebase Cross-check with BA
8 Tester logging disabled (fo_allow_log_tester=false) on production Firebase Firebase Console
9 ProGuard does not obfuscate SDK classes Build release and test
10 UI resources from Step 8 present and named correctly (4 colors, logo, onboarding images + strings) Visual check on QA build