# Android

Source: https://docs.ezoic.com/docs/mobileapps/android/


The Ezoic Ads SDK for Android lets you display banner, rewarded, interstitial, native, outstream video, and instream video ads in native Android apps. The SDK initializes Ezoic configuration, Prebid, Google Ad Manager, and consent handling from one integration point.

## Requirements

- Android SDK 24 or higher
- Android Gradle Plugin 8.0 or higher
- Kotlin 1.9 or higher
- Google Mobile Ads application ID

## Installation

Add the Ezoic Ads SDK dependency to your app module:

```kotlin
dependencies {
    implementation("com.ezoic.sdk:ezoic-ads-sdk:1.5.0")
}
```

The SDK depends on Google Mobile Ads and Prebid Mobile. Make sure your project resolves dependencies from Google's Maven repository and Maven Central.

## Initialize the SDK

Initialize the SDK from your `Application` class or main `Activity` before loading ads.

```kotlin
import android.app.Application
import android.util.Log
import com.ezoic.ads.sdk.core.EzoicAds
import com.ezoic.ads.sdk.core.EzoicConfiguration

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        val config = EzoicConfiguration(
            domain = "example.com",
            debugEnabled = false,
            testMode = false
        )

        EzoicAds.instance.initialize(this, config) { result ->
            result.onSuccess {
                Log.d("Ezoic", "SDK initialized")
            }.onFailure { error ->
                Log.e("Ezoic", "Initialization failed: $error")
            }
        }
    }
}
```

`domain` must match the domain configured for your site in Ezoic.

## Add a Banner Ad

Create an `EzoicBannerView`, add it to your layout, and call `loadAd()` after the SDK is initialized.

```kotlin
import android.os.Bundle
import android.util.Log
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import com.ezoic.ads.sdk.adunits.EzoicBannerView
import com.ezoic.ads.sdk.adunits.EzoicBannerViewListener
import com.ezoic.ads.sdk.core.EzoicError

class MainActivity : AppCompatActivity(), EzoicBannerViewListener {
    private lateinit var bannerView: EzoicBannerView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        bannerView = EzoicBannerView(this, 12345)
        bannerView.listener = this

        val container = findViewById<FrameLayout>(R.id.banner_container)
        container.addView(bannerView)

        bannerView.loadAd("300x250")
    }

    override fun onBannerLoaded(bannerView: EzoicBannerView) {
        Log.d("Ezoic", "Banner loaded")
    }

    override fun onBannerLoadFailed(bannerView: EzoicBannerView, error: EzoicError) {
        Log.e("Ezoic", "Banner failed: ${error.message}")
    }

    override fun onDestroy() {
        bannerView.destroy()
        super.onDestroy()
    }
}
```

Replace `12345` with your Ezoic ad unit identifier. The SDK fetches the Google Ad Manager ad unit, Prebid configuration, supported sizes, targeting values, and refresh interval from Ezoic servers.

## Banner Sizes

You can load ads with an adaptive default size, a typed size, one size string, or a list of size strings.

```kotlin
bannerView.loadAd()
bannerView.loadAd(EzoicBannerSize.MediumRectangle)
bannerView.loadAd("300x250")
bannerView.loadAd(listOf("300x250", "320x50"))
```

Common sizes include:

- `EzoicBannerSize.Banner`: 320x50
- `EzoicBannerSize.LargeBanner`: 320x100
- `EzoicBannerSize.MediumRectangle`: 300x250
- `EzoicBannerSize.FullBanner`: 468x60
- `EzoicBannerSize.Leaderboard`: 728x90
- `EzoicBannerSize.Custom(width, height)`: custom dimensions

## Add a Rewarded Ad

Rewarded ads are full-screen ads that grant an in-app reward when the user finishes watching. They use a load-then-show lifecycle: load the ad ahead of time (for example, at the start of a level), then present it at a natural break and grant the reward when it is earned.

```kotlin
import com.ezoic.ads.sdk.adunits.EzoicRewardedAd
import com.ezoic.ads.sdk.adunits.EzoicRewardedAdListenerAdapter

EzoicRewardedAd.load(this, 12345) { result ->
    result.onSuccess { ad ->
        // Optional: observe lifecycle events
        ad.listener = object : EzoicRewardedAdListenerAdapter() {
            override fun onRewardedAdDismissed(rewardedAd: EzoicRewardedAd) {
                Log.d("Ezoic", "Rewarded ad closed")
            }
        }
        // Present and grant the reward when earned
        ad.show(this) { reward ->
            Log.d("Ezoic", "Earned ${reward.amount} ${reward.type}")
            grantReward(reward.amount)
        }
    }.onFailure { error ->
        Log.e("Ezoic", "Rewarded load failed: ${error.message}")
    }
}
```

Replace `12345` with your Ezoic ad unit identifier. Call `show(activity)` only after the ad has loaded; showing before the load completes (or after the ad was already shown) reports `EzoicError.AdNotReady`. Rewarded ads are single-use — load a new ad for each opportunity.

The reward `type` and `amount` come from the reward configured on the Google Ad Manager rewarded ad unit. The `EzoicRewardedAdListener` also reports `onRewardedAdShown`, `onRewardedAdFailedToShow`, `onRewardedAdImpression`, `onRewardedAdClicked`, and `onUserEarnedReward`. Java apps load with an `EzoicRewardedAdLoadListener` and extend `EzoicRewardedAdListenerAdapter`.

## Add an Interstitial Ad

Interstitial ads are full-screen ads shown at natural transition points (for example, between levels or screens). Unlike rewarded ads, they grant no reward. They use the same load-then-show lifecycle: load the ad ahead of time, then present it at a natural break.

```kotlin
import com.ezoic.ads.sdk.adunits.EzoicInterstitialAd
import com.ezoic.ads.sdk.adunits.EzoicInterstitialAdListenerAdapter

EzoicInterstitialAd.load(this, 12345) { result ->
    result.onSuccess { ad ->
        // Optional: observe lifecycle events
        ad.listener = object : EzoicInterstitialAdListenerAdapter() {
            override fun onInterstitialAdDismissed(interstitialAd: EzoicInterstitialAd) {
                Log.d("Ezoic", "Interstitial ad closed")
            }
        }
        // Present at a natural transition point
        ad.show(this)
    }.onFailure { error ->
        Log.e("Ezoic", "Interstitial load failed: ${error.message}")
    }
}
```

Replace `12345` with your Ezoic ad unit identifier. Call `show(activity)` only after the ad has loaded; showing before the load completes (or after the ad was already shown) reports `EzoicError.AdNotReady`. Interstitial ads are single-use — load a new ad for each opportunity.

The `EzoicInterstitialAdListener` reports `onInterstitialAdShown`, `onInterstitialAdFailedToShow`, `onInterstitialAdImpression`, `onInterstitialAdClicked`, and `onInterstitialAdDismissed`. Java apps load with an `EzoicInterstitialAdLoadListener` and extend `EzoicInterstitialAdListenerAdapter`.

## Add an Outstream Video Ad

Outstream video ads render inline in your own layout, like a banner, but with a video creative in an SDK-built player. Create an `EzoicOutstreamAdView`, add it to your layout, and call `loadAd()`.

```kotlin
import com.ezoic.ads.sdk.adunits.EzoicOutstreamAdView
import com.ezoic.ads.sdk.adunits.EzoicOutstreamAdViewListener
import com.ezoic.ads.sdk.core.EzoicError

class MainActivity : AppCompatActivity(), EzoicOutstreamAdViewListener {
    private lateinit var outstreamAdView: EzoicOutstreamAdView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        outstreamAdView = EzoicOutstreamAdView(this, 12345)
        outstreamAdView.listener = this

        val container = findViewById<FrameLayout>(R.id.outstream_container)
        container.addView(outstreamAdView)

        outstreamAdView.loadAd()
    }

    override fun onOutstreamLoaded(adView: EzoicOutstreamAdView) {
        Log.d("Ezoic", "Outstream ad loaded")
    }

    override fun onOutstreamLoadFailed(adView: EzoicOutstreamAdView, error: EzoicError) {
        Log.e("Ezoic", "Outstream failed: ${error.message}")
    }

    override fun onDestroy() {
        outstreamAdView.destroy()
        super.onDestroy()
    }
}
```

Replace `12345` with your Ezoic ad unit identifier. `EzoicOutstreamAdView` is also XML-inflatable. Unlike `EzoicBannerView`, `loadAd()` takes no size — the SDK renders at the size configured on the server (640x360 by default). Call `destroy()` when the hosting `Activity` or `Fragment` is destroyed.

The `EzoicOutstreamAdViewListener` also reports `onOutstreamImpression`, `onOutstreamClicked`, `onOutstreamOpened`, and `onOutstreamClosed` — all optional.

## Add an Instream Video Ad

Instream video ads play inside your own video content. Your app owns the video player and the [Google IMA SDK](https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side); the Ezoic SDK's job is to build the Google Ad Manager VAST ad-tag URL you hand to IMA. There is no Ezoic view — the deliverable is a URL string. `EzoicInstreamAd` is a view-less, multi-use controller: unlike rewarded and interstitial ads it is not single-use, so keep the instance and call `load()` again for the next video.

```kotlin
import com.ezoic.ads.sdk.adunits.EzoicInstreamAd
import com.ezoic.ads.sdk.adunits.EzoicInstreamAdListener
import com.ezoic.ads.sdk.core.EzoicError
import com.google.ads.interactivemedia.v3.api.ImaSdkFactory

private val instreamAd = EzoicInstreamAd(12345)

instreamAd.load(this, contentUrl = playingVideoUrl, listener = object : EzoicInstreamAdListener {
    override fun onAdTagReady(adTagUrl: String) {
        // Feed the tag to your IMA ads request.
        val request = ImaSdkFactory.getInstance().createAdsRequest()
        request.adTagUrl = adTagUrl
        adsLoader.requestAds(request)
    }

    override fun onAdFailedToLoad(error: EzoicError) {
        Log.e("Ezoic", "Instream load failed: ${error.message}")
        // Play content without a preroll.
    }
})

// In your AdErrorEvent.AdErrorListener, walk down the floor waterfall:
instreamAd.getNextAdTagUrl()?.let { nextTag ->
    val request = ImaSdkFactory.getInstance().createAdsRequest()
    request.adTagUrl = nextTag
    adsLoader.requestAds(request)
}

// In your AdEvent.AdEventListener, on AdEventType.STARTED:
instreamAd.reportImpression()
```

Replace `12345` with your Ezoic ad unit identifier. `contentUrl` (the URL of the video being played) is optional and, when supplied, is added to the ad tag for contextual targeting. The `EzoicInstreamAdListener` reports `onAdTagReady(adTagUrl)` when the tag is ready and `onAdFailedToLoad(error)` on no fill. On an IMA ad error, call `getNextAdTagUrl()` to retry the next floor in the waterfall — it returns `null` once the waterfall is exhausted. On the IMA `STARTED` event, call `reportImpression()` (optionally passing a `revenueUsd` value) to record the Ezoic impression. Unlike rewarded and interstitial ads, `EzoicInstreamAd` is multi-use — call `destroy()` only when the ad unit is no longer needed, for example when the player is torn down.

## Add a Native Ad

Native ads deliver ad assets (headline, image, body text, call to action) that you render inside your own layout instead of a fixed banner or full-screen format, so the ad matches the look and feel of your content.

```kotlin
import com.ezoic.ads.sdk.adunits.EzoicNativeAd
import com.google.android.gms.ads.nativead.NativeAdView

private var ezoicNativeAd: EzoicNativeAd? = null

EzoicNativeAd.load(this, 12345) { result ->
    result.onSuccess { ad ->
        ezoicNativeAd = ad
        val gmaAd = ad.nativeAd ?: return@onSuccess

        // Inflate your own NativeAdView layout and populate its asset views
        val adView = layoutInflater.inflate(R.layout.native_ad_view, null) as NativeAdView
        val headline = adView.findViewById<TextView>(R.id.ad_headline)
        headline.text = gmaAd.headline
        adView.headlineView = headline
        adView.setNativeAd(gmaAd)

        adContainer.removeAllViews()
        adContainer.addView(adView)
    }.onFailure { error ->
        Log.e("Ezoic", "Native load failed: ${error.message}")
    }
}
```

Replace `12345` with your Ezoic ad unit identifier. The SDK returns the underlying Google Mobile Ads `NativeAd` on `ad.nativeAd`; populate a `NativeAdView` with your own styling and assign it with `setNativeAd()`.

Release the ad when the hosting `Activity` or `Fragment` is destroyed:

```kotlin
override fun onDestroy() {
    ezoicNativeAd?.destroy()
    ezoicNativeAd = null
    super.onDestroy()
}
```

The `EzoicNativeAdListener` reports `onNativeAdImpression`, `onNativeAdClicked`, `onNativeAdOpened`, and `onNativeAdClosed`. Java apps load with an `EzoicNativeAdLoadListener` and can extend `EzoicNativeAdListenerAdapter`.

## AndroidManifest.xml

Add your Google Mobile Ads application ID to `AndroidManifest.xml`:

In most Ezoic mobile app integrations, this app ID is provided by Ezoic and can be found in your Ezoic dashboard. Use the value assigned to your app unless your Ezoic representative gives you a different Google Mobile Ads application ID.

```xml
<manifest>
    <application>
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX" />
    </application>
</manifest>
```

If your app targets Android 12 or higher and uses the advertising ID, add the advertising ID permission:

```xml
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
```

## app-ads.txt

Host an `app-ads.txt` file at the root of the developer website listed on your app's Play Store page (for example, `https://example.com/app-ads.txt`). It authorizes the buyers and exchanges that may sell your inventory; a missing or incomplete file causes most programmatic demand to be filtered out. Ezoic provides the required entries — confirm the file is published and current.

Unlike iOS, Android has no App Tracking Transparency or SKAdNetwork requirements. The advertising ID permission above is the main identifier-related step, and Google Mobile Ads merges its own required entries through the manifest automatically.

## Privacy and Consent

The SDK can automatically read consent signals from `SharedPreferences` when they are set by a consent management platform.

- TCF v2 consent is read from `IABTCF_*` keys.
- GPP consent is read from `IABGPP_*` keys.
- US Privacy consent is read from the standard IAB privacy key.

You can also set consent manually:

```kotlin
EzoicAds.instance.setGDPRConsent(
    applies = true,
    consentString = "TCF_CONSENT_STRING"
)

EzoicAds.instance.setGPPConsent(
    gppString = "GPP_STRING",
    sectionIds = "7"
)

EzoicAds.instance.setSubjectToCOPPA(true)
```

## Pageview Tracking

The SDK automatically tracks pageviews for standard `Activity`, `Fragment`, and view-hosted Navigation components after initialization.

If your app uses Compose Navigation, opt in with your `NavController`:

```kotlin
val navController = rememberNavController()
EzoicAds.instance.TrackNavigation(navController)
```

For WebView-heavy apps, use `EzoicWebViewClient` so page loads are tracked as pageviews:

```kotlin
webView.webViewClient = EzoicWebViewClient()
```

You can also track a pageview manually:

```kotlin
EzoicAds.instance.trackPageview()
```

## Java Compatibility

The Android SDK is written in Kotlin, but the public API is designed for Java interoperability. Java apps can use the `EzoicConfiguration.Builder`, callback interfaces, Java-friendly banner size constants, and `EzoicBannerViewAdapter`.

## Troubleshooting

### SDK Not Initializing

1. Confirm the configured domain matches your Ezoic dashboard.
2. Confirm the app has network access.
3. Enable `debugEnabled = true` and check Logcat for `EzoicAds` logs.

### Ads Not Loading

1. Initialize the SDK before calling `loadAd()`.
2. Confirm the Ezoic ad unit identifier is configured in Ezoic.
3. Confirm the Google Mobile Ads application ID is present in `AndroidManifest.xml`.
4. Check consent configuration if traffic is subject to privacy regulations.

