Баннеры – один из наиболее популярных видов рекламы в мобильных приложениях. Они не занимают много места, как, например, полноэкранная (interstitial) реклама. И позволяют совместить их с элементами пользовательского интерфейса приложения. Их можно добавить на разные экраны в приложении.
Прочитав данную статью, вы узнаете, как лучше вставить баннеры таким образом, чтобы они не мешали пользователю и не портили вид приложения. При этом вам не придётся изменять layout xml и вносить много изменений в код приложения. Вы можете внедрить баннеры в своё готовое приложение, добавив всего несколько строк кода. Подход, описанный в статье, универсальный, вы можете использовать его для API любых рекламных сервисов. Статья будет интересна как для новичков, так и для опытных разработчиков. Если вы — новичок в разработке, то для того, чтобы понять предмет статьи, от вас не потребуется каких-либо глубоких знаний. Достаточно понимания базовых концепций разработки под Android. А опытные разработчики могут найти в ней готовое решение, которое они могут внедрить у себя. Но инициализация рекламного сервиса, работа с конкретными рекламными API и кеширование находятся за пределами данной статьи. Для решения таких вопросов, пожалуйста, обратитесь к руководству для вашего конкретного рекламного сервиса.
Идея статьи возникла от того, что в одном из наших приложений для Android нам было необходимо разместить баннеры в нескольких местах, но сделать это следовало таким образом, чтобы не испортить вид приложения и не перекрыть баннерами элементы управления. Код приложения был уже написан полностью и перекраивать его нам очень не хотелось, поэтому мы постарались сделать так, чтобы добавление баннеров было максимально простым, корректным и не затрагивало работу существующего кода. Другая причина — нам потребовалось создать платную версию приложения без рекламы. А если бы внедрение баннеров потребовало бы изменение layout xml, то это сильно бы усложнило создание версии без рекламы.
Чтобы было более наглядно и понятно то, о чём я пишу, посмотрите на следующий экран:
Элементы пользовательского интерфейса занимают всё пространство экрана. Пустых мест нет. В таком случае, мы можем разместить баннер внизу или вверху. Вариант размещения баннера снизу предпочтительнее, так как баннер будет находится подальше от кнопок и пользователь не заденет баннер, случайно пытаясь нажать на «Выбрать» или «Назад». Нам необходимо разместить баннер снизу экрана под GridView с фото. Так как баннер загружается по сети, он может быть не сразу и не всегда недоступен. Следовательно, не в каждый момент времени его можно показать и может получиться пустое место снизу. Если мы оставим это пустое место – получится очень некрасиво. Будет выглядеть, как будто это грубая недоработка дизайна интерфейса. Если мы разместим баннер поверх GridView, то он перекроет собой части фото и создаст неудобства пользователю, что тоже недопустимо.
Тогда сводим задачу к тому, что нам необходимо сделать так, чтобы не было дополнительных отступов. А когда баннер загружен и может быть показан – динамически добавить отступ снизу и показать баннер. С другой стороны, нам необходимо сделать код размещения баннеров максимально простым, без сложных инициализаций. Т.е. передавать id элементов или ссылки на контейнеры (ViewGroup) недопустимо. Вставлять баннеры в layout xml каждого экрана, куда нам необходимо добавить баннер – тоже недостустимо, т.к. потребует значительных изменений. В идеале, код установки баннера должен выглядеть следующим образом:
Всего одна строка кода, один вызов метода, которому передаётся только ссылка на Activity в которой будет размещён баннер. Такой код можно вставить в метод Activity onCreate.
Для того, чтобы это реализовать, нам необходимо знать, что находится в View и получить к этому доступ. Прямого метода для доступа к content view в Activity нет. Но благодаря пользователю nickes со StackOverflow мы нашли решение. Необходимо идти через Window, в котором находится Activity. У Window есть DecorView, а в DecorView находится ContentView. Первый дочерний элемент в нём – это и есть ViewGroup из layout xml.
Так что нам требуется Window, затем мы получаем DecorView, затем получаем ContentView и затем получаем первый дочерний элемент ContentView. И у этого дочернего элемента мы изменяем отступ:
Мы нашли решение, как динамически добавить отступ. Теперь нам необходимо разместить сам баннер. У разных рекламных сервисов разные API. У некоторых есть View баннера, который вы можете создать и добавить в ViewGroup. Но некоторые рекламные API не имеют доступа к View баннера, а имеют только метод, который показывает баннер. Рассмотрим оба варианта.
Назовём класс View баннера — Banner. (Чтобы узнать, как он реально называется в вашем случае и как с ним работать, пожалуйста, обратитесь к руководству вашего рекламного сервиса.)
Сначала, нам необходимо создать объект Banner:
Затем ему следует назначить слушатель событий. Нас интересует событие успешной загрузки баннера (это опять код — пример. Для того, чтобы узнать как слушатель называется и как его использовать, обратитесь, пожалуйста, к руководству вашего рекламного сервиса):
Когда баннер загружен, мы вызываем setupContentViewPadding, чтобы динамически добавить отступ снизу.
Затем мы добавляем наш баннер в Window. Мы добавляем его поверх существующих элементов. В классе Window есть метод addContentView для этого:
У нас нет View баннера и мы не можем создать и разместить его явным образом. Но API имеет методы, вроде showBanner — показать баннер.
Я условно назову класс рекламного API — AdAPI (вам следует обратится к руководству вашего рекламного сервиса, чтобы узнать, как называется класс в которой есть методы размещения баннеров). В этом случае, код размещения баннера будет выглядеть примерно так:
Где BANNER_HEIGHT — константа равная высоте баннера.
Здесь возникают некоторые затруднения. Вам следует точно узнать или установить высоту баннера. У нас была такая проблема: мы запускали наше приложение на 3.7 дюймовом смартфоне и на 10.1 дюймовом планшете. Размеры баннера оказались разными на разных устройствах. На смартфоне баннер выглядел отлично, но на планшете он оказался слишком большим и отнял слишком много места у других элементов. Если ваш рекламный сервис позволяет явно задать высоту баннера — лучше задайте, чтобы не было таких неприятных неожиданностей.
Как вы можете видеть, баннер показан и не перекрывает другие элементы. Отступ снизу добавлен динамически.
Это то, что нам требовалось.
Подводя итог всему вышесказанному, привожу способ интеграции кода в ваше приложение.
Класс Ads:
Замените код в методе showBottomBanner на вызовы API вашего рекламного сервиса.
Чтобы разместить баннер, добавьте строчку кода Ads.showBottomBanner(this) в метод Activity onCreate.
В статье я привёл описание как интегрировать баннеры в приложение наиболее корректным и простым способом. Есть и другие способы размещения баннеров. Например, можно взять первый экран показанный в статье и разместить баннер не снизу, а между элементами.
Надеюсь, статья была полезна для вас.
Пожалуйста, пишите ваши замечания в комментариях.
Благодарю за внимание. Успехов вам в разработке!
Прочитав данную статью, вы узнаете, как лучше вставить баннеры таким образом, чтобы они не мешали пользователю и не портили вид приложения. При этом вам не придётся изменять layout xml и вносить много изменений в код приложения. Вы можете внедрить баннеры в своё готовое приложение, добавив всего несколько строк кода. Подход, описанный в статье, универсальный, вы можете использовать его для API любых рекламных сервисов. Статья будет интересна как для новичков, так и для опытных разработчиков. Если вы — новичок в разработке, то для того, чтобы понять предмет статьи, от вас не потребуется каких-либо глубоких знаний. Достаточно понимания базовых концепций разработки под Android. А опытные разработчики могут найти в ней готовое решение, которое они могут внедрить у себя. Но инициализация рекламного сервиса, работа с конкретными рекламными API и кеширование находятся за пределами данной статьи. Для решения таких вопросов, пожалуйста, обратитесь к руководству для вашего конкретного рекламного сервиса.
Идея статьи возникла от того, что в одном из наших приложений для Android нам было необходимо разместить баннеры в нескольких местах, но сделать это следовало таким образом, чтобы не испортить вид приложения и не перекрыть баннерами элементы управления. Код приложения был уже написан полностью и перекраивать его нам очень не хотелось, поэтому мы постарались сделать так, чтобы добавление баннеров было максимально простым, корректным и не затрагивало работу существующего кода. Другая причина — нам потребовалось создать платную версию приложения без рекламы. А если бы внедрение баннеров потребовало бы изменение layout xml, то это сильно бы усложнило создание версии без рекламы.
Чтобы было более наглядно и понятно то, о чём я пишу, посмотрите на следующий экран:
Элементы пользовательского интерфейса занимают всё пространство экрана. Пустых мест нет. В таком случае, мы можем разместить баннер внизу или вверху. Вариант размещения баннера снизу предпочтительнее, так как баннер будет находится подальше от кнопок и пользователь не заденет баннер, случайно пытаясь нажать на «Выбрать» или «Назад». Нам необходимо разместить баннер снизу экрана под GridView с фото. Так как баннер загружается по сети, он может быть не сразу и не всегда недоступен. Следовательно, не в каждый момент времени его можно показать и может получиться пустое место снизу. Если мы оставим это пустое место – получится очень некрасиво. Будет выглядеть, как будто это грубая недоработка дизайна интерфейса. Если мы разместим баннер поверх GridView, то он перекроет собой части фото и создаст неудобства пользователю, что тоже недопустимо.
Тогда сводим задачу к тому, что нам необходимо сделать так, чтобы не было дополнительных отступов. А когда баннер загружен и может быть показан – динамически добавить отступ снизу и показать баннер. С другой стороны, нам необходимо сделать код размещения баннеров максимально простым, без сложных инициализаций. Т.е. передавать id элементов или ссылки на контейнеры (ViewGroup) недопустимо. Вставлять баннеры в layout xml каждого экрана, куда нам необходимо добавить баннер – тоже недостустимо, т.к. потребует значительных изменений. В идеале, код установки баннера должен выглядеть следующим образом:
Ads.showBottomBanner(activity);
Всего одна строка кода, один вызов метода, которому передаётся только ссылка на Activity в которой будет размещён баннер. Такой код можно вставить в метод Activity onCreate.
Динамическое добавление отступа
Для того, чтобы это реализовать, нам необходимо знать, что находится в View и получить к этому доступ. Прямого метода для доступа к content view в Activity нет. Но благодаря пользователю nickes со StackOverflow мы нашли решение. Необходимо идти через Window, в котором находится Activity. У Window есть DecorView, а в DecorView находится ContentView. Первый дочерний элемент в нём – это и есть ViewGroup из layout xml.
Так что нам требуется Window, затем мы получаем DecorView, затем получаем ContentView и затем получаем первый дочерний элемент ContentView. И у этого дочернего элемента мы изменяем отступ:
public static void setupContentViewPadding(Activity activity, boolean top, int margin) {
View view = ((ViewGroup) activity.getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0);
if (top)
view.setPadding(view.getPaddingLeft(), margin, view.getPaddingRight(), view.getPaddingBottom());
else
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), margin);
}
Размещение баннера
Мы нашли решение, как динамически добавить отступ. Теперь нам необходимо разместить сам баннер. У разных рекламных сервисов разные API. У некоторых есть View баннера, который вы можете создать и добавить в ViewGroup. Но некоторые рекламные API не имеют доступа к View баннера, а имеют только метод, который показывает баннер. Рассмотрим оба варианта.
API, в котором есть View баннера
Назовём класс View баннера — Banner. (Чтобы узнать, как он реально называется в вашем случае и как с ним работать, пожалуйста, обратитесь к руководству вашего рекламного сервиса.)
Сначала, нам необходимо создать объект Banner:
final Banner banner = new Banner(activity);
Затем ему следует назначить слушатель событий. Нас интересует событие успешной загрузки баннера (это опять код — пример. Для того, чтобы узнать как слушатель называется и как его использовать, обратитесь, пожалуйста, к руководству вашего рекламного сервиса):
banner.setBannerListener(new BannerListener() {
@Override
public void onReceiveAd(View view) {
// добавить отступ снизу
setupContentViewPadding(activity, true, BANNER_HEIGHT);
}
});
Когда баннер загружен, мы вызываем setupContentViewPadding, чтобы динамически добавить отступ снизу.
Затем мы добавляем наш баннер в Window. Мы добавляем его поверх существующих элементов. В классе Window есть метод addContentView для этого:
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
height);// Utils.toDIP(activity, BANNER_HEIGHT));
layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
activity.getWindow().addContentView(banner, layoutParams);
API без View баннера
У нас нет View баннера и мы не можем создать и разместить его явным образом. Но API имеет методы, вроде showBanner — показать баннер.
Я условно назову класс рекламного API — AdAPI (вам следует обратится к руководству вашего рекламного сервиса, чтобы узнать, как называется класс в которой есть методы размещения баннеров). В этом случае, код размещения баннера будет выглядеть примерно так:
Ad banner = AdAPI.loadBanner();
banner.addListener(new AdListener() {
public void adLoaded() {
// add bottom padding, when banner is loaded.
setupContentViewPadding(activity, true, BANNER_HEIGHT);
}
});
Где BANNER_HEIGHT — константа равная высоте баннера.
Здесь возникают некоторые затруднения. Вам следует точно узнать или установить высоту баннера. У нас была такая проблема: мы запускали наше приложение на 3.7 дюймовом смартфоне и на 10.1 дюймовом планшете. Размеры баннера оказались разными на разных устройствах. На смартфоне баннер выглядел отлично, но на планшете он оказался слишком большим и отнял слишком много места у других элементов. Если ваш рекламный сервис позволяет явно задать высоту баннера — лучше задайте, чтобы не было таких неприятных неожиданностей.
Результат
Как вы можете видеть, баннер показан и не перекрывает другие элементы. Отступ снизу добавлен динамически.
Это то, что нам требовалось.
Использование
Подводя итог всему вышесказанному, привожу способ интеграции кода в ваше приложение.
Класс Ads:
public class Ads {
// замените на реальное значение высоты баннера
final private static int BANNER_HEIGHT = 75;
public static void showBottomBanner(Activity activity) {
// замените на реальный код для работы с вашим рекламным сервисом
final Banner banner = new Banner(activity);
banner.setBannerListener(new BannerListener() {
@Override
public void onReceiveAd(View view) {
// добавить отступ снизу
setupContentViewPadding(activity, true, BANNER_HEIGHT);
}
});
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
height);// Utils.toDIP(activity, BANNER_HEIGHT));
layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
activity.getWindow().addContentView(banner, layoutParams);
}
public static void setupContentViewPadding(Activity activity, boolean top, int margin) {
View view = ((ViewGroup) activity.getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0);
if (top)
view.setPadding(view.getPaddingLeft(), margin, view.getPaddingRight(), view.getPaddingBottom());
else
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), margin);
}
}
Замените код в методе showBottomBanner на вызовы API вашего рекламного сервиса.
Чтобы разместить баннер, добавьте строчку кода Ads.showBottomBanner(this) в метод Activity onCreate.
Заключение
В статье я привёл описание как интегрировать баннеры в приложение наиболее корректным и простым способом. Есть и другие способы размещения баннеров. Например, можно взять первый экран показанный в статье и разместить баннер не снизу, а между элементами.
Надеюсь, статья была полезна для вас.
Пожалуйста, пишите ваши замечания в комментариях.
Благодарю за внимание. Успехов вам в разработке!
datacompboy
А разве их не специально встраивают так, чтоб чуть-чуть перекрывало контролы, для повышения CTR?
sergeyotro
Это противоречит правилам AdMob, можно предпреждение/бан схватить, если реклама будет слишком близко к контролам.
datacompboy
Интересно, а как пожаловаться? Я десятки «игрищ» видел, вполне себе из топа, с такой радостью.
pyra
в баннере есть i в кружочке, если нажать то будет три кнопки. Одна из них «Ad covers the page»
datacompboy
значит это не адмоб, так как никаких кружочков нет.
BitGriff Автор
Нашей мотивацией было даже не то, что могут забаннить. А то, что реклама не должна портить функциональность приложения.
Это ладно, если баннер стоит поверх фона или чего-то не важного, но он создавать проблемы пользователю, если что-то перекроет.