libGDX: Часть 7.1. Использование AdMob

AdMob в своей игре

Ради интереса решил посмотреть сколько в принципе можно заработать на рекламе в не очень раскрученном приложении. Как раз дописывал Lode Runner’а, в него и запихнул. Решил показать, как добавить в свои игры на LibGDX рекламу.

Google AdMob Ads SDK для Android

В целом трудностей никаких нет. Порадовало, что в руководстве всё чётко расписано как делать, при чём на русском. Так же, не мало инфы можно на developer.android.com найти.

SDK Manager

В Eclipse вообще проблем нет. Выбирайте Android SDK Manager и там скачивайте/обновляйте необходимый SDK. В принципе, можно и самому скачать SDK с developer.android.com.

Для работы пакета Google AdMob Ads SDK для Android требуется операционная система Android версии 1.5 или более поздней. Убедитесь, что у вас установлена последняя версия SDK для Android и что компиляция настроена как минимум для Android 3.2 (задайте для target в default.properties значение android-13).

AdMob SDK в разделе Extras в менеджере.

AdMob SDK

Добавление JAR-архива SDK

1. Нажмите правой кнопкой мыши на проект своего приложения в Eclipse и выберите Properties.
2. Выберите Java Build Path.
3. На вкладке Libraries нажмите Add External JARs и добавьте SDK.
4. На вкладке Order and Export поставьте галку напротив либы.

Введение

В оффициальном мануале по либе написано как рекламу добавить. Может кто-то там не разберётся или ещё чего, поэтому сам распишу.

Background

Чтобы встроить рекламу, необходимо понять как работает LibGDX. Взглянем на типичную реализацию главного Activity для игры на LibGDX. Что-то вроде такого:

@Override
public void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState);
  AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
		
  config.useAccelerometer = false;
  config.useCompass = false;
  config.useWakelock = true;
  config.useGL20 = true;

  initialize(new BomberMan(this), config);
}

Нам тут интересен метод initialize. Посмотрим, что там внутри.

public void initialize(ApplicationListener listener, AndroidApplicationConfiguration config) {
  graphics = new AndroidGraphics(this, ...

  ...

  requestWindowFeature(Window.FEATURE_NO_TITLE);
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  getWindow().clearFlags( WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
  setContentView(graphics.getView(), createLayoutParams());
  ...
}

Что там происходит:

  • Создаётся объект AndroidGraphics с некоторыми параметрами.
  • Определяется, что у окна нет названия.
  • Определяется, что окно во весь экраню
  • Вызывается setContentView().

Последний шаг всё связывает и позволяет использовать представление libgdx в качестве основного представления. Теперь надо понять, как туда впихнуть AdMob.

Инициализация

Надо понять, что AdMob использует свое собственное представление. И мы знаем, что libgdx создает представление. Вызывая setContentView () для представления libgdx, мы уже не можем впихнуть AdMob. Таким образом, вот то, что мы должны сделать:

  • Создать слой, который может включать в себя другие.
  • Создать представление libgdx, добавить к слою.
  • Создать представление AdMob, добавить его к слою.
  • Вызвать setContentView() для слоя.

Для этого идеально подходит RelativeLayout, которые может содержать другие слои, которые могут перекрывать друг друга. Приведу весь код целиком с комментами. После всех манипуляций метод будет примерно таким:

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
		
  config.useAccelerometer = false;
  config.useCompass = false;
  config.useWakelock = true;
  config.useGL20 = true;
		
  //создём главный слой	
  RelativeLayout layout = new RelativeLayout(this);
  //устанавливаем флаги, которые устанавливались в методе initialize() вместо нас
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
  getWindow().clearFlags( WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

  //представление для LibGDX
  View gameView = initializeForView(new LodeRunner(this), config);
  
  //представление и настройка AdMob
  adView = new AdView(this, AdSize.BANNER, "ваш_ID_в_AdMob"); 
  AdRequest adRequest = new AdRequest();
  adView.loadAd(adRequest); 
   //добавление представление игрык слою
  layout.addView(gameView);

  RelativeLayout.LayoutParams adParams = 
                new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, 
                        RelativeLayout.LayoutParams.WRAP_CONTENT);
  adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); 
  adParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); 
  //добавление представление рекламы к слою
  layout.addView(adView, adParams);  
      
  //всё соединяем в одной слое
  setContentView(layout); 

}

AndroidManifest

Нужно добавить разрешения на доступ к сети.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Ну и добавить само активити AdMob.

<activity android:name="com.google.ads.AdActivity"
   android:configChanges="keyboard|keyboardHidden| orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
 />

Управление рекламой

Теперь нам необходимо скрывать/отображать и подгружать рекламу. Для начала в админке AdMob надо выбрать пункт, что вы будете сами обновлять рекламу в коде. Можно этого и не делать. Но, с нашей реализацией реклама в фоне есть всегда, если она будет обновляться каждые 60 секунд, как пример, то CTR упадёт, так как юзер её не видит, а счётчик показов растёт.

Refresh rate

Создадим метод, который будет отображать/скрывать рекламу, когда нам надо. Если сделать обычный метод, то при попытке вызова из игры, вывалиться ошибка Can’t create handler inside thread that has not called Looper.prepare(). Из-за того, что вызов происходит из рабочего дочернего потока.

Для обхода этой ошибки создадим интерфейс.

public interface IActivityRequestHandler {
	   public void showAdMob(boolean show);
}

Реализуем его в нашем классе и будем работать с хэндлером и слать ему сообщения.

public class MainActivity extends AndroidApplication implements IActivityRequestHandler  {
  ...
  @Override
  public void showAdMob(boolean show){
    handler.sendEmptyMessage(show ? 1 : 0);
  }

  protected Handler handler = new Handler()
  {
    @Override
    public void handleMessage(Message msg) {
      if(msg.what ==0)
        adView.setVisibility(View.GONE);
      if(msg.what==1){
        adView.setVisibility(View.VISIBLE);
        AdRequest adRequest = new AdRequest();
        adView.loadAd(adRequest); 
      }
    }
  }; 
}

Теперь, когда вам необходимо показать рекламу, вызывайте метод showAdMob(true); и showAdMob(false); для скрытия.

Тестирование

Во время разработки должен быть включен тестовый режим, иначе вы не сможете нажимать на свои объявления. Для этого необходимо добавить строку adRequest.addTestDevice("TEST_DEVICE_ID"); Как узнать ID для этого метода?

LogCat Filter

Добавьте фильтр для лога. Запустите ваше приложение в режиме отладки. Вы увидите в логе что-то вроде такого.

Test ID

Берёте этот ID и вписываете в метод. Теперь при разработке вам будут показаны тестовые рекламные предложения. Они будут кликабельны и за клики по ним ваш аккаунт не заблокируют.

  Категории: Android, java, libgdx, Коддинг
  • http://winners-games.com Vitalik

    Но лучше на ранних этапах не монитизировать игру, может раздражать. Кстати откуда столько посетителей на сайте?

    • http://suvitruf.ru Suvitruf

      1) Если умно рекламу впихнуть, то не особо раздражает. У меня она на экране загрузки уровня только появляется. То есть, самому процессу игры не мешает (:
      2) Я рекламу с самого начала впихнул, чтобы потом посмотреть корреляцию между количеством загрузок и прибылью.

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

      • http://winners-games.com Vitalik

        Любопытно, я вот тоже хочу заняться флеш анимацией. Может что и выйдет.

        • http://suvitruf.ru Suvitruf

          Главное – не забрасывать в долгий ящик)

  • Леха

    Большое спасибо за инфу. И посылайте далеко всех, кто на рекламу возмушается. Ну не покупают люди русские на Андроиде игры. Только реклама и спасает. Иначе все ява кодеры пойдут в банк работать -))))

  • http://angors.ru Gexon

    посетители ищут инф о libGDX =)
    и вопрос. есть ли в libGDX GUI?

    • http://suvitruf.ru Suvitruf

      Нет)

  • Алексей

    Подскажите как из объекта игры вызвать showAdMob(true); и showAdMob(false); для скрытия.

    • http://suvitruf.ru Suvitruf

      Ну вот у меня пример View gameView = initializeForView(new LodeRunner(this), config);.

      А в конструкторе класса:
      public LodeRunner (IActivityRequestHandler app){
      application = app;
      }

      , где IActivityRequestHandler application;

      Теперь вы можете вызывать application.showAdMob(true); из игры.

  • 11rus

    Ну так что в итоге то? Много денег реклама приносит?

    • http://suvitruf.ru Suvitruf

      Мою ж игру выпилили из Google Play)
      Ну а так, пару десятков баксов в день приносить может, даже не раскрученная.

      • anonymous

        А за что выпилили, если не секрет?

        • http://suvitruf.ru Suvitruf

          Нарушение авторских прав. Права на товарный знак у Tonzai )

  • Mafiy

    При выполнении кода
    AdView m_adView = new AdView(this,AdSize.BANNER,"xxxxxxxxxxxxxxxxx");
    AdRequest m_adRequest = new AdRequest();
    m_adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
    m_adRequest.addTestDevice("xxxxxxxxxxxxxxxxx");
    m_adView.loadAd(m_adRequest);

    вываливаются ошибки из libgdx. я думаю из-за них не отображается реклама. В чем может быть проблема? доступ к интернету дал. libgdx 0.9.8 android:minSdkVersion=”5″ android:targetSdkVersion=”17″

    netstack: STAT_HUB – App crazy.building.game isn’t supported
    netstack: STAT_HUB – Failed to load plugin: pp_proc_plugin.so
    netstack: LIB_MGR – Error loading lib pp_proc_plugin.so
    netstack: STAT_HUB – Failed to load plugin: spl_proc_plugin.so
    netstack: LIB_MGR – Error loading lib spl_proc_plugin.so
    netstack: STAT_HUB – Failed to load plugin: libdnshostprio.so
    netstack: LIB_MGR – Error loading lib libdnshostprio.so
    netstack: LIB_MGR – Error loading lib libsocketpoolextend.so

    • http://suvitruf.ru Suvitruf

      Это не libgdx ошибки О_о

  • MAx

    помогите добавить startapp-рекламу в libgdx-приложение, а то всё никак не получается

  • https://play.google.com/store/apps/details?id=com.nikitin.turtle.jump Игорь Игорь Никитин

    У меня почему то при таком подходе fps в 2 раза падает (я box2d использую). Это нормально, так и должно быть?

    • http://suvitruf.ru/ Андрей

      Вы что-то не так скорей всего делаете, раз это сказывается на fps O_o

  • https://play.google.com/store/apps/details?id=com.nikitin.turtle.jump Игорь Игорь Никитин

    На форуме падение fps посоветовали решить путем изменения приоритета, http://4pda.ru/forum/index.php?showtopic=493326&st=3160#entry41356207 . Вы случайно не знаете как поднять приоритет представления libGDX?

  • https://play.google.com/store/apps/details?id=com.nikitin.turtle.jump Игорь Игорь Никитин

    Спасибо форуму, с помощью поднятия приоритета потока игры все

    улучшилось на 90 %, нужно в конце метода create() написать

    try { Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    } catch (Exception e) {}

    А вы не знаете случайно как межстраничные объявления добавить в старый admob (например GoogleAdMobAdsSdk-6.4.1.)? Просто в новом admob нужно андроид студию ставить и разбераться как публиковать в маркете, а уроки по старому admob куда то делись.

    • http://suvitruf.ru/ Андрей

      Я с рекламой уже давно не работал. Не знаю, как там что сейчас )