SDK Integration

Integrate AdsPlus in your mobile app.

One tenant ID, one init call, one line to show an ad. Ad credentials and placement IDs are delivered at runtime — there are no ad-network accounts or keys for you to manage.

The whole integration, in five steps

  1. 1.Get your tenant ID — submit your app in the console; the ID is issued immediately.
  2. 2.Add the SDK — six repositories and one Gradle dependency.
  3. 3.Initialize — one call in Application.onCreate().
  4. 4.Show ads — one call per ad; preloading is automatic.
  5. 5.Verify — check the log, or watch the console card flip.
In a hurry? Let your AI coding agent do it — one prompt, and it follows the same steps and verifies the result.

1. Get your tenant ID

  1. a. Create a developer account and sign in.
  2. b. Submit your app. The package name must be exactly your app's applicationId.
  3. c. Copy the tenant_id (looks like tp_abc1234567) from the app's page. It is the only value you embed.
The tenant ID exists the moment you submit, so you can integrate while the app is under review. Ads start serving after approval, once we have connected ad networks to your ad slots (usually 1-3 business days) — with no code change on your side. The app's page in the console shows each step under Integration status.

2. Add the SDK

Add the SDK repository and the mediation repositories to settings.gradle.kts (projects without dependencyResolutionManagement: the root build file's allprojects.repositories). All six are required.

settings.gradle.kts
gradle
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        // AdsPlus SDK
        maven { url = uri("https://www.bytemedia.mobi/adsplus/maven") }
        // Required mediation dependency repositories — add exactly as shown
        maven { url = uri("https://jfrog.anythinktech.com/artifactory/overseas_sdk") }
        maven { url = uri("https://artifact.bytedance.com/repository/pangle") }
        maven { url = uri("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea") }
        maven { url = uri("https://artifactory.bidmachine.io/bidmachine") }
        maven { url = uri("https://cboost.jfrog.io/artifactory/chartboost-ads/") }
    }
}

Then, in your app module, set compileSdk 35 and add the dependency. ProGuard / R8 rules and manifest permissions are bundled — nothing else to add.

app/build.gradle.kts
gradle
android {
    compileSdk = 35   // required by a mediation dependency
}

dependencies {
    implementation("com.gameadsdk:ads-sdk-android:1.0.13")
}

Build requirements

compileSdk35 or higher (targetSdk can stay; 34 is tested)
minSdk21 or higher
Android Gradle Plugin8.5.2 or higher (needs Gradle 8.7+ and JDK 17 to run the build)
Java source level11 or higher (compileOptions)
Kotlin Gradle plugin2.0 or higher — only if your app module uses Kotlin

On AGP 8.5.x (which officially supports up to compileSdk 34), also add this to gradle.properties:

gradle.properties
properties
# AGP 8.5.x only — not needed on AGP 8.6+
android.suppressUnsupportedCompileSdk=35

Kotlin projects on plugin 1.9.x fail in compileDebugKotlin with Module was compiled with an incompatible version of Kotlin. Upgrade the Kotlin Gradle plugin to 2.0+ (recommended), or add this to your app module. Pure-Java apps are not affected.

app/build.gradle.kts
gradle
// Only if you are stuck on Kotlin Gradle plugin 1.9.x — prefer upgrading to 2.0+
android {
    kotlinOptions {
        freeCompilerArgs += listOf("-Xskip-metadata-version-check")
    }
}

3. Initialize

Initialize once, in Application.onCreate() — not in an Activity. If your project has no Application class yet, create one:

MyApplication.java
java
import android.app.Application;
import android.util.Log;
import com.gameadsdk.GameAdSDK;
import com.gameadsdk.callbacks.GADSDKCallback;
import com.gameadsdk.core.GADConfig;

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        GADConfig config = new GADConfig.Builder("tp_abc1234567")   // your tenant ID
                .packageId(getPackageName())
                .build();

        GameAdSDK.getInstance().initialize(this, config, new GADSDKCallback() {
            @Override
            public void onSDKInitialized() {
                // Ready. The SDK is already preloading ads — show them whenever you like.
            }

            @Override
            public void onSDKInitializeFailed(String error) {
                Log.e("AdsPlus", "Init failed: " + error);
            }
        });
    }
}

and register it in the manifest:

AndroidManifest.xml
xml
<application
    android:name=".MyApplication"
    ... >
</application>

4. Show ads

After init the SDK keeps a rewarded and an interstitial ad preloaded and refills them after every show. You never create ad objects, handle placement IDs or track load state — just call show.

Rewarded ad

java
import com.gameadsdk.GameAdSDK;
import com.gameadsdk.ads.RewardedAd;
import com.gameadsdk.callbacks.RewardedAdCallback;

// Optional: enable your "Watch ad" button only when an ad is ready
watchAdButton.setEnabled(GameAdSDK.getInstance().isRewardedReady());

GameAdSDK.getInstance().showRewarded(activity, new RewardedAdCallback() {
    @Override
    public void onUserRewarded(RewardedAd ad, String rewardType, int rewardAmount) {
        // The user earned the reward — grant it here.
        // rewardType / rewardAmount are placeholders ("" / 1); decide the reward in your own code.
    }

    // Exactly one of the next three fires per call — resume your game there.
    // `ad` may be null in the two failure callbacks; use the error string.
    @Override
    public void onAdClosed(RewardedAd ad) { resumeGame(); }

    @Override
    public void onAdLoadFailed(RewardedAd ad, String error) { resumeGame(); }

    @Override
    public void onAdDisplayFailed(RewardedAd ad, String error) { resumeGame(); }
});

Interstitial ad

java
import com.gameadsdk.GameAdSDK;
import com.gameadsdk.ads.InterstitialAd;
import com.gameadsdk.callbacks.InterstitialAdCallback;

GameAdSDK.getInstance().showInterstitial(activity, new InterstitialAdCallback() {
    // Exactly one of these fires per call. `ad` may be null in the failure callbacks.
    @Override
    public void onAdClosed(InterstitialAd ad) { resumeGame(); }

    @Override
    public void onAdLoadFailed(InterstitialAd ad, String error) { resumeGame(); }

    @Override
    public void onAdDisplayFailed(InterstitialAd ad, String error) { resumeGame(); }
});

MREC ad (300×250 banner)

The banner is the one format you hold as an object, because it stays on screen:

java
import com.gameadsdk.GameAdSDK;
import com.gameadsdk.ads.MRECAd;
import com.gameadsdk.callbacks.MRECAdCallback;

// Create it only after onSDKInitialized() — the placement ID is null before that.
MRECAd mrecAd = new MRECAd(GameAdSDK.getInstance().getMrecPlacementId());
mrecAd.setCallback(new MRECAdCallback() {
    @Override
    public void onAdLoaded(MRECAd ad) {
        ad.show(activity);   // auto-positioned bottom-center
    }

    @Override
    public void onAdLoadFailed(MRECAd ad, String error) { /* no ad this time */ }
});
mrecAd.load(activity);   // must be given the Activity

// Toggle visibility
mrecAd.hide();
mrecAd.show();

// In the Activity's onDestroy()
mrecAd.destroy();

5. Verify

Build, launch the app on a device or emulator, and watch the SDK log:

shell
adb logcat -s GameAdSDK:*
What you seeWhat it means
Init succeeds and onSDKInitialized() firesIntegration verified. Call showRewarded() and you should see an ad.
HTTP 403: Invalid tenant or package not approvedIf the app is still pending review: your integration is complete — it starts working on approval, with no code change. If the app is approved: your applicationId does not exactly match the package name registered in the console.
Init succeeds, but ads fail with no_fillAd networks are still being connected to your ad slots (usually 1-3 business days after approval). Not an integration bug — wait for "Ad demand configured" on the Integration status card.

You can also confirm it without a cable: the app's page in the console has an Integration status card that flips to “SDK initialized” within about ten seconds of the first successful init, and to “First ad shown” after the first impression.

Let an AI agent do it

Claude Code, Cursor, Copilot and similar agents can do all of the above unattended. We publish a self-contained spec written for them:

Or paste this generic prompt and fill in the two placeholders:

prompt.md
markdown
You are integrating the AdsPlus ad-monetization SDK into my Android app.

App facts (use these values verbatim):
- tenant_id: TENANT_ID                  <- from AdsPlus console -> My Apps
- package name (applicationId must match exactly): YOUR_PACKAGE_NAME
- platform: android

Fetch and follow EXACTLY this integration spec — it overrides any other
AdsPlus snippet you find elsewhere:
https://bytemedia.mobi/adsplus/integration/android.md

Acceptance criteria:
1. ./gradlew assembleDebug succeeds.
2. On launch, "adb logcat -s GameAdSDK:*" shows init success (onSDKInitialized fires).
3. If init fails with HTTP 403 "Invalid tenant or package not approved" and the app
   is still pending review, the code integration is COMPLETE — stop and report that.
4. Never create ad objects before onSDKInitialized() fires.

Bind your own user ID (optional)

The SDK identifies users on its own. If your app has stable account IDs and you want the same user recognised after a reinstall, pass one as outerId when you build the config. (There is also updateUserId(), but it is ignored once the user has been identified, which normally happens during init — use outerId.)

java
GADConfig config = new GADConfig.Builder("tp_abc1234567")
        .packageId(getPackageName())
        .outerId("your_account_id")   // stable per user; survives reinstall
        .build();

Ad pacing

Pacing is managed on the platform side; there is nothing to configure in the app. When ads are switched off for your app or for a particular user, show calls end in the failure callback with ads_disabled (MREC: limited: <reason>). The last known state is cached, so a briefly unreachable backend does not interrupt playback.

Manual ad objects (advanced)

RewardedAd and InterstitialAd can also be driven by hand (load → isReady → show → destroy). You then own preloading, reloading and cleanup yourself, so prefer the one-call API in step 4 unless you have a specific reason.

Show the manual rewarded example
java
// Only if you need to own the ad object. Create it after onSDKInitialized().
RewardedAd rewardedAd = new RewardedAd(GameAdSDK.getInstance().getRewardedPlacementId());
rewardedAd.setCallback(new RewardedAdCallback() {
    @Override
    public void onAdLoaded(RewardedAd ad) {
        // Loading is async — show from here, or just enable your button
        if (ad.isReady()) ad.show(activity);
    }

    @Override
    public void onAdClosed(RewardedAd ad) { ad.load(context); }   // preload the next one
});
rewardedAd.load(context);   // the first load() must be given a Context

// In onDestroy()
rewardedAd.destroy();

H5 / WebView bridge (optional)

Lets a web page inside your app's WebView (a wallet, a task list) trigger native ads. On the native side, attach the bridge to the WebView and name the hosts that are allowed to use it — without setAllowedHosts, any page the WebView navigates to could call it. Subdomains are not implied; list each host.

WalletActivity.java
java
import com.gameadsdk.h5bridge.GADWebViewBridge;

WebView webView = findViewById(R.id.webview);
GADWebViewBridge bridge = new GADWebViewBridge(webView, this)
        .setAllowedHosts("your-server.com");   // only pages on these hosts may call the bridge
webView.loadUrl("https://your-server.com/wallet");

// In onDestroy()
bridge.destroy();

On the web side, download adsplus-bridge.js, host it next to your page, and call it:

wallet.html
html
<!-- Download adsplus-bridge.js (link above) and host it next to your page -->
<script src="adsplus-bridge.js"></script>
wallet.js
javascript
// Show a rewarded ad from the web page
if (AdsPlusBridge.isAdReady('rewarded')) {
    AdsPlusBridge.showRewardedAd();
}

// The user finished the ad
window.addEventListener('adsplus:userRewarded', function () {
    // Ask YOUR server to credit the reward — a web page can be tampered with.
    // e.detail.rewardType / e.detail.amount are placeholders; do not rely on them.
});

// No ad this time (no fill, ads switched off, ...)
window.addEventListener('adsplus:adFailed', function (e) {
    console.log('Ad failed:', e.detail.adType, e.detail.error);
});

Troubleshooting

SymptomFix
Build error mentioning compileSdk 34 or io.bidmachine.media3Set compileSdk to 35 in the app module; on AGP 8.5.x also add the gradle.properties flag from step 2.
Module was compiled with an incompatible version of KotlinUpgrade the Kotlin Gradle plugin to 2.0+, or add the -Xskip-metadata-version-check snippet from step 2.
Could not resolve com.gameadsdk:ads-sdk-androidA repository from step 2 is missing — all six are required. Retry once before digging further; they are remote.
IllegalArgumentException: packageId required for tenant modeAdd .packageId(getPackageName()) to the GADConfig builder.
sdk_not_initializedAn ad was requested before onSDKInitialized() fired, or init failed — check the init error first.
no_fillNo ad is available right now. Expected until ad demand is configured for a new app; occasional afterwards.
ads_disabledAds are switched off on the platform side for this app or this user.
no_activityMRECAd.load() and the first load() of a manual ad object must be given an Activity / Context.
ad_in_progress / load_timeout / display_failedAnother ad is already showing, the ad did not load in time, or it failed to render. Resume your game and try again later.

Error strings can carry a detail suffix (no_fill: …), so match them with startsWith. For verbose SDK logs while integrating:

java
GameAdSDK.getInstance().setLogLevel(GADLogger.Level.DEBUG);   // com.gameadsdk.core.GADLogger
adsplus.·Open ad monetization platform

© 2026 AdsPlus. All rights reserved.