开屏广告

请选择平台Android iOS Unity Flutter

本指南面向希望使用 Google 移动广告 SDK 集成开屏广告的发布商。

开屏广告是一种特殊的广告格式,适合希望通过应用加载屏幕创收的发布商。开屏广告在用户将您的应用切换为在前台运行时展示,用户可随时关闭。

开屏广告会自动在一个较小的区域内展示您的品牌信息,让用户知道他们是在您的应用中。以下是一个开屏广告示例:

前提条件

务必用测试广告进行测试

在构建和测试应用时,请确保使用的是测试广告,而不是实际投放的广告。否则,可能会导致您的账号被中止。

对于开屏广告,加载测试广告最简便的方法就是使用下面的测试专用广告单元 ID:

ca-app-pub-3940256099942544/9257395921

该测试广告单元 ID 已经过专门配置,可确保每个请求返回的都是测试广告。您可以在自己应用的编码、测试和调试过程中随意使用该测试广告单元 ID。需要注意的一点是,请务必在发布应用前用您的广告单元 ID 替换该测试广告单元 ID。

如需详细了解 Google 移动广告 SDK 的测试广告如何运作,请参阅启用测试广告

扩展 Application 类

创建一个扩展 Application 类的新类。这提供了一种可感知生命周期的方式来管理与应用状态(而非单个 Activity)相关联的广告:

Java

public class MyApplication extends Application
    implements ActivityLifecycleCallbacks, DefaultLifecycleObserver {

  private AppOpenAdManager appOpenAdManager;
  private Activity currentActivity;

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

    ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    appOpenAdManager = new AppOpenAdManager();
  }

Kotlin

class MyApplication :
  MultiDexApplication(), Application.ActivityLifecycleCallbacks, DefaultLifecycleObserver {

  private lateinit var appOpenAdManager: AppOpenAdManager
  private var currentActivity: Activity? = null

  override fun onCreate() {
    super<MultiDexApplication>.onCreate()
    registerActivityLifecycleCallbacks(this)

    ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    appOpenAdManager = AppOpenAdManager()
  }

接下来,将以下代码添加到您的 AndroidManifest.xml 中:

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

实现实用工具组件

您的广告应该要快速展示,因此最好先加载广告,以备需要展示时使用。这样一来,用户进入您的应用后,广告便可以立即展示。

实现一个实用程序组件 AppOpenAdManager,以封装与加载和展示开屏广告相关的工作:

Java

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;

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

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

Kotlin

private inner class AppOpenAdManager {

  private var appOpenAd: AppOpenAd? = null
  private var isLoadingAd = false
  var isShowingAd = false

  /** 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

如需使用 AppOpenAdManager,请调用单例 MyApplication 实例上的公共封装容器方法。Application 类与其余代码进行交互,将加载和展示广告的工作委托给管理器。

加载广告

下一步是填充 loadAd() 方法并处理广告加载回调。

Java

AppOpenAd.load(
    context,
    "AD_UNIT_ID",
    new AdRequest.Builder().build(),
    new AppOpenAdLoadCallback() {
      @Override
      public void onAdLoaded(AppOpenAd ad) {
        // Called when an app open ad has loaded.
        Log.d(LOG_TAG, "App open ad 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, "App open ad failed to load with error: " + loadAdError.getMessage());

        isLoadingAd = false;
      }
    });

Kotlin

AppOpenAd.load(
  context,
  "AD_UNIT_ID",
  AdRequest.Builder().build(),
  object : AppOpenAdLoadCallback() {
    override fun onAdLoaded(ad: AppOpenAd) {
      // Called when an app open ad has loaded.
      Log.d(LOG_TAG, "App open ad 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, "App open ad failed to load with error: " + loadAdError.message)

      isLoadingAd = false
    }
  },
)

AD_UNIT_ID 替换为您自己的广告单元 ID。

展示广告

最常见的开屏广告实现方式是在应用启动时尝试展示开屏广告,如果广告未准备就绪,则启动应用内容,并预加载另一个广告以备下次展示开屏广告。如需查看实现示例,请参阅开屏广告指南

以下代码展示了如何展示广告,然后重新加载广告:

Java

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(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 (appOpenAd == null) {
    Log.d(TAG, "The app open ad is not ready yet.");
    onShowAdCompleteListener.onShowAdComplete();
    // Load an ad.
    return;
  }

  isShowingAd = true;
  appOpenAd.show(activity);
}

Kotlin

fun showAdIfAvailable(activity: Activity, onShowAdCompleteListener: OnShowAdCompleteListener) {
  // If the app open ad is already showing, do not show the ad again.
  if (isShowingAd) {
    Log.d(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 (appOpenAd == null) {
    Log.d(TAG, "The app open ad is not ready yet.")
    onShowAdCompleteListener.onShowAdComplete()
    // Load an ad.
    return
  }

  isShowingAd = true
  appOpenAd?.show(activity)
}

设置 FullScreenContentCallback

FullScreenContentCallback 处理与展示 AppOpenAd 相关的事件。在展示 AppOpenAd 之前,请务必按如下方式设置回调:

Java

appOpenAd.setFullScreenContentCallback(
    new FullScreenContentCallback() {
      @Override
      public void onAdDismissedFullScreenContent() {
        // Called when full screen content is dismissed.
        Log.d(TAG, "Ad dismissed fullscreen content.");
        // Don't forget to set the ad reference to null so you
        // don't show the ad a second time.
        appOpenAd = null;
        isShowingAd = false;

        onShowAdCompleteListener.onShowAdComplete();
        // Load an ad.
      }

      @Override
      public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
        // Called when full screen content failed to show.
        Log.d(TAG, adError.getMessage());
        appOpenAd = null;
        // Don't forget to set the ad reference to null so you
        // don't show the ad a second time.
        isShowingAd = false;

        onShowAdCompleteListener.onShowAdComplete();
        // Load an ad.
      }

      @Override
      public void onAdShowedFullScreenContent() {
        Log.d(TAG, "Ad showed fullscreen content.");
      }

      @Override
      public void onAdImpression() {
        // Called when an impression is recorded for an ad.
        Log.d(TAG, "The ad recorded an impression.");
      }

      @Override
      public void onAdClicked() {
        // Called when ad is clicked.
        Log.d(TAG, "The ad was clicked.");
      }
    });

Kotlin

appOpenAd?.fullScreenContentCallback =
  object : FullScreenContentCallback() {
    override fun onAdDismissedFullScreenContent() {
      // Called when full screen content is dismissed.
      Log.d(TAG, "Ad dismissed fullscreen content.")
      // Don't forget to set the ad reference to null so you
      // don't show the ad a second time.
      appOpenAd = null
      isShowingAd = false

      onShowAdCompleteListener.onShowAdComplete()
      // Load an ad.
    }

    override fun onAdFailedToShowFullScreenContent(adError: AdError) {
      // Called when full screen content failed to show.
      Log.d(TAG, adError.message)
      // Don't forget to set the ad reference to null so you
      // don't show the ad a second time.
      appOpenAd = null
      isShowingAd = false

      onShowAdCompleteListener.onShowAdComplete()
      // Load an ad.
    }

    override fun onAdShowedFullScreenContent() {
      Log.d(TAG, "Ad showed fullscreen content.")
    }

    override fun onAdImpression() {
      // Called when an impression is recorded for an ad.
      Log.d(TAG, "The ad recorded an impression.")
    }

    override fun onAdClicked() {
      // Called when ad is clicked.
      Log.d(TAG, "The ad was clicked.")
    }
  }

考虑广告有效期

为确保您不会展示过期的广告,请在 AppOpenAdManager 中添加一个方法,用于检查广告引用加载后经过了多长时间。然后,使用该方法检查广告是否仍然有效。

Java

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

/** Check if ad exists and can be shown. */
private boolean isAdAvailable() {
  // For time interval details, see: https://support.google.com/admob/answer/9341964
  return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4);
}

Kotlin

/** 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 {
  // For time interval details, see: https://support.google.com/admob/answer/9341964
  return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4)
}

跟踪当前 activity

您需要 Activity 上下文才能展示广告。如需跟踪正在使用的最新 activity,请注册并实现 Application.ActivityLifecycleCallbacks

Java

@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {}

@Override
public void onActivityStarted(@NonNull Activity activity) {
  // An ad activity is started when an ad is showing, which could be AdActivity class from Google
  // SDK or another activity class implemented by a third party mediation partner. Updating the
  // currentActivity only when an ad is not showing will ensure it is not an ad activity, but the
  // one that shows the ad.
  if (!appOpenAdManager.isShowingAd) {
    currentActivity = activity;
  }
}

@Override
public void onActivityResumed(@NonNull Activity activity) {}

@Override
public void onActivityPaused(@NonNull Activity activity) {}

@Override
public void onActivityStopped(@NonNull Activity activity) {}

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

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

Kotlin

override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}

override fun onActivityStarted(activity: Activity) {
  // An ad activity is started when an ad is showing, which could be AdActivity class from Google
  // SDK or another activity class implemented by a third party mediation partner. Updating the
  // currentActivity only when an ad is not showing will ensure it is not an ad activity, but the
  // one that shows the ad.
  if (!appOpenAdManager.isShowingAd) {
    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 启动和销毁的时间,您可以跟踪对当前 Activity 的引用,然后根据该 activity 展示您的开屏广告。

监听应用前台事件

如需监听应用前台事件,请执行以下步骤:

将库添加到 gradle 文件中

要接收应用前台事件的通知,您需要注册 DefaultLifecycleObserver。向应用级 build 文件添加其依赖项:

Kotlin

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

Groovy

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

实现生命周期观察器接口

您可以通过实现 DefaultLifecycleObserver 接口来监听前台事件。

实现 onStart() 以展示开屏广告。

Java

@Override
public void onStart(@NonNull LifecycleOwner owner) {
  DefaultLifecycleObserver.super.onStart(owner);
  // Show the ad (if available) when the app moves to foreground.
  appOpenAdManager.showAdIfAvailable(currentActivity);
}

Kotlin

override fun onStart(owner: LifecycleOwner) {
  super.onStart(owner)
  currentActivity?.let {
    // Show the ad (if available) when the app moves to foreground.
    appOpenAdManager.showAdIfAvailable(it)
  }
}

冷启动和加载屏幕

到目前为止,本文档都假定您仅在以下情况下展示开屏广告:用户将在内存中挂起的应用切换为在前台运行。用户启动您的应用,但该应用之前未在内存中挂起,这种情况就称为“冷启动”。

例如,用户首次打开您的应用便属于冷启动。对于冷启动,您没有之前已加载的开屏广告可供立即展示。请求广告和收到相应广告之间的延迟会导致出现以下情况:用户能够暂时使用您的应用,然后突然看到一条无关广告。应避免出现这种情况,因为这会导致用户体验不佳。

在冷启动时使用开屏广告的首选方法是,使用加载屏幕来加载游戏或应用素材资源,并且仅在加载屏幕展示广告。如果您的应用已加载完毕,并且用户已经看到应用的主要内容,则不要展示广告。

最佳做法

借助开屏广告,您可以在用户首次启动应用和切换应用期间通过应用的加载屏幕变现,不过,还请务必考虑一些最佳做法,以便保持良好的应用使用体验。最佳做法如下所示:

  • 在用户使用几次您的应用后展示第一个开屏广告。
  • 利用用户等待应用加载的那段时间,展示开屏广告。
  • 如果有加载屏幕位于开屏广告之下,并且加载屏幕在用户关闭广告之前已加载完毕,您可能需要通过 onAdDismissedFullScreenContent() 方法关闭加载屏幕。

GitHub 上的示例

后续步骤

不妨探索以下主题: