# Banner Ad

## 1. 기본 요건

* [ADX Android SDK](/adx/android/integrate.md#2-adx-android-sdk)를 프로젝트에 추가합니다.
* Banner Ad용으로 발급받은 Ad Unit ID를 사용합니다.
* 광고를 요청하기 전에 [SDK 초기화](/adx/android/sdk-integration/initialize.md)를 먼저 진행합니다.
  * **SDK 초기화는 앱 실행 시 한 번만 호출**하여 주시고, **광고 요청은 초기화가 완료된 후**에 이뤄져야 합니다.

## 2. 레이아웃 설정

광고를 게재할 `Activity` 또는 `Fragment` 레이아웃에 `BannerAd` 를 추가합니다.

* Ad Unit ID와 배너 광고의 사이즈를 입력합니다.
* 지원되는 사이즈는 아래와 같으며 필수로 입력하셔야 합니다.

  ```
  AD_SIZE_320x50, AD_SIZE_728x90, AD_SIZE_320x100, AD_SIZE_300x250
  ```

```markup
<com.adxcorp.ads.BannerAd
    android:id="@+id/banner"
    android:layout_width="320dp"
    android:layout_height="50dp"
    app:ADX_UNIT_ID="<BANNER_AD_UNIT_ID>"
    app:BANNER_AD_SIZE="AD_SIZE_320x50">
</com.adxcorp.ads.BannerAd>
```

## 3. 광고 객체 생성

레이아웃 설정 대신 직접 코드로 작성할 경우 광고를 게재할 `Activity` 또는 `Fragment` 에 `BannerAd` 를 추가합니다.

* Ad Unit ID와 배너 광고의 사이즈를 입력합니다.
* 지원되는 사이즈는 아래와 같으며 필수로 입력하셔야 합니다.

  ```
  AD_SIZE_320x50, AD_SIZE_728x90, AD_SIZE_320x100, AD_SIZE_300x250
  ```

{% tabs %}
{% tab title="Java" %}

```java
public class BannerActivity extends AppCompatActivity {

    private com.adxcorp.ads.BannerAd bannerAd;
    private RelativeLayout container;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_banner);

        bannerAd = new BannerAd(this, "<BANNER_AD_UNIT_ID>", AdConstants.BANNER_AD_SIZE.AD_SIZE_300x250);
        container = (RelativeLayout) findViewById(R.id.container);

        container.addView(bannerAd);
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class BannerActivity : AppCompatActivity() {

    private var bannerAd: BannerAd? = null
    private var container: RelativeLayout? = null

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

        bannerAd = BannerAd(this, "<BANNER_AD_UNIT_ID>", AdConstants.BANNER_AD_SIZE.AD_SIZE_320x50)

        container = findViewById<RelativeLayout>(R.id.container)
        container?.addView(bannerAd)
    }
}
```

{% endtab %}
{% endtabs %}

## 4. 구현

1. `BannerAd`를 인스턴스화하고 `BannerAdListener`를 추가합니다.
2. `loadAd()` 를 호출하여 광고를 로드합니다.
3. 노출 종료 시 `onDestroy()`에 `BannerAd`의 `destroy()`를 호출하여 `BannerAd`를 제거합니다.

{% tabs %}
{% tab title="Java" %}

```java
public class BannerActivity extends AppCompatActivity {

    private com.adxcorp.ads.BannerAd bannerAd;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_banner);

        bannerAd = findViewById(R.id.banner);
        bannerAd.setBannerListener(new BannerAd.BannerListener() {
            @Override
            public void onAdLoaded() {
            }

            @Override
            public void onAdError(int errorCode) {
            }

            @Override
            public void onAdClicked() {
            }
        });

        bannerAd.loadAd();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (bannerAd != null) {
            bannerAd.destroy();
            bannerAd = null;
        }
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class BannerActivity : AppCompatActivity() {

    private var bannerAd: BannerAd? = null

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

        bannerAd = findViewById(R.id.banner)
        bannerAd?.setBannerListener(object : BannerAd.BannerListener {
            override fun onAdLoaded() {
            }

            override fun onAdError(errorCode: Int) {
            }

            override fun onAdClicked() {
            }
        })

        bannerAd?.loadAd()
    }

    override fun onDestroy() {
        super.onDestroy()

        bannerAd?.destroy()
        bannerAd = null
    }
}
```

{% endtab %}
{% endtabs %}

## 5. Callback

`BannerAd`의 `BannerListener`를 설정하여 특정 이벤트를 수신할 수 있습니다. 필요에 따라 구현해주세요.

{% tabs %}
{% tab title="Java" %}

```java
bannerAd.setBannerListener(new BannerAd.BannerListener() {
    @Override
    public void onAdLoaded() {
    }

    @Override
    public void onAdError(int errorCode) {
    }

    @Override
    public void onAdClicked() {
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
bannerAd?.setBannerListener(object : BannerAd.BannerListener {
    override fun onAdLoaded() {
    }

    override fun onAdError(errorCode: Int) {
    }

    override fun onAdClicked() {
    }
})
```

{% endtab %}
{% endtabs %}

## 6. Ad Revenue (OnPaidEvent)

* 광고 노출이 발생동안 예상되는 광고 수익을 받아볼 수 있습니다.
* 이는 미디에이션 설정 과정에서 수동적으로 설정한 값과 정확한 값이 섞여 있어서 예상 값으로 사용하시는 것을 권장드립니다.
* ecpm의 currency는 **USD**입니다.
* 아래와 같이 <mark style="color:red;">`OnPaidEvent`</mark> 콜백을 등록하여 사용하시면 됩니다.
* 광고 매출 데이터를 MMP와 연동할 수 있습니다. 자세한 사항은 아래 SDK 연동 가이드를 참조해 주십시오.
  * [애드저스트(Adjust)의 AD(X) SDK 연동 가이드](https://dev.adjust.com/ko/sdk/android/integrations/adx)
  * [에어브릿지(Airbridge)의 AD(X) SDK 연동 가이드](https://help.airbridge.io/ko/developers/ad-x-ad-revenue-integration#sdk-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-android)

{% tabs %}
{% tab title="Java" %}

```java
 bannerAd.setOnPaidEventListener(new OnPaidEventListener() {
    @Override
    public void onPaidEvent(double ecpm) {
        // Firebase Analytics 샘플
        double revenue = ecpm / 1000;

        mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
        Bundle params = new Bundle();
        params.putString(FirebaseAnalytics.Param.AD_PLATFORM, "AD(X)");
        params.putString(FirebaseAnalytics.Param.AD_FORMAT, "BannerAd");
        params.putString(FirebaseAnalytics.Param.AD_UNIT_NAME, "ADX Banner Ad");
        params.putDouble(FirebaseAnalytics.Param.VALUE, revenue);
        params.putString(FirebaseAnalytics.Param.CURRENCY, "USD");
        mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION, params);
        
        /// AppsFlyer 샘플
        double revenue = ecpm / 1000;

        Map<String, String> customParams = new HashMap<>();
        customParams.put(Scheme.AD_TYPE, "BannerAd");
        customParams.put("ad_unit_name", "ADX Banner Ad");

        AppsFlyerAdRevenue.logAdRevenue(
              "AD(X)",
              MediationNetwork.customMediation,
              Currency.getInstance(Locale.US),
              revenue,
              customParams
        );
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
bannerAd.setOnPaidEventListener(object : OnPaidEventListener() {
    fun onPaidEvent(ecpm: Double) {
        /// Firebase Analytics 샘플
        val revenue: Double = ecpm / 1000

        firebaseAnalytics = Firebase.analytics
        firebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION) {
            param(FirebaseAnalytics.Param.AD_PLATFORM, "AD(X)")
            param(FirebaseAnalytics.Param.AD_UNIT_NAME, "ADX Banner Ad")
            param(FirebaseAnalytics.Param.AD_FORMAT, "BannerAd")
            param(FirebaseAnalytics.Param.VALUE, revenue)
            param(FirebaseAnalytics.Param.CURRENCY, "USD")
        }
        
        /// AppsFlyer 샘플
        val revenue: Double = ecpm / 1000

        val customParams: MutableMap<String, String> = HashMap()
        customParams[Scheme.AD_TYPE] = "BannerAd"
        customParams["ad_unit_name"] = "ADX Banner Ad"
        
        AppsFlyerAdRevenue.logAdRevenue(
            "AD(X)",
            MediationNetwork.customMediation,
            Currency.getInstance(Locale.US),
            revenue,
            customParams
        )
    }
})
```

{% endtab %}
{% endtabs %}


---

# 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://platform-business.gitbook.io/adx/android/sdk-integration/ad-formats/banner-ad.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.
