Это руководство предназначено для издателей, интегрирующих открытые объявления в приложениях с помощью Google Mobile Ads SDK.
Объявления при открытии приложения – это специальный формат рекламы, предназначенный для издателей, желающих монетизировать экраны загрузки приложений. Объявления при открытии приложения можно закрыть в любой момент. Они предназначены для показа, когда пользователи выводят ваше приложение на передний план.
В объявлениях при запуске приложения автоматически отображается небольшая область фирменного оформления, чтобы пользователи знали, что они находятся в вашем приложении. Вот пример того, как выглядит объявление при открытии приложения:
Предварительные условия
- Заполните руководство по началу работы .
Всегда тестируйте с помощью тестовых объявлений
При создании и тестировании приложений убедитесь, что вы используете тестовые объявления, а не действующие, рабочие. Несоблюдение этого требования может привести к блокировке вашего аккаунта.
Самый простой способ загрузить тестовые объявления — использовать наш специальный идентификатор тестового рекламного блока для объявлений при открытии приложения:
ca-app-pub-3940256099942544/9257395921
Он был специально настроен для возврата тестовых объявлений по каждому запросу, и вы можете использовать его в своих собственных приложениях при написании кода, тестировании и отладке. Просто убедитесь, что вы заменили его собственным идентификатором рекламного блока перед публикацией приложения.
Дополнительную информацию о том, как работают тестовые объявления Google Mobile Ads SDK, см. в разделе Включение тестовых объявлений .
Расширить класс приложения
Создайте новый класс, расширяющий класс Application
, и добавьте следующий код для инициализации Google Mobile Ads 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();
}
}
Котлин
/** 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;
}
}
}
Котлин
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);
}
}
Котлин
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;
}
});
}
// ...
}
Котлин
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);
}
// ...
}
}
Котлин
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);
}
}
Котлин
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) {}
}
Котлин
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
. Добавьте его зависимость в файл сборки уровня приложения:
Котлин
dependencies { implementation("com.google.android.gms:play-services-ads:23.3.0") implementation("androidx.lifecycle:lifecycle-process:2.8.3") }
классный
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.
}
});
}
}
Котлин
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
Следующие шаги
Изучите следующие темы:
- Конфиденциальность пользователя
- Оптимизированная инициализация SDK и загрузка рекламы (бета-версия).