앱 오프닝 광고

이 가이드는 Google 애널리틱스 API를 사용하여 앱 오프닝 광고를 통합하는 게시자를 위해 모바일 광고 SDK에 오신 것을 환영합니다.

앱 오프닝 광고는 수익을 창출하려는 게시자를 위한 특수한 광고 형식입니다. 확인할 수 있습니다. 앱 오프닝 광고는 언제든지 닫을 수 있으며 사용자가 앱을 포그라운드로 가져올 때 표시됩니다.

앱 오프닝 광고에는 작은 브랜딩 영역이 자동으로 표시되므로 사용자가 어디에 있는지 알 수 있습니다. 있습니다. 다음은 앱 오프닝 광고의 예입니다.

기본 요건

항상 테스트 광고로 테스트

앱을 빌드하고 테스트할 때는 만들 수 있습니다. 이렇게 하지 않으면 계정이 정지될 수 있습니다.

테스트 광고를 로드하는 가장 쉬운 방법은 앱 전용 테스트 광고 단위 ID를 사용하는 것입니다. 광고 열기:

ca-app-pub-3940256099942544/9257395921

이 ID는 모든 요청에 대해 테스트 광고를 반환하도록 특별히 구성되었으며, 코딩, 테스트, 디버깅 중에 앱에서 자유롭게 사용할 수 있습니다. 원하는 대로 앱을 게시하기 전에 이 ID를 자체 광고 단위 ID로 바꿔야 합니다.

Google 모바일 광고 SDK의 테스트 광고가 작동하는 방식을 자세히 알아보려면 테스트 광고 사용 설정을 참고하세요.

Application 클래스 확장

Application 클래스를 확장하는 새 클래스를 만들고 다음을 추가합니다. 코드를 사용하여 앱 시작 시 Google 모바일 광고 SDK를 초기화하세요.

자바

/** Application class that initializes, loads and show ads when activities change states. */
public class MyApplication extends Application {

  @Override
  public void onCreate() {
    super.onCreate();
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
  }
}

Kotlin

/** Application class that initializes, loads and show ads when activities change states. */
class MyApplication : Application() {

  override fun onCreate() {
    super.onCreate()
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
  }
}

이렇게 하면 SDK가 초기화되고 나중에 등록할 스켈레톤이 제공됩니다. 사용할 수 있습니다.

다음으로 AndroidManifest.xml에 다음 코드를 추가합니다.

<!-- TODO: Update to reference your actual package name. -->
<application
    android:name="com.google.android.gms.example.appopendemo.MyApplication" ...>
...
</application>

유틸리티 구성요소 구현

광고는 빠르게 게재되어야 하므로 광고를 게재하기 전에 미리 로드하는 것이 좋습니다. 이렇게 하면 사용자가 사이트를 방문하자마자 바로 광고를 시작할 수 있습니다. 삽입해야 합니다.

유틸리티 구성요소 AppOpenAdManager를 구현하여 미리 광고를 요청합니다. 광고를 게재해야 할 때

자바

public class MyApplication extends Application {
  // ...
  /** Inner class that loads and shows app open ads. */
  private class AppOpenAdManager {
    private static final String LOG_TAG = "AppOpenAdManager";
    private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/9257395921";

    private AppOpenAd appOpenAd = null;
    private boolean isLoadingAd = false;
    private boolean isShowingAd = false;

    /** Constructor. */
    public AppOpenAdManager() {}

    /** Request an ad. */
    private void loadAd(Context context) {
      // We will implement this later.
    }

    /** Check if ad exists and can be shown. */
    private boolean isAdAvailable() {
      return appOpenAd != null;
    }
  }
}

Kotlin

private const val String LOG_TAG = "AppOpenAdManager"
private const val String AD_UNIT_ID = "ca-app-pub-3940256099942544/9257395921"

public class MyApplication extends Application {
  // ...
  /** Inner class that loads and shows app open ads. */
  private inner class AppOpenAdManager {
    private var appOpenAd: AppOpenAd? = null
    private var isLoadingAd = false
    var isShowingAd = false

    /** Request an ad. */
    fun loadAd(context: Context) {
      // We will implement this later.
    }

    /** Check if ad exists and can be shown. */
    private fun isAdAvailable(): Boolean {
      return appOpenAd != null
    }
  }
}

이제 유틸리티 클래스가 있으므로 이 클래스를 MyApplication 클래스:

자바

public class MyApplication extends Application {

  private AppOpenAdManager appOpenAdManager;

  @Override
  public void onCreate() {
    super.onCreate();
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
    appOpenAdManager = new AppOpenAdManager(this);
  }
}

Kotlin

class MyApplication : Application() {

  private lateinit var appOpenAdManager: AppOpenAdManager

  override fun onCreate() {
    super.onCreate()
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
    appOpenAdManager = AppOpenAdManager()
  }
}

광고 로드

다음 단계는 loadAd() 메서드를 작성하고 광고 로드를 처리하는 것입니다. 있습니다.

자바

private class AppOpenAdManager {
  // ...
  /** Request an ad. */
  public void loadAd(Context context) {
    // Do not load ad if there is an unused ad or one is already loading.
    if (isLoadingAd || isAdAvailable()) {
      return;
    }

    isLoadingAd = true;
    AdRequest request = new AdRequest.Builder().build();
    AppOpenAd.load(
        context, AD_UNIT_ID, request,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        new AppOpenAdLoadCallback() {
          @Override
          public void onAdLoaded(AppOpenAd ad) {
            // Called when an app open ad has loaded.
            Log.d(LOG_TAG, "Ad was loaded.");
            appOpenAd = ad;
            isLoadingAd = false;
            loadTime = (new Date()).getTime();
          }

          @Override
          public void onAdFailedToLoad(LoadAdError loadAdError) {
            // Called when an app open ad has failed to load.
            Log.d(LOG_TAG, loadAdError.getMessage());
            isLoadingAd = false;
          }
        });
  }
  // ...
}

Kotlin

private inner class AppOpenAdManager {
  // ...
  /** Request an ad. */
  fun loadAd(context: Context) {
    // Do not load ad if there is an unused ad or one is already loading.
    if (isLoadingAd || isAdAvailable()) {
      return
    }

    isLoadingAd = true
    val request = AdRequest.Builder().build()
    AppOpenAd.load(
        context, AD_UNIT_ID, request,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        object : AppOpenAdLoadCallback() {

          override fun onAdLoaded(ad: AppOpenAd) {
            // Called when an app open ad has loaded.
            Log.d(LOG_TAG, "Ad was loaded.")
            appOpenAd = ad
            isLoadingAd = false
            loadTime = Date().time
          }

          override fun onAdFailedToLoad(loadAdError: LoadAdError) {
            // Called when an app open ad has failed to load.
            Log.d(LOG_TAG, loadAdError.message)
            isLoadingAd = false;
          }
        })
  }
  // ...
}

광고 표시 및 전체 화면 콜백 이벤트 처리

가장 일반적인 앱 오프닝 구현은 앱 오프닝 광고 게재를 시도하는 것입니다. 앱 실행 직전에 광고가 준비되지 않은 경우 앱 콘텐츠를 시작하고 다른 광고를 미리 로드합니다. 다음번 앱 오프닝 기회를 놓치지 마세요 구현 예시는 앱 오프닝 광고 안내를 참고하세요.

다음 코드는 광고를 표시한 후 다시 로드하는 방법을 보여줍니다.

자바

public class MyApplication extends Application {
  // ...
  /** Interface definition for a callback to be invoked when an app open ad is complete. */
  public interface OnShowAdCompleteListener {
    void onShowAdComplete();
  }

  private class AppOpenAdManager {
    // ...

    /** Shows the ad if one isn't already showing. */
    public void showAdIfAvailable(
        @NonNull final Activity activity,
        @NonNull OnShowAdCompleteListener onShowAdCompleteListener){
      // If the app open ad is already showing, do not show the ad again.
      if (isShowingAd) {
        Log.d(LOG_TAG, "The app open ad is already showing.");
        return;
      }

      // If the app open ad is not available yet, invoke the callback then load the ad.
      if (!isAdAvailable()) {
        Log.d(LOG_TAG, "The app open ad is not ready yet.");
        onShowAdCompleteListener.onShowAdComplete();
        loadAd(activity);
        return;
      }

      appOpenAd.setFullScreenContentCallback(
          new FullScreenContentCallback() {

            @Override
            public void onAdDismissedFullScreenContent() {
              // Called when fullscreen content is dismissed.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, "Ad dismissed fullscreen content.");
              appOpenAd = null;
              isShowingAd = false;

              onShowAdCompleteListener.onShowAdComplete();
              loadAd(activity);
            }

            @Override
            public void onAdFailedToShowFullScreenContent(AdError adError) {
              // Called when fullscreen content failed to show.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, adError.getMessage());
              appOpenAd = null;
              isShowingAd = false;

              onShowAdCompleteListener.onShowAdComplete();
              loadAd(activity);
            }

            @Override
            public void onAdShowedFullScreenContent() {
              // Called when fullscreen content is shown.
              Log.d(LOG_TAG, "Ad showed fullscreen content.");
            }
          });
      isShowingAd = true;
      appOpenAd.show(activity);
    }
    // ...
  }
}

Kotlin

class MyApplication : Application() {
  // ...
  /** Interface definition for a callback to be invoked when an app open ad is complete. */
  interface OnShowAdCompleteListener {
    fun onShowAdComplete()
  }

  private inner class AppOpenAdManager {
    // ...

    /** Shows the ad if one isn't already showing. */
    fun showAdIfAvailable(
        activity: Activity,
        onShowAdCompleteListener: OnShowAdCompleteListener) {
      // If the app open ad is already showing, do not show the ad again.
      if (isShowingAd) {
        Log.d(LOG_TAG, "The app open ad is already showing.")
        return
      }

      // If the app open ad is not available yet, invoke the callback then load the ad.
      if (!isAdAvailable()) {
        Log.d(LOG_TAG, "The app open ad is not ready yet.")
        onShowAdCompleteListener.onShowAdComplete()
        loadAd(activity)
        return
      }

      appOpenAd?.setFullScreenContentCallback(
          object : FullScreenContentCallback() {

            override fun onAdDismissedFullScreenContent() {
              // Called when full screen content is dismissed.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, "Ad dismissed fullscreen content.")
              appOpenAd = null
              isShowingAd = false

              onShowAdCompleteListener.onShowAdComplete()
              loadAd(activity)
            }

            override fun onAdFailedToShowFullScreenContent(adError: AdError) {
              // Called when fullscreen content failed to show.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, adError.message)
              appOpenAd = null
              isShowingAd = false

              onShowAdCompleteListener.onShowAdComplete()
              loadAd(activity)
            }

            override fun onAdShowedFullScreenContent() {
              // Called when fullscreen content is shown.
              Log.d(LOG_TAG, "Ad showed fullscreen content.")
            }
          })
      isShowingAd = true
      appOpenAd?.show(activity)
    }
    // ...
  }
}

FullScreenContentCallback 광고가 표시되거나, 표시되지 않거나, 광고가 게재될 때와 같은 닫았습니다.

광고 만료 고려

만료된 광고가 게재되지 않도록 하려면 AppOpenAdManager에 메서드를 추가하세요. 광고 참조가 로드된 후 경과한 시간을 확인합니다. 그런 다음 메서드를 사용하여 광고가 여전히 유효한지 확인합니다.

자바

private class AppOpenAdManager {
  // ...
  /** Keep track of the time an app open ad is loaded to ensure you don't show an expired ad. */
  private long loadTime = 0;

  // ...

  /** Utility method to check if ad was loaded more than n hours ago. */
  private boolean wasLoadTimeLessThanNHoursAgo(long numHours) {
    long dateDifference = (new Date()).getTime() - this.loadTime;
    long numMilliSecondsPerHour = 3600000;
    return (dateDifference < (numMilliSecondsPerHour * numHours));
  }

  /** Check if ad exists and can be shown. */
  public boolean isAdAvailable() {
    return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4);
  }
}

Kotlin

private inner class AppOpenAdManager {
  // ...
  /** Keep track of the time an app open ad is loaded to ensure you don't show an expired ad. */
  private var loadTime: Long = 0;

  // ...

  /** Utility method to check if ad was loaded more than n hours ago. */
  private fun wasLoadTimeLessThanNHoursAgo(numHours: Long): Boolean {
    val dateDifference: Long = Date().time - loadTime
    val numMilliSecondsPerHour: Long = 3600000
    return dateDifference < numMilliSecondsPerHour * numHours
  }

  /** Check if ad exists and can be shown. */
  private fun isAdAvailable(): Boolean {
    return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4)
  }
}

현재 활동 추적

광고를 게재하려면 Activity 컨텍스트가 필요합니다. 사용 중인 최신 활동을 추적하려면 Application.ActivityLifecycleCallbacks를 등록하고 구현합니다.

자바

public class MyApplication extends Application implements ActivityLifecycleCallbacks {

  private Activity currentActivity;

  @Override
  public void onCreate() {
    super.onCreate();
    this.registerActivityLifecycleCallbacks(this);
    // ...
  }

  /** ActivityLifecycleCallback methods. */
  @Override
  public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

  @Override
  public void onActivityStarted(Activity activity) {
    currentActivity = activity
  }

  @Override
  public void onActivityResumed(Activity activity) {}

  @Override
  public void onActivityStopped(Activity activity) {}

  @Override
  public void onActivityPaused(Activity activity) {}

  @Override
  public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {}

  @Override
  public void onActivityDestroyed(Activity activity) {}
}

Kotlin

class MyApplication : Application(), Application.ActivityLifecycleCallbacks {

  private var currentActivity: Activity? = null

  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(this)
    // ...
  }

  /** ActivityLifecycleCallback methods. */
  override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}

  override fun onActivityStarted(activity: Activity) {
    currentActivity = activity
  }

  override fun onActivityResumed(activity: Activity) {}

  override fun onActivityPaused(activity: Activity) {}

  override fun onActivityStopped(activity: Activity) {}

  override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

  override fun onActivityDestroyed(activity: Activity) {}
}

registerActivityLifecycleCallbacks 드림 모든 Activity 이벤트를 수신 대기할 수 있습니다. 활동이 시작되고 소멸될 때를 수신하여 현재 Activity에 대한 참조를 추적할 수 있고, 이 참조는 앱 오프닝 광고를 표시하는 데 사용됩니다.

앱 포그라운드 이벤트 수신

gradle 파일에 라이브러리 추가

앱 포그라운드 이벤트에 대한 알림을 받으려면 DefaultLifecycleObserver 앱 수준 빌드 파일에 종속 항목을 추가합니다.

Kotlin

  dependencies {
    implementation("com.google.android.gms:play-services-ads:23.3.0")
    implementation("androidx.lifecycle:lifecycle-process:2.8.3")
  }

Groovy

  dependencies {
    implementation 'com.google.android.gms:play-services-ads:23.3.0'
    implementation 'androidx.lifecycle:lifecycle-process:2.8.3'
  }

수명 주기 관찰자 인터페이스 구현

다음과 같은 방법으로 포그라운드 이벤트를 수신 대기할 수 있습니다. DefaultLifecycleObserver 인터페이스

onStart 이벤트를 구현하여 앱 오프닝 광고를 표시합니다.

자바

public class MyApplication extends Application
    implements ActivityLifecycleCallbacks, LifecycleObserver {
  // ...
  @Override
  public void onCreate() {
    super.onCreate();
    this.registerActivityLifecycleCallbacks(this);
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
    ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    appOpenAdManager = new AppOpenAdManager();
  }

  /** LifecycleObserver method that shows the app open ad when the app moves to foreground. */
  @OnLifecycleEvent(Event.ON_START)
  protected void onMoveToForeground() {
    // Show the ad (if available) when the app moves to foreground.
    appOpenAdManager.showAdIfAvailable(currentActivity);
  }

  /** Show the ad if one isn't already showing. */
  private void showAdIfAvailable(@NonNull final Activity activity) {
      showAdIfAvailable(
          activity,
          new OnShowAdCompleteListener() {
            @Override
            public void onShowAdComplete() {
              // Empty because the user will go back to the activity that shows the ad.
            }
          });
  }
}

Kotlin

class MyApplication : Application(),
    Application.ActivityLifecycleCallbacks, LifecycleObserver {
  // ...
  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(this)
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
    ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    appOpenAdManager = AppOpenAdManager()
  }

  /** LifecycleObserver method that shows the app open ad when the app moves to foreground. */
  @OnLifecycleEvent(Lifecycle.Event.ON_START)
  fun onMoveToForeground() {
    // Show the ad (if available) when the app moves to foreground.
    currentActivity?.let {
      appOpenAdManager.showAdIfAvailable(it)
    }
  }

  /** Show the ad if one isn't already showing. */
  fun showAdIfAvailable(activity: Activity) {
    showAdIfAvailable(
        activity,
        object : OnShowAdCompleteListener {
          override fun onShowAdComplete() {
            // Empty because the user will go back to the activity that shows the ad.
          }
        })
  }
}

콜드 스타트 및 로드 화면

지금까지 문서에서는 사용자가 앱 오프닝 광고를 메모리에서 정지된 경우 앱을 포그라운드로 설정하세요. '콜드 스타트' 은(는) 다음과 같은 경우에 발생합니다. 앱이 실행되었지만 이전에 메모리에서 정지되지 않았어야 합니다.

콜드 스타트의 예로는 사용자가 앱을 처음 여는 경우를 들 수 있습니다. 콜드 스타트를 사용하면 이전에 로드한 앱 오프닝 광고가 없지만 바로 표시되도록 할 수 있습니다. 광고를 요청하고 광고를 수신하는 시점 사이에 지연 시간이 발생하면 사용자가 그 잠깐 동안 앱을 사용하다가 갑작스럽게 광고가 게재되며 불편을 겪을 수 있습니다. 이것은 피해야 하는 부정적인 사용자 경험을 제공할 수 있습니다

콜드 스타트 시 앱 오프닝 광고를 사용하는 좋은 방법은 로드 화면을 사용하는 것입니다. 를 설정하여 게임 또는 앱 애셋을 로드하고 화면에 나타납니다. 앱 로드가 완료되고 사용자를 기본 광고를 게재하지 않습니다.

권장사항

앱 오프닝 광고를 사용하면 앱이 처음 실행될 때 앱의 로드 화면에서 수익을 창출할 수 있습니다. 앱 전환 시에 변경사항을 적용할 수도 있지만 권장사항을 유지하는 것이 사용자가 앱을 즐겁게 사용할 수 있도록 해야 합니다. 가장 좋은 방법은 다음과 같습니다.

  • 사용자가 앱을 몇 번 사용한 후에 첫 앱 오프닝 광고를 게재하세요.
  • 사용자가 기다리지 않을 시간에 앱 오프닝 광고 게재 최대 24시간이 필요합니다.
  • 앱 오프닝 광고 아래에 로드 화면이 있고 로드 화면이 있는 경우 광고가 닫히기 전에 로드가 완료된 경우 onAdDismissedFullScreenContent() 메서드의 로드 중 화면

GitHub의 예

다음 단계

다음 주제를 살펴보세요.