적응형 인라인 배너

적응형 인라인 배너는 기기마다 광고 크기를 최적화해 최대 효율을 내는 유연한 배너 광고 형식입니다.

이 광고 유형을 사용하면 개발자가 광고의 최대 허용 너비와 높이를 설정할 수 있으며, 최적 광고 크기는 여전히 자동으로 결정됩니다. 최적 크기를 고르기 위해 내장 적응형 배너는 고정 높이가 아니라 최대 높이를 사용합니다. 이를 통해 성능 개선 여지가 생깁니다.

이 형식은 주로 피드형 앱이나 광고에 비중을 두기에 적합한 맥락에서 사용합니다.

표시 예

이 가이드는 Android 앱에 적응형 인라인 배너를 연동하는 방법을 보여 줍니다. 코드 예시와 설명 외에도 형식별 권장 사항과 추가 자료 링크를 포함합니다.

사전 요구 사항

  1. 빠른 시작에 설명된 SDK 통합 단계를 따릅니다.
  2. 미리 광고 SDK를 초기화합니다.
  3. Yandex Mobile Ads SDK의 최신 버전을 사용 중인지 확인합니다. 미디에이션을 사용하는 경우 통합 빌드도 최신 버전인지 확인합니다.

구현

적응형 인라인 배너 연동의 주요 단계:

  • 배너 광고를 표시할 뷰를 만들고 설정합니다.
  • 콜백 메서드 리스너를 등록합니다.
  • 광고를 로드합니다.
  • Adfox를 사용하는 경우 추가 설정을 전달합니다.

적응형 인라인 배너 연동의 특징

  1. Yandex Mobile Ads SDK 메서드 호출은 모두 메인 스레드에서 수행해야 합니다.

  2. 앱 화면에서 동영상 광고를 정상 표시하려면 하드웨어 가속을 켜야 합니다. 기본적으로 하드웨어 가속은 활성화되어 있으나 일부 앱에서는 끕니다. 해당되는 경우 광고를 사용하는 Activity 클래스에 대해 하드웨어 가속을 켜는 것을 권장합니다.

  3. onAdFailedToLoad() 콜백에서 오류가 발생하면 바로 새 광고를 다시 로드하지 마세요. 부득이하면 광고 로드 재시도 횟수를 제한하세요. 제한이 걸린 환경에서 반복적인 실패 요청과 연결 문제를 줄이는 데 도움이 됩니다.

  4. 적응형 인라인 배너가 올바르게 동작하려면 앱 레이아웃을 적응형으로 구성하세요. 그렇지 않으면 광고가 잘못 렌더링될 수 있습니다.

  5. 어댑티브 인라인 배너는 사용 가능한 전체 너비를 쓸 때 가장 잘 동작합니다. 대부분 기기 화면의 전체 너비입니다. 앱에 적용되는 패딩과 안전 표시 영역을 모두 포함하세요.

  6. 적응형 인라인 배너는 스크롤 가능한 콘텐츠 안에 넣도록 설계되었습니다. 기기 화면과 같은 높이일 수도 있고, API에 따라 최대 높이로 제한될 수도 있습니다.

  7. 광고 크기는 BannerAdSize.inlineSize(context, adWidth, maxAdHeight) 메서드로 구합니다. 인자로 광고 컨텍스트, 광고 컨테이너의 사용 가능한 너비, 허용되는 최대 광고 높이를 넘깁니다.

  8. BannerAdSize.inlineSize(context, adWidth, maxAdHeight)로 계산한 BannerAdSize 객체에는 백엔드에서 가장 효과적인 광고 크기를 고르기 위한 기술 데이터가 들어 있습니다. 광고 높이는 로드할 때마다 바뀔 수 있습니다. 실제 광고 너비와 높이는 광고 로드 성공 메시지를 받은 뒤에 알 수 있습니다.

  1. 상단 비클릭 안전 영역의 높이는 80 dp입니다. 해당 영역 안의 컨트롤은 클릭 가능할 수 있습니다.

  2. 시각 요소(에셋)는 닫기 버튼을 포함해 모든 아이콘을 합쳐 최소 32×32 dp 크기여야 합니다.

  3. 에셋 주변 클릭 영역은 최소 64×64 dp여야 합니다. 예를 들어 에셋이 32×32 dp이면 패딩을 두어 전체 클릭 영역이 64×64 dp가 되도록 해야 합니다.

  4. 컨트롤이 지연되어 나타나면 요소가 로드될 때까지 타이머나 진행 표시줄을 표시해야 합니다.

예시

앱 레이아웃에 광고 뷰 추가

배너 광고를 표시하려면 앱 레이아웃에 BannerAdView를 추가해야 합니다. 프로그래밍 방식이나 XML로 추가할 수 있습니다.

앱 화면 레이아웃에 BannerAdView를 추가하는 예:

# activity.xml
...
<com.yandex.mobile.ads.banner.BannerAdView
        android:id="@+id/banner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
...

프로그래밍 방식으로 BannerAdView 객체를 만들 수도 있습니다.

val bannerAd = BannerAdView(this)
final BannerAdView bannerAd = new BannerAdView(this);

광고 로드 및 렌더링

BannerAdView를 만들어 앱 화면에 추가한 뒤에는 광고를 로드해야 합니다. 적응형 인라인 배너를 로드하기 전에 기기마다 광고 크기도 계산해야 합니다.

이 작업은 SDK API BannerAdSize.inlineSize(context, adWidth, maxAdHeight)로 자동 수행됩니다. 인자로 컨텍스트, 광고 컨테이너의 사용 가능한 너비, 허용되는 최대 광고 높이를 넘깁니다. 적응형 인라인 배너는 화면에서 사용 가능한 전체 너비를 쓸 때 가장 잘 동작합니다. 대부분 기기 화면의 전체 너비입니다. 앱에 설정된 패딩과 디스플레이 안전 영역을 반드시 고려하세요.

private val adSize: BannerAdSize
    get() {
        val screenHeight = resources.displayMetrics.run { heightPixels / density }.roundToInt()
        // Calculate the width of the ad, taking into account the padding in the ad container.
        var adWidthPixels = binding.adContainerView.width
        if (adWidthPixels == 0) {
            // If the ad hasn't been laid out, default to the full screen width
            adWidthPixels = resources.displayMetrics.widthPixels
        }
        val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()
        val maxAdHeight = screenHeight / 2

        return BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
    }
@NonNull
private BannerAdSize getAdSize() {
    final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
    final int screenHeight = Math.round(displayMetrics.heightPixels / displayMetrics.density);
    // Calculate the width of the ad, taking into account the padding in the ad container.
    int adWidthPixels = mBinding.adContainerView.getWidth();
    if (adWidthPixels == 0) {
        // If the ad hasn't been laid out, default to the full screen width
        adWidthPixels = displayMetrics.widthPixels;
    }
    final int adWidth = Math.round(adWidthPixels / displayMetrics.density);
    // Determine the maximum allowable ad height. The current value is given as an example.
    final int maxAdHeight = screenHeight / 2;

    return BannerAdSize.inlineSize(this, adWidth, maxAdHeight);
}

광고를 로드하려면 Activity 컨텍스트와 Yandex Advertising Network 인터페이스의 광고 단위 ID(adUnitId)가 필요합니다.

로드 성공·실패 알림과 적응형 인라인 배너의 수명 주기를 추적하려면 BannerAdView 객체에 BannerAdEventListener 콜백 메서드 리스너를 설정합니다.

AdRequest.Builder()로 사용자 관심사, 앱 컨텍스트, 위치 등의 데이터를 넣어 광고 요청 매개변수를 확장할 수 있습니다. 요청에 추가 컨텍스트를 담으면 광고 품질이 크게 향상될 수 있습니다. 자세한 내용은 광고 타기팅을 참고하세요.

아래 예시는 적응형 인라인 배너를 로드하는 방법을 보여 줍니다. 로드에 성공하면 배너가 자동으로 표시됩니다.

class AdaptiveInlineBannerAdActivity : AppCompatActivity(R.layout.activity_inline_banner_ad) {
    private var bannerAd: BannerAdView? = null
    private lateinit var binding: ActivityInlineBannerAdBinding

    private val adSize: BannerAdSize
        get() {
            val screenHeight = resources.displayMetrics.run { heightPixels / density }.roundToInt()
            // Calculate the width of the ad, taking into account the padding in the ad container.
            var adWidthPixels = binding.adContainerView.width
            if (adWidthPixels == 0) {
                // If the ad hasn't been laid out, default to the full screen width
                adWidthPixels = resources.displayMetrics.widthPixels
            }
            val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()
            // Determine the maximum allowable ad height. The current value is given as an example.
            val maxAdHeight = screenHeight / 2

            return BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityInlineBannerAdBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // Since we're loading the banner based on the adContainerView size,
        // we need to wait until this view is laid out before we can get the width
        binding.adContainerView.viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                binding.adContainerView.viewTreeObserver.removeOnGlobalLayoutListener(this);
                bannerAd = loadBannerAd(adSize)
            }
        })
    }

    private fun loadBannerAd(adSize: BannerAdSize): BannerAdView {
        return binding.banner.apply {
            setAdSize(adSize)
            setAdUnitId("your-ad-unit-id")
            setBannerAdEventListener(object : BannerAdEventListener {
                override fun onAdLoaded() {
                    // If this callback occurs after the activity is destroyed, you
                    // must call destroy and return or you may get a memory leak.
                    // Note `isDestroyed` is a method on Activity.
                    if (isDestroyed) {
                        bannerAd?.destroy()
                        return
                    }
                }

                override fun onAdFailedToLoad(adRequestError: AdRequestError) {
                    // Ad failed to load with AdRequestError.
                    // Attempting to load a new ad from the onAdFailedToLoad() method is strongly discouraged.
                }

                override fun onAdClicked() {
                    // Called when a click is recorded for an ad.
                }

                override fun onLeftApplication() {
                    // Called when user is about to leave application (e.g., to go to the browser), as a result of clicking on the ad.
                }

                override fun onReturnedToApplication() {
                    // Called when user returned to application after click.
                }

                override fun onImpression(impressionData: ImpressionData?) {
                    // Called when an impression is recorded for an ad.
                }
            })
            loadAd(
                AdRequest.Builder()
                    // Methods in the AdRequest.Builder class can be used here to specify individual options settings.
                    .build()
            )
        }
    }
}
public class AdaptiveInlineBannerAdActivity extends AppCompatActivity {
    @Nullable
    private BannerAdView mBannerAd = null;
    private ActivityInlineBannerAdBinding mBinding;

    public AdaptiveInlineBannerAdActivity() {
        super(R.layout.activity_inline_banner_ad);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityInlineBannerAdBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());

        // Since we're loading the banner based on the adContainerView size,
        // we need to wait until this view is laid out before we can get the width
        mBinding.adContainerView.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mBinding.adContainerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        mBannerAd = loadBannerAd(getAdSize());
                    }
                }
        );
    }

    @NonNull
    private BannerAdSize getAdSize() {
        final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        final int screenHeight = Math.round(displayMetrics.heightPixels / displayMetrics.density);
        // Calculate the width of the ad, taking into account the padding in the ad container.
        int adWidthPixels = mBinding.adContainerView.getWidth();
        if (adWidthPixels == 0) {
            // If the ad hasn't been laid out, default to the full screen width
            adWidthPixels = displayMetrics.widthPixels;
        }
        final int adWidth = Math.round(adWidthPixels / displayMetrics.density);
        // Determine the maximum allowable ad height. The current value is given as an example.
        final int maxAdHeight = screenHeight / 2;

        return BannerAdSize.inlineSize(this, adWidth, maxAdHeight);
    }

    @NonNull
    private BannerAdView loadBannerAd(@NonNull final BannerAdSize adSize) {
        final BannerAdView bannerAd = mBinding.banner;
        bannerAd.setAdSize(adSize);
        bannerAd.setAdUnitId("your-ad-unit-id");
        bannerAd.setBannerAdEventListener(new BannerAdEventListener() {
            @Override
            public void onAdLoaded() {
                // If this callback occurs after the activity is destroyed, you
                // must call destroy and return or you may get a memory leak.
                // Note `isDestroyed` is a method on Activity.
                if (isDestroyed() && mBannerAd != null) {
                    mBannerAd.destroy();
                }
            }

            @Override
            public void onAdFailedToLoad(@NonNull final AdRequestError adRequestError) {
                // Ad failed to load with AdRequestError.
                // Attempting to load a new ad from the onAdFailedToLoad() method is strongly discouraged.
            }

            @Override
            public void onAdClicked() {
                // Called when a click is recorded for an ad.
            }

            @Override
            public void onLeftApplication() {
                // Called when user is about to leave application (e.g., to go to the browser), as a result of clicking on the ad.
            }

            @Override
            public void onReturnedToApplication() {
                // Called when user returned to application after click.
            }

            @Override
            public void onImpression(@Nullable ImpressionData impressionData) {
                // Called when an impression is recorded for an ad.
            }
        });
        final AdRequest adRequest = new AdRequest.Builder()
                // Methods in the AdRequest.Builder class can be used here to specify individual options settings.
                .build();
        bannerAd.loadAd(adRequest);
        return bannerAd;
    }
}

Adfox를 통해 광고를 게재하는 경우 배너 광고 응답 후 BannerAdView 객체에서 AdAttributes 유형의 adAttributes 속성을 사용해 campaignId, bannerId, placeId 데이터에 접근할 수 있습니다.

리소스 해제

Activity 수명 주기가 끝난 뒤에 콜백 메서드가 호출되면, 광고 객체에 대해 destroy()를 호출해 리소스를 해제하세요.

private fun loadBannerAd(adSize: BannerAdSize): BannerAdView {
    return binding.banner.apply {
        setBannerAdEventListener(object : BannerAdEventListener {
            override fun onAdLoaded() {
                // If this callback occurs after the activity is destroyed, you
                // must call destroy and return or you may get a memory leak.
                // Note `isDestroyed` is a method on Activity.
                if (isDestroyed) {
                    bannerAd?.destroy()
                    return
                }
            }
            ...
        })
        ...
    }
}
@NonNull
private BannerAdView loadBannerAd(@NonNull final BannerAdSize adSize) {
    final BannerAdView bannerAd = mBinding.banner;
    bannerAd.setBannerAdEventListener(new BannerAdEventListener() {
        @Override
        public void onAdLoaded() {
            // If this callback occurs after the activity is destroyed, you
            // must call destroy and return or you may get a memory leak.
            // Note `isDestroyed` is a method on Activity.
            if (isDestroyed() && mBannerAd != null) {
                mBannerAd.destroy();
            }
        }
        ...
    });
    ...
    return bannerAd;
}

적응형 인라인 배너 연동 테스트

광고 테스트를 위한 데모 광고 유닛 사용

적응형 인라인 배너 통합과 앱 자체를 테스트하려면 테스트 광고 사용을 권장합니다.

모든 광고 요청에 테스트 광고가 반환되도록 특별한 데모 광고 게재 ID를 만들었습니다. 광고 통합 확인에 사용하세요.

데모 adUnitId: demo-banner-yandex.

Важно

스토어에 앱을 게시하기 전에 데모 광고 게재 ID를 Yandex Advertising Network 인터페이스에서 받은 실제 ID로 반드시 바꾸세요.

사용 가능한 데모 광고 게재 ID 목록은 테스트용 데모 광고 유닛 섹션에서 확인할 수 있습니다.

광고 통합 테스트

SDK에 내장된 분석기로 적응형 인라인 배너 통합을 테스트할 수 있습니다.

이 도구는 광고가 올바르게 통합되었는지 검사하고 로그에 자세한 보고서를 출력합니다. 보고서를 보려면 Android 앱 디버깅용 Logcat 도구에서 키워드 YandexAds로 검색하세요.

adb logcat -v brief '*:S YandexAds'

통합이 성공하면 다음 메시지가 표시됩니다.

adb logcat -v brief '*:S YandexAds'
mobileads$ adb logcat -v brief '*:S YandexAds'
I/YandexAds(13719): [Integration] Ad type banner was integrated successfully

배너 광고 통합에 문제가 있으면 문제점과 수정 권장 사항이 담긴 자세한 보고서를 받을 수 있습니다.

추가 자료