# Android Integration

This guide shows how to integrate Nexx360 Direct InApp with the Google Mobile Ads SDK on Android.

{% hint style="info" %}
The Nexx360 Direct InApp call must be made **before** the Google Ad Manager ad request. The returned targeting key-values must be set on the `AdManagerAdRequest` before calling `loadAd()`.
{% endhint %}

## Prerequisites

* Google Mobile Ads SDK integrated in your app ([Quick Start Guide](https://developers.google.com/ad-manager/mobile-ads-sdk/android/quick-start))
* A Nexx360 account with a configured `tag_id` or `placement`

## Integration Flow

```
1. App starts ad loading
2. App calls Nexx360 /directinapp endpoint (HTTP GET)
3. Nexx360 returns targeting key-values
4. App creates AdManagerAdRequest with targeting key-values
5. App loads ad via Google Ad Manager SDK
```

## Step 1: Add Network Permission

Ensure your `AndroidManifest.xml` includes internet permission:

```xml
<uses-permission android:name="android.permission.INTERNET" />
```

## Step 2: Create the Nexx360 Helper

Create a helper class to call the Nexx360 endpoint and parse the response:

```kotlin
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.net.URL

object Nexx360DirectInApp {

    private const val BASE_URL = "https://fast.nexx360.io/directinapp"

    data class TargetingResult(
        val targeting: Map<String, String>,
        val success: Boolean
    )

    suspend fun fetchTargeting(
        tagId: String? = null,
        placement: String? = null,
        bundle: String,
        sizes: String,
        ifa: String? = null,
        gdpr: String? = null,
        gdprConsent: String? = null
    ): TargetingResult = withContext(Dispatchers.IO) {
        try {
            val params = mutableListOf<String>()
            if (tagId != null) params.add("tag_id=$tagId")
            if (placement != null) params.add("placement=$placement")
            params.add("bundle=$bundle")
            params.add("sizes=$sizes")
            if (ifa != null) params.add("ifa=$ifa")
            if (gdpr != null) params.add("gdpr=$gdpr")
            if (gdprConsent != null) {
                params.add("gdpr_consent=$gdprConsent")
            }

            val url = URL("$BASE_URL?${params.joinToString("&")}")
            val connection = url.openConnection()
            connection.connectTimeout = 1000
            connection.readTimeout = 1000

            val responseCode =
                (connection as java.net.HttpURLConnection).responseCode

            if (responseCode == 204) {
                return@withContext TargetingResult(emptyMap(), true)
            }

            if (responseCode != 200) {
                return@withContext TargetingResult(emptyMap(), false)
            }

            val body = connection.inputStream
                .bufferedReader().use { it.readText() }
            val json = JSONObject(body)
            val targetingJson = json.getJSONObject("targeting")

            val targeting = mutableMapOf<String, String>()
            targetingJson.keys().forEach { key ->
                targeting[key] = targetingJson.getString(key)
            }

            TargetingResult(targeting, true)
        } catch (e: Exception) {
            TargetingResult(emptyMap(), false)
        }
    }
}
```

## Step 3: Load a Banner Ad with Nexx360 Targeting

```kotlin
import com.google.android.gms.ads.admanager.AdManagerAdRequest
import com.google.android.gms.ads.admanager.AdManagerAdView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class BannerAdLoader(private val adView: AdManagerAdView) {

    fun loadAd() {
        CoroutineScope(Dispatchers.Main).launch {
            // Step 1: Fetch targeting from Nexx360
            val result = Nexx360DirectInApp.fetchTargeting(
                tagId = "your_tag_id",
                bundle = applicationContext.packageName,
                sizes = "300x250,320x50",
                ifa = getAdvertisingId()
            )

            // Step 2: Build the ad request with targeting
            val adRequestBuilder = AdManagerAdRequest.Builder()

            // Step 3: Add Nexx360 targeting key-values
            result.targeting.forEach { (key, value) ->
                adRequestBuilder.addCustomTargeting(key, value)
            }

            // Step 4: Load the ad
            adView.loadAd(adRequestBuilder.build())
        }
    }
}
```

## Step 4: Full Activity Example

```kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.admanager.AdManagerAdRequest
import com.google.android.gms.ads.admanager.AdManagerAdView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    private lateinit var adView: AdManagerAdView

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

        // Initialize Google Mobile Ads SDK
        MobileAds.initialize(this)

        // Set up the ad view
        adView = findViewById(R.id.ad_view)
        adView.setAdSizes(AdSize.MEDIUM_RECTANGLE, AdSize.BANNER)
        adView.adUnitId = "/your-network-id/your-ad-unit"

        // Load ad with Nexx360 header bidding
        loadAdWithNexx360()
    }

    private fun loadAdWithNexx360() {
        CoroutineScope(Dispatchers.Main).launch {
            // Fetch Nexx360 targeting
            val result = Nexx360DirectInApp.fetchTargeting(
                tagId = "your_tag_id",
                bundle = packageName,
                sizes = "300x250,320x50",
                ifa = getAdvertisingId()
            )

            // Build ad request with targeting
            val adRequest = AdManagerAdRequest.Builder().apply {
                result.targeting.forEach { (key, value) ->
                    addCustomTargeting(key, value)
                }
            }.build()

            // Load the ad
            adView.loadAd(adRequest)
        }
    }

    private suspend fun getAdvertisingId(): String? {
        return try {
            val adInfo = com.google.android.gms.ads.identifier
                .AdvertisingIdClient.getAdvertisingIdInfo(this)
            if (adInfo.isLimitAdTrackingEnabled) null
            else adInfo.id
        } catch (e: Exception) {
            null
        }
    }
}
```

## Using Placement Instead of Tag ID

If your Nexx360 setup uses placements, pass the `placement` parameter instead of `tag_id`:

```kotlin
val result = Nexx360DirectInApp.fetchTargeting(
    placement = "my-placement-code",
    bundle = packageName,
    sizes = "300x250,320x50"
)
```

## GDPR Consent

If your app collects GDPR consent (e.g., via a CMP), pass the consent string:

```kotlin
val result = Nexx360DirectInApp.fetchTargeting(
    tagId = "your_tag_id",
    bundle = packageName,
    sizes = "300x250",
    gdpr = "1",
    gdprConsent = "CPMeqrnPMeqrn..."
)
```

{% hint style="warning" %}
Always call the Nexx360 endpoint **before** `loadAd()`. The targeting key-values must be present in the `AdManagerAdRequest` for the bid to compete in Google Ad Manager.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.nexx360.io/integration-methods/direct-inapp-sdkless/android-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
