本指南適用於使用 Google Mobile Ads Android SDK 整合應用程式開啟頁面廣告的發布商。
應用程式開啟頁面廣告是一種特殊廣告格式,適合希望藉由應用程式載入畫面賺取收益的發布商。應用程式開啟頁面廣告會在使用者將應用程式切換至前景時出現,而且使用者隨時可以關閉。
應用程式開啟頁面廣告會自動保留一小塊畫面,向使用者顯示應用程式的品牌資訊。以下是應用程式開啟頁面廣告的外觀範例:
大致步驟如下:
- 擴充
Application
類別,初始化 Google Mobile Ads SDK。 - 請先建立公用程式類別,然後載入廣告。
- 載入廣告。
- 聽取
ActivityLifecycleCallbacks.
- 放送廣告並處理回呼。
- 實作及註冊
LifecycleObserver
介面,以便在前景事件期間顯示廣告。
必要條件
- Google Mobile Ads SDK 19.4.0 以上版本。
- 按照入門指南中的設定說明操作。
一律使用測試廣告進行測試
打造及測試應用程式時,請務必使用測試廣告,而非實際的廣告。否則帳戶可能會遭到停權。
如要載入測試廣告,最簡單的方法是使用應用程式開啟頁面專用測試廣告單元 ID:
ca-app-pub-3940256099942544/3419835294
這個功能經過特別設計,可針對每項要求傳回測試廣告,您可以在編寫、測試及偵錯時,自由在應用程式中使用。您只要在發布應用程式前將其 ID 換成您自己的廣告單元 ID 即可。
如要進一步瞭解 Mobile Ads SDK 的測試廣告的運作方式,請參閱測試廣告。
擴充應用程式類別
建立擴充 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();
MobileAds.initialize(
this,
new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {}
});
}
}
Kotlin
/** Application class that initializes, loads and show ads when activities change states. */
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
MobileAds.initialize(this) {}
}
}
這項操作會初始化 SDK,並提供稍後註冊的資源,以便日後註冊應用程式前景事件。
接著,請在 AndroidManifest.xml
中新增下列程式碼:
<application
android:name="com.google.android.gms.example.appopendemo.MyApplication" ...>
...
</application>
請務必提及實際的套件名稱。
實作公用程式類別
您的廣告應該要能快速顯示,因此在顯示之前,最好先載入廣告。這樣一來,您就可以在使用者進入應用程式後立即準備好放送廣告。只要實作公用程式類別,即可在需要顯示廣告時提出廣告請求。
在 MyApplication
類別中建立名為 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 = "ca-app-pub-3940256099942544/3419835294";
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 below.
}
/** 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/3419835294"
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 below.
}
/** 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();
MobileAds.initialize(
this,
new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {}
});
appOpenAdManager = new AppOpenAdManager(this);
}
}
Kotlin
class MyApplication : Application() {
private lateinit var appOpenAdManager: AppOpenAdManager
override fun onCreate() {
super.onCreate()
MobileAds.initialize(this) {}
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;
}
@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
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
// Called when an app open ad has failed to load.
Log.d(LOG_TAG, loadAdError.message)
isLoadingAd = false;
}
})
}
...
}
AppOpenAdLoadCallback
會在 AppOpenAd
完成載入時呼叫的方法。
追蹤目前活動
您必須擁有 Activity
內容才能顯示廣告。如要追蹤使用者目前使用的最新活動,請在 Application
類別中實作 Application.ActivityLifecycleCallbacks
。
Java
public class MyApplication extends Application implements ActivityLifecycleCallbacks {
private Activity currentActivity;
...
/** ActivityLifecycleCallback methods. */
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted(Activity activity) {
// Updating the currentActivity only when an ad is not showing.
if (!appOpenAdManager.isShowingAd) {
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
...
/** ActivityLifecycleCallback methods. */
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {
// Updating the currentActivity only when an ad is not showing.
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
方法註冊這個介面。
Java
public class MyApplication extends Application {
...
@Override
public void onCreate() {
super.onCreate();
this.registerActivityLifecycleCallbacks(this);
MobileAds.initialize(
this,
new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {}
});
appOpenAdManager = new AppOpenAdManager();
}
}
Kotlin
class MyApplication : Application() {
...
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(this)
MobileAds.initialize(this) {}
appOpenAdManager = AppOpenAdManager()
}
}
registerActivityLifecycleCallbacks
可監聽所有 Activity
事件。透過監聽活動開始和刪除的時間,您可以追蹤目前 Activity
的參照,然後用來顯示應用程式開啟頁面廣告。
放送廣告並處理全螢幕回呼事件
以下程式碼示範如何顯示及再重新載入廣告。
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
會處理事件,例如當廣告顯示、顯示或未顯示時。如果使用者在點選應用程式開啟頁面廣告後離開了應用程式,系統會確保使用者並未看到其他應用程式開啟頁面廣告。
監聽應用程式前景事件
將程式庫新增至 Gradle 檔案
您必須註冊 LifecycleObserver
,才能收到應用程式前景事件的通知。首先,請編輯應用程式層級的 build.gradle
檔案以加入 LifecycleObserver
程式庫:
apply plugin: 'com.android.application'
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.gms:play-services-ads:22.4.0'
def lifecycle_version = "2.3.1"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
}
實作 LifecycleObserver 介面
您可以實作 LifecycleObserver
介面,藉此監聽 Application
類別中的前景事件。
Java
public class MyApplication extends Application
implements ActivityLifecycleCallbacks, LifecycleObserver { {
...
@Override
public void onCreate() {
super.onCreate();
this.registerActivityLifecycleCallbacks(this);
MobileAds.initialize(
this,
new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {}
});
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)
MobileAds.initialize(this) {}
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.
}
})
}
}
註冊 LifecycleObserver
後,應用程式便會收到應用程式啟動和前景事件的快訊,並在適當時間顯示廣告。
考量廣告效期
為避免顯示已失效的廣告,請在 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;
/** 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;
}
});
}
...
/** 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
/** 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;
}
})
}
...
private fun wasLoadTimeLessThanNHoursAgo(numHours: Long): Boolean {
val dateDifference: Long = Date().time - loadTime
val numMilliSecondsPerHour: Long = 3600000
return dateDifference < numMilliSecondsPerHour * numHours
}
private fun isAdAvailable(): Boolean {
return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4)
}
}
冷啟動和載入畫面
到目前為止,說明文件都假設您只會在應用程式於記憶體中暫停時,才顯示應用程式開啟頁面廣告。應用程式啟動後,如果先前未在記憶體中暫停,就會發生「冷啟動」。
使用者初次開啟應用程式的範例便是冷啟動。在冷啟動期間,系統不會顯示先前載入的廣告,而且不會立即顯示。從要求送出廣告到收到廣告要求之間的延遲時間,可能會導致使用者短暫使用您的應用程式,然後再因內容相關廣告而感到出乎意料。請避免這種情況,因為這會對使用者體驗造成負面影響。
如要在冷啟動時使用應用程式開啟頁面廣告,建議您使用載入畫面載入遊戲或應用程式素材資源,並只顯示載入畫面顯示廣告。如果應用程式已經載入完成,並將使用者傳送至應用程式的主要內容,請勿顯示廣告。
最佳做法
應用程式開啟頁面廣告可協助您透過應用程式的載入畫面營利,在應用程式首次啟動期間和切換應用程式時;不過,請務必保留最佳做法,讓使用者更熟悉您的應用程式。建議您採取下列做法:
- 在使用者初次使用應用程式幾次後,首次放送應用程式開啟頁面廣告。
- 在使用者等候應用程式載入的期間,顯示應用程式開啟頁面廣告。
- 如果您在應用程式開啟頁面下有一個載入畫面,且載入畫面在廣告關閉前完成載入,您可能需要在
onAdDismissedFullScreenContent()
方法中關閉載入畫面。
GitHub 上的範例
後續步驟
探索下列主題: