hypelab logo

Android SDK Quickstart

The HypeLab Android SDK allows you to monetize your Android app with banner, native, interstitial, and rewarded ads. The SDK handles ad loading, rendering, viewability tracking, and click handling with a simple callback-based API.

Privacy: Publishers must comply with all regional data protection and privacy laws (GDPR, CCPA, etc.) and obtain necessary user consents prior to using the HypeLab SDK. See Privacy & Compliance for details.

All code examples below are in Kotlin.

Installation

Add the HypeLab Maven repository and SDK dependency to your project.

Requirements

RequirementMinimum
Android API level24 (Android 7.0)
Java version17
Kotlin version1.9+

Initialization

Initialize the SDK once in your Application.onCreate() before creating any ad instances.

MyApplication.kt
Copy
import com.hypelab.sdk.HypeLab

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

        HypeLab.initialize(
            context = this,
            propertySlug = "your_property_slug"
        )
    }
}

Don't forget to register your Application class in AndroidManifest.xml:

<application android:name=".MyApplication" ... >

Configuration Parameters

ParameterTypeDefaultDescription
contextContextrequiredApplication context
propertySlugStringrequiredYour HypeLab property slug
environmentEnvironmentPRODUCTIONTarget environment (PRODUCTION, STAGING)
debugBooleanfalseEnable verbose logging to Logcat

You can also initialize with a Config object for more control:

val config = HypeLab.Config(
    propertySlug = "your_property_slug",
    debug = BuildConfig.DEBUG
)
HypeLab.initialize(this, config)

Test Mode

Enable test mode during development to receive test ads that are safe to click:

HypeLab.setTestMode(true)

Banner ads display image or rich media content in fixed-size placements. They are a great starting point for ad monetization.

SizeConstantDimensionsDescription
StandardBannerSize.STANDARD320x50Phone banner
LargeBannerSize.LARGE320x100Large phone banner
MRECBannerSize.MREC300x250Medium rectangle
LeaderboardBannerSize.LEADERBOARD728x90Tablet leaderboard

Usage

MainActivity.kt
Copy
import com.hypelab.sdk.Banner
import com.hypelab.sdk.BannerSize

class MainActivity : AppCompatActivity() {
    private var banner: Banner? = null

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

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

        banner = Banner("your_banner_slug", BannerSize.STANDARD).apply {
            onReady = {
                // Ad is loaded — add the view to your layout
                view?.let { container.addView(it) }
            }
            onError = { error ->
                Log.e("Ad", "Banner error: ${error.message}")
            }
            onImpression = {
                Log.d("Ad", "Banner impression tracked")
            }
            onClick = {
                Log.d("Ad", "Banner clicked")
            }
        }

        banner?.loadAd()
    }

    override fun onDestroy() {
        super.onDestroy()
        banner?.destroy()
    }
}
CallbackSignatureDescription
onReady() -> UnitAd is loaded and view is available
onError(HypeLabError) -> UnitAd failed to load
onImpression() -> UnitViewable impression tracked (MRC standard)
onClick() -> UnitUser clicked the ad
onClose() -> UnitBanner was destroyed
onExpired() -> UnitLoaded ad expired (1-hour TTL)

Lifecycle: Always call banner.destroy() in your Activity or Fragment's onDestroy() to release resources and prevent memory leaks.

Native Ads

Native ads provide structured data (headline, body, images, etc.) that you render in your own UI, giving you full control over the ad's appearance.

Native Ad Assets

PropertyTypeDescription
headlineStringPrimary ad title
advertiserStringAdvertiser/sponsor name
bodyStringAd description text
ctaTextStringCall-to-action button text
displayUrlStringDisplay URL for transparency
iconUrlStringAdvertiser logo/icon URL
imageUrlString?Main image URL (either image or video is present)
videoUrlString?Video URL from VAST (either image or video is present)
starRatingDouble?App store rating (optional)

Usage

NativeAdActivity.kt
Copy
import com.hypelab.sdk.Native
import com.bumptech.glide.Glide

class NativeAdActivity : AppCompatActivity() {
    private var nativeUnit: Native? = null

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

        val container = findViewById<ViewGroup>(R.id.native_ad_container)
        val headline = findViewById<TextView>(R.id.headline)
        val body = findViewById<TextView>(R.id.body)
        val ctaButton = findViewById<Button>(R.id.cta_button)
        val icon = findViewById<ImageView>(R.id.icon)
        val mediaImage = findViewById<ImageView>(R.id.media_image)

        nativeUnit = Native("your_native_slug").apply {
            onReady = { ad ->
                // Bind assets to your views
                headline.text = ad.headline
                body.text = ad.body
                ctaButton.text = ad.ctaText

                // Load images with Glide (or your preferred library)
                Glide.with(this@NativeAdActivity).load(ad.iconUrl).into(icon)
                ad.imageUrl?.let { url ->
                    Glide.with(this@NativeAdActivity).load(url).into(mediaImage)
                }

                // Register view for impression and click tracking
                ad.registerView(container, listOf(ctaButton, headline))

                container.visibility = View.VISIBLE
            }
            onError = { error ->
                Log.e("Ad", "Native error: ${error.message}")
            }
            onImpression = {
                Log.d("Ad", "Native impression tracked")
            }
            onClick = {
                Log.d("Ad", "Native ad clicked")
            }
        }

        nativeUnit?.loadAd()
    }

    override fun onDestroy() {
        super.onDestroy()
        nativeUnit?.destroy()
    }
}

Registering Views for Tracking

After binding assets to your UI, you must call registerView() on the NativeAd object. This enables:

  • Impression tracking - The SDK monitors viewability (MRC standard: 50% visible for 1 second) and fires impression events automatically.
  • Click tracking - Taps on the specified clickable views trigger click events and open the destination URL.
ad.registerView(
    containerView = nativeAdContainer,    // Root view for viewability measurement
    clickableViews = listOf(ctaButton)    // Views that trigger click events
)

If you omit the clickableViews parameter, the entire container becomes clickable.

Native Callbacks

CallbackSignatureDescription
onReady(NativeAd) -> UnitAd is loaded; bind assets and call registerView()
onError(HypeLabError) -> UnitAd failed to load
onImpression() -> UnitViewable impression tracked (MRC standard)
onClick() -> UnitUser clicked the ad
onExpired() -> UnitLoaded ad expired (1-hour TTL)

Image loading: The SDK provides image URLs but does not load images. Use Glide, Coil, or any image loading library you prefer.

Interstitial Ads

Interstitial ads are full-screen ads displayed at natural transition points, such as level completion, app launch, or between content screens.

Usage

Interstitials follow a load-then-show pattern. Load the ad early, then show it when the user reaches a natural break point.

GameActivity.kt
Copy
import com.hypelab.sdk.Interstitial

class GameActivity : AppCompatActivity() {
    private var interstitial: Interstitial? = null

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

        interstitial = Interstitial("your_interstitial_slug").apply {
            onReady = {
                Log.d("Ad", "Interstitial ready to show")
            }
            onError = { error ->
                Log.e("Ad", "Interstitial error: ${error.message}")
            }
            onImpression = {
                Log.d("Ad", "Interstitial impression tracked")
            }
            onClick = {
                Log.d("Ad", "Interstitial clicked")
            }
            onClose = {
                Log.d("Ad", "Interstitial closed")
                // Resume your app flow here
            }
        }

        // Load early so the ad is ready when needed
        interstitial?.loadAd()
    }

    // Show at a natural transition point
    private fun onLevelComplete() {
        if (interstitial?.isReady == true) {
            interstitial?.show()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        interstitial?.destroy()
    }
}

Interstitial Callbacks

CallbackSignatureDescription
onReady() -> UnitAd is loaded and ready to show
onError(HypeLabError) -> UnitAd failed to load or show
onImpression() -> UnitImpression tracked
onClick() -> UnitUser clicked the ad
onClose() -> UnitUser dismissed the ad
onExpired() -> UnitLoaded ad expired (1-hour TTL)

Best practices:

  • Load early (e.g., when the user starts a level) so the ad is ready when needed.
  • Always check isReady before calling show().
  • Show only at natural transition points to preserve user experience.

Rewarded Ads

Rewarded ads let users opt in to watch a video ad in exchange for an in-app reward (extra lives, coins, premium content, etc.). The onReward callback fires when the user has earned the reward.

Usage

RewardedActivity.kt
Copy
import com.hypelab.sdk.Rewarded

class RewardedActivity : AppCompatActivity() {
    private var rewarded: Rewarded? = null

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

        val watchAdButton = findViewById<Button>(R.id.watch_ad_button)
        watchAdButton.isEnabled = false

        rewarded = Rewarded("your_rewarded_slug").apply {
            onReady = {
                watchAdButton.isEnabled = true
            }
            onError = { error ->
                Log.e("Ad", "Rewarded error: ${error.message}")
                watchAdButton.isEnabled = false
            }
            onVideoStart = {
                Log.d("Ad", "Video started playing")
            }
            onVideoComplete = {
                Log.d("Ad", "Video completed")
            }
            onReward = { reward ->
                Log.d("Ad", "Reward earned: ${reward.amount} ${reward.type}")
                // Grant the reward to the user
                grantReward(reward.amount, reward.type)
            }
            onClose = {
                Log.d("Ad", "Rewarded ad closed")
                watchAdButton.isEnabled = false
                // Reload for next time
                rewarded?.loadAd()
            }
        }

        rewarded?.loadAd()

        watchAdButton.setOnClickListener {
            if (rewarded?.isReady == true) {
                rewarded?.show()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        rewarded?.destroy()
    }
}

Rewarded Callbacks

CallbackSignatureDescription
onReady() -> UnitAd is loaded and ready to show
onError(HypeLabError) -> UnitAd failed to load or show
onImpression() -> UnitImpression tracked
onClick() -> UnitUser clicked the ad
onVideoStart() -> UnitVideo started playing
onVideoComplete() -> UnitVideo finished playing
onVideoError(String) -> UnitVideo playback error
onReward(Reward) -> UnitUser earned the reward
onClose() -> UnitUser dismissed the ad
onExpired() -> UnitLoaded ad expired (1-hour TTL)

Reward Object

The onReward callback provides a Reward object:

PropertyTypeDescription
typeStringReward type (e.g., "coins", "gems")
amountIntReward quantity
transactionIdString?Unique ID for server-side verification

Server-Side Verification (SSV)

To verify rewards server-to-server for fraud prevention, set ssvOptions before calling loadAd():

val rewarded = Rewarded("your_rewarded_slug")

// Set SSV options before loading
rewarded.ssvOptions = SSVOptions(
    userID = "user_123",
    customData = "level=5&item=boost"  // Optional URL-encoded data
)

rewarded.onReward = { reward ->
    // The transactionId can be cross-referenced with
    // the server-to-server callback to your SSV endpoint
    Log.d("SSV", "Transaction ID: ${reward.transactionId}")
}

rewarded.loadAd()
SSVOptions PropertyTypeDescription
userIDStringYour unique user identifier
customDataString?Optional URL-encoded custom data

Privacy & Compliance

The SDK provides APIs for GDPR, COPPA, and CCPA compliance. Configure these after initialization and before loading ads.

GDPR / TCF v2.2

If you use a TCF-compliant CMP (e.g., Google UMP, OneTrust), the SDK automatically reads the TC consent string from SharedPreferences. No additional setup is needed.

For manual consent management:

// Set GDPR consent manually
HypeLab.setGDPRConsent(granted = true)

// Tag users under the EU age of consent (typically 16)
HypeLab.setTagForUnderAgeOfConsent(enabled = true)

COPPA

For apps directed at children under 13:

HypeLab.setTagForChildDirectedTreatment(enabled = true)

When enabled, no behavioral targeting or device identifiers are collected.

CCPA / US State Privacy

To enable restricted data processing for users who opt out of data sale:

HypeLab.setRestrictedDataProcessing(enabled = true)

Wallet Addresses

If your app supports crypto wallets, passing wallet addresses enables wallet-targeted ads for higher CPMs:

// When user connects wallet
HypeLab.setWalletAddresses(listOf("0x123...", "0x234..."))

// When user disconnects wallet
HypeLab.clearWalletAddresses()

Error Handling

All onError callbacks receive a HypeLabError sealed class. Use Kotlin's when expression to handle specific cases:

banner.onError = { error ->
    when (error) {
        is HypeLabError.NoFill -> {
            // No ad available — hide the ad container
        }
        is HypeLabError.NetworkError -> {
            // Network issue — retry later
        }
        is HypeLabError.NotInitialized -> {
            // SDK not initialized — call HypeLab.initialize() first
        }
        else -> {
            Log.e("Ad", "Error ${error.code}: ${error.message}")
        }
    }
}

Error Codes

CodeTypeDescription
1001NetworkErrorNetwork connectivity or HTTP error
1002NoFillNo ad available for this placement
1003InvalidPlacementInvalid or unknown placement slug
1004AdExpiredLoaded ad exceeded 1-hour TTL
1005AdAlreadyShowingAttempted to show while another ad is displayed
1006NotInitializedSDK not initialized before use
1007ServerErrorServer returned an error response
1008TimeoutRequest timed out
1009InvalidResponseServer response was malformed
1010LoadInProgressAd load already in progress
1011AdLoadingThrottledToo many requests (rate limited)
1099InternalErrorUnexpected internal error