應用程式開啟頁面廣告

本指南適用於使用 Google Mobile Ads SDK 整合應用程式開啟頁面廣告的發布商。

應用程式開啟頁面廣告是一種特殊廣告格式,適合希望藉由應用程式載入畫面賺取收益的發布商。應用程式開啟頁面廣告會在使用者將應用程式切換至前景時出現,而且使用者隨時可以關閉。

應用程式開啟頁面廣告會自動保留一小塊畫面,向使用者顯示應用程式的品牌資訊。以下是應用程式開啟頁面廣告的示例:

必要條件

請務必使用測試廣告進行測試

建構及測試應用程式時,請務必使用測試廣告,而非實際的正式版廣告。否則可能導致帳戶停權。

如要載入測試廣告,最簡單的方法是使用專用測試廣告單元 ID 來開啟應用程式廣告:

/21775744923/example/app-open

這項廣告單元已特別設定為針對每項要求傳回測試廣告,您可以在編寫程式碼、測試及偵錯時,在自己的應用程式中自由使用這項廣告單元。只要在發布應用程式前,將其替換為自己的廣告單元 ID 即可。

如要進一步瞭解 Google Mobile Ads SDK 的測試廣告運作方式,請參閱「啟用測試廣告」。

擴充 Application 類別

建立可擴充 Application 類別的新類別,並新增下列程式碼,在應用程式啟動時初始化 Google Mobile Ads SDK。

Java

/** 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,在需要顯示廣告前提出廣告請求。

Java

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 = "/21775744923/example/app-open";

    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 = "/21775744923/example/app-open"

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 類別中將其例項化:

Java

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() 方法並處理廣告載入回呼。

Java

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;
          }
        })
  }
  // ...
}

顯示廣告並處理全螢幕回呼事件

最常見的應用程式開啟導入做法,是在應用程式啟動時嘗試顯示應用程式開啟廣告,如果廣告尚未準備就緒,則開始播放應用程式內容,並為下次應用程式開啟機會預先載入其他廣告。如需實作範例,請參閱應用程式開啟頁面廣告指南

以下程式碼示範如何顯示廣告,並在之後重新載入廣告:

Java

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 中新增方法,檢查廣告參照項目載入後已過多久。然後使用該方法檢查廣告是否仍有效。

Java

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

Java

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.5.0")
    implementation("androidx.lifecycle:lifecycle-process:2.8.3")
  }

Groovy

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

實作生命週期觀察器介面

您可以實作 DefaultLifecycleObserver 介面,監聽前景事件。

實作 onStart 事件,以便顯示應用程式開啟頁面廣告。

Java

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.
          }
        })
  }
}

冷啟動和載入畫面

目前的說明文件假設您只會在使用者將應用程式從記憶體中暫停後,在前景顯示應用程式開啟頁面廣告。當應用程式啟動,但先前未在記憶體中暫停時,就會發生「冷啟動」。

舉例來說,使用者初次開啟應用程式就是冷啟動。在冷啟動期間,您不會有先前載入的應用程式開啟頁面廣告,因此無法立即顯示廣告。在您提出廣告請求和收到廣告回應之間,可能會出現延遲的情況,導致使用者在應用程式運作一段時間後,才會看到不相關的廣告。這會造成使用者體驗不佳,因此應避免採用。

在冷啟動時使用應用程式開啟頁面廣告的首選方式,是使用載入畫面載入遊戲或應用程式素材資源,並只在載入畫面中顯示廣告。如果應用程式已完成載入,並將使用者導向應用程式的主內容,請勿顯示廣告。

最佳做法

應用程式開啟頁面廣告可在應用程式首次啟動和切換應用程式期間,協助您透過應用程式的載入畫面營利,但請務必遵循最佳做法,讓使用者能盡情享受應用程式。建議做法如下:

  • 等使用者用過應用程式幾次之後,再放送第一則應用程式開啟頁面廣告。
  • 在使用者等待應用程式載入時,顯示應用程式開啟頁面廣告。
  • 如果載入畫面顯示在應用程式開啟頁面廣告的背景中,且載入畫面在廣告關閉前就完成載入,建議您利用 onAdDismissedFullScreenContent() 方法關閉載入畫面。

GitHub 上的範例

後續步驟

請參閱下列主題: