Объявления об открытии приложений

Это руководство предназначено для издателей, интегрирующих рекламу при открытии приложения с помощью Google Mobile Ads Android SDK.

Объявления об открытии приложения — это специальный формат рекламы, предназначенный для издателей, желающих монетизировать загрузочные экраны своих приложений. Объявления об открытии приложения можно закрыть в любое время, и они предназначены для показа, когда ваши пользователи выводят ваше приложение на передний план.

Объявления об открытии приложения автоматически показывают небольшую область брендинга, чтобы пользователи знали, что они находятся в вашем приложении. Вот пример того, как выглядит объявление об открытии приложения:

На высоком уровне это важные шаги:

  1. Расширьте класс Application , чтобы инициализировать Google Mobile Ads SDK.
  2. Создайте служебный класс, который загружает рекламу до того, как вам нужно будет ее отобразить.
  3. Загрузите объявление.
  4. Слушайте ActivityLifecycleCallbacks.
  5. Показывайте рекламу и обрабатывайте обратные вызовы.
  6. Реализуйте и зарегистрируйте интерфейс LifecycleObserver , чтобы показывать рекламу во время событий приоритетного плана.

Предпосылки

  • Google Mobile Ads SDK 19.4.0 или более поздней версии.
  • Следуйте инструкциям по настройке в руководстве по началу работы .

Всегда тестируйте тестовые объявления

При создании и тестировании своих приложений убедитесь, что вы используете тестовую рекламу, а не живую производственную рекламу. Невыполнение этого требования может привести к приостановке действия вашей учетной записи.

Самый простой способ загрузить тестовые объявления — использовать наш специальный идентификатор тестового рекламного блока для объявлений, открывающих приложение:

ca-app-pub-3940256099942544/3419835294

Он был специально настроен для возврата тестовых объявлений для каждого запроса, и вы можете использовать его в своих собственных приложениях при написании кода, тестировании и отладке. Просто убедитесь, что вы заменили его собственным идентификатором рекламного блока, прежде чем публиковать свое приложение.

Дополнительные сведения о том, как работают тестовые объявления 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();
    MobileAds.initialize(
        this,
        new OnInitializationCompleteListener() {
          @Override
          public void onInitializationComplete(InitializationStatus initializationStatus) {}
        });
  }
}

Котлин

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

Обязательно укажите фактическое имя пакета.

Реализуйте свой служебный класс

Ваше объявление должно показываться быстро, поэтому лучше загрузить его до того, как оно понадобится. Таким образом, у вас будет готовое объявление, как только пользователь войдет в ваше приложение. Реализуйте служебный класс, чтобы делать запросы объявлений до того, как вам нужно показать рекламу.

Создайте новый класс с именем AppOpenAdManager в классе MyApplication и заполните его следующим образом:

Ява

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;
    }
  }
}

Котлин

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 :

Ява

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

Котлин

class MyApplication : Application() {

  private lateinit var appOpenAdManager: AppOpenAdManager

  override fun onCreate() {
    super.onCreate()
    MobileAds.initialize(this) {}
    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;
          }

          @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
          }

          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.ActivityLifecycleCallbacks в своем классе Application .

Ява

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

Котлин

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 .

Ява

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();
  }
}

Котлин

class MyApplication : Application() {
  ...
  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(this)
    MobileAds.initialize(this) {}
    appOpenAdManager = AppOpenAdManager()
  }
}

registerActivityLifecycleCallbacks позволяет прослушивать все события Activity . Прослушивая, когда действия запускаются и уничтожаются, вы можете отслеживать ссылку на текущую Activity , которую затем будете использовать при представлении объявления об открытии вашего приложения.

Показывать рекламу и обрабатывать события обратного вызова в полноэкранном режиме

Следующий код показывает, когда следует показывать и затем перезагружать объявление.

Ява

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.fullScreenContentCallback(
          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 обрабатывает такие события, как отображение объявления, его отсутствие или отклонение. Если пользователь возвращается в ваше приложение после того, как покинул его, нажав на объявление об открытии приложения, это гарантирует, что ему не будет представлено другое объявление об открытии приложения.

Прослушивание событий приоритетного плана приложения

Добавьте библиотеки в ваш файл 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:21.1.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.

Вы можете прослушивать события переднего плана в своем классе Application , реализуя интерфейс LifecycleObserver .

Ява

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

Котлин

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 метод, который проверяет, сколько времени прошло с момента загрузки вашей ссылки на рекламу. Затем используйте этот метод, чтобы проверить, действует ли объявление.

Ява

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

Котлин

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