Нативная реклама
Нативная реклама - это гибкий вид рекламы. Вы можете адаптировать показ к своему пользовательскому интерфейсу, подготовив шаблон.
Appodeal предоставляет 4 варианта реализации макета нативной рекламы 3 шаблона + ваша кастомная
реализация
Все они наследуются от одного и того же класса NativeAdView
.
NativeAdView
состоит из следующих компонентов:
NativeIconView
- Иконка нативной рекламы.AdAttributionView
- Индикатор рекламы. Это TextView с меткой "Ad".TitleVIew
- Заголовок нативной рекламы.DescriptionView
- Текстовый вид описания нативной рекламы.RatingBarView
- Рейтинг приложения в диапазоне [0-5].NativeMediaView
- Медиаконтент нативной рекламы.CallToActionView
- Кнопка для клика.AdChoiceView
- Специальная иконка объявления, предоставляемая рекламной сетью.
- Шаблоны: Для их отображения достаточно сделать следующее:
- Создайте программно или в файле xml разметки один из классов View шаблонов;
Классы шаблонов нативной рекламы:.
NativeAdViewNewsFeed
:NativeAdViewAppWall
:NativeAdViewContentStream
:
NativeAdView для кастомной реализации:
Для его отображения достаточно сделать следующее:
- Создайте класс
NativeAdVIew
программно или в xml файле разметки - Внутри созданного
NativeAdVIew
расположите всеView
/IconView
/MediaView
, необходимые для отображения в любом удобном для вас стиле - Привяжите программно или в файле макета все необходимые
View
/IconView
/MediaView
.
Вид нативной рекламы в кастомной реализации:
NativeAdView
.
Вы можете использовать наше демо приложение в качестве примера по интеграции.
Демо приложениеРуководство по интеграции
- For templates
- Для кастомной разметки
- Создайте программно или в файле xml разметки один из классов View шаблонов:
- XML
- Kotlin
- Java
<com.appodeal.ads.nativead.NativeAdViewNewsFeed
android:id="@+id/native_news_feed"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.appodeal.ads.nativead.NativeAdViewAppWall
android:id="@+id/native_app_wall"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.appodeal.ads.nativead.NativeAdViewContentStream
android:id="@+id/native_content_stream"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
val newsFeedView = NativeAdViewNewsFeed(context)
val appWallView = NativeAdViewAppWall(context)
val contentStreamView = NativeAdViewContentStream(context)
NativeAdViewNewsFeed newsFeedView = new NativeAdViewNewsFeed(context);
NativeAdViewAppWall appWallView = new NativeAdViewAppWall(context);
NativeAdViewContentStream contentStreamView = new NativeAdViewContentStream(context);
- Получите экземпляр представления из макета ИЛИ добавьте программно созданный шаблон ViewTemplate в иерархию View:
- XML
- Kotlin
- Java
val newsFeedView = findViewById<NativeAdViewNewsFeed>(R.id.native_news_feed);
val appWallView = findViewById<NativeAdViewAppWall>(R.id.native_app_wall);
val contentStreamView = findViewById<NativeAdViewContentStream>(R.id.native_content_stream);
NativeAdViewNewsFeed newsFeedView = findViewById(R.id.native_news_feed);
NativeAdViewAppWall appWallView = findViewById(R.id.native_app_wall);
NativeAdViewContentStream contentStreamView = findViewById(R.id.native_content_stream);
rootView.addView(newsFeedView)
rootView.addView(appWallView)
rootView.addView(contentStreamView)
rootView.addView(newsFeedView);
rootView.addView(appWallView);
rootView.addView(contentStreamView);
- Когда NativeAd будет загружен, просто зарегистрируйте его:
- Для одного экземпляра
- Для нескольких экземпляров
- Kotlin
- Java
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
newsFeedView.registerView(Appodeal.getNativeAdCount(1))
}
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
newsFeedView.registerView(Appodeal.getNativeAdCount(1));
}
- Kotlin
- Java
val needToShow = 3
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
val nativeAds = Appodeal.getNativeAdCount(needToShow)
newsFeedView.registerView(nativeAds[0])
appWallView.registerView(nativeAds[1])
contentStreamView.registerView(nativeAds[2])
}
int needToShow = 3;
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
List<NativeAd> nativeAds = Appodeal.getNativeAdCount(needToShow);
newsFeedView.registerView(nativeAds.get(0));
appWallView.registerView(nativeAds.get(1));
contentStreamView.registerView(nativeAds.get(2);
}
- Когда показ завершен и вы больше не планируете использовать NativeAdView, необходимо вызвать метод destroy:
- Kotlin
- Java
nativeAdView.destroy()
nativeAdView.destroy();
Общие требования:.
- Минимальная высота
NativeAdView
должна составлять 32dp; NativeMediaView
должен иметь минимальный размер 120dp x 120dp;- В
AdAttributionView
должен быть четко обозначен в вашем View как "Реклама", чтобы пользователи не приняли его за контент; - Разрешается уменьшать масштаб
NativeIconView
илиNativeMediaView
без изменения соотношения сторон; - Разрешается симметрично обрезать
NativeIconView
илиNativeMediaView
не более чем на 20% только в одном измерении (высота или ширина).
- Создайте свою разметку с
NativeAdView
в качестве родителя:
Вы можете построить макет с любым стилем, расположением элементов и с любым типом
ViewGroup
(ConstrainLayout
, RelativeLayout
, FrameLayout
)
<?xml version="1.0" encoding="utf-8"?>
<com.appodeal.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nativeAdView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:adChoicePosition="end_top"
app:callToActionViewId="@id/callToActionView"
app:descriptionViewId="@id/descriptionView"
app:iconViewId="@id/iconView"
app:mediaViewId="@id/mediaView"
app:ratingViewId="@id/ratingView"
app:titleViewId="@id/titleView"
app:adAttributionViewId="@+id/ad_attribution">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.appodeal.ads.nativead.NativeIconView
android:id="@+id/iconView"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="center_vertical"
android:layout_margin="5dp" />
<TextView
android:id="@+id/ad_attribution"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:background="@color/red" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/titleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="@+id/descriptionView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal">
<RatingBar
android:id="@+id/ratingView"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:id="@+id/callToActionView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="30dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<com.appodeal.ads.nativead.NativeMediaView
android:id="@+id/mediaView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</com.appodeal.ads.nativead.NativeAdView>
Requirements for NativeAdView
elements
Имя view | Тип | Необходимость | Описание |
---|---|---|---|
titleView | TextView | Обязателен | Заголовок нативного объявления. В заголовке всегда должно отображаться не более 25 символов. Если заголовок длиннее, можно добавить многоточие в конце. |
callToActionView | Button | Обязателен | Кнопка призыва к действию. Текст должен отображаться без усечения на видимой кнопке. |
descriptionView | TextView | Опционален | Текстовое описание нативной рекламы. Если вы решили отобразить описание, то в нем должно быть не более 100 символов. В конце можно добавить многоточие. |
ratingView | RatingBar | Опционален | Рейтинг приложения в диапазоне [0-5]. |
adAttributionView | TextView | Обязателен | Индикатор рекламы. Это TextView с меткой "Ad". Вы можете задать цвет текста и фона. Смотрите настройки adAttribution. Вы можете разместить его в любом месте внутри NativeAdView . |
adChoicesView | ViewGroup | Добавляется автоматически | Специальный рекламный значок, предоставляемый рекламной сетью. Если SDK получил AdChoice от рекламной сети, то он прикрепляет его автоматически. Вы можете указать позицию в одном из углов NativeAdView . См. setAdChoice position |
iconView | NativeIconView | Обязателен/Опционален | Медиаконтент нативного объявления. |
mediaView | NativeMediaView | Обязателен/Опционален | Иконка нативного объявления. |
NativeAdView
должен обязательно содержать NativeIconView
или NativeMediaView
.
titleView
, callToActionView
и adAttributionView
должен быть добавлен в любом случае.
- Установите идентификаторы всех дочерних представлений
NativeAdView
.
Это можно сделать либо в xml-файле markdown (рекомендуемый способ), либо программно
- XML
- Kotlin
- Java
<com.appodeal.ads.nativead.NativeAdView
app:callToActionViewId="@id/callToActionView"
app:descriptionViewId="@id/descriptionView"
app:iconViewId="@id/iconView"
app:mediaViewId="@id/mediaView"
app:ratingViewId="@id/ratingView"
app:titleViewId="@id/titleView">
app:adAttributionViewId="@id/adAttribution">
val nativeAdView: NativeAdView = ...
nativeAdView.titleViewId = R.id.titleView
nativeAdView.callToActionViewId = R.id.callToActionView
nativeAdView.descriptionViewId = R.id.descriptionView
nativeAdView.ratingViewId = R.id.ratingView
nativeAdView.iconViewId = R.id.iconView
nativeAdView.mediaViewId = R.id.mediaView
nativeAdView.adAttributionViewId = R.id.adAttribution
// OR
nativeAdView.titleView = findViewById(R.id.titleView)
nativeAdView.callToActionView = findViewById(R.id.callToActionView)
nativeAdView.descriptionView = findViewById(R.id.descriptionView)
nativeAdView.ratingView = findViewById(R.id.ratingView)
nativeAdView.iconView = findViewById(R.id.iconView)
nativeAdView.mediaView = findViewById(R.id.mediaView)
nativeAdView.adAttributionView = findViewById(R.id.adAttribution)
NativeAdView nativeAdView: NativeAdView = ...
nativeAdView.setTitleViewId(R.id.titleView);
nativeAdView.setCallToActionViewId(R.id.callToActionView);
nativeAdView.setDescriptionViewId(R.id.descriptionView);
nativeAdView.setRatingViewId(R.id.ratingView);
nativeAdView.setIconViewId(R.id.iconView);
nativeAdView.setMediaViewId(R.id.mediaView);
nativeAdView.setAdAttributionViewId(R.id.adAttribution);
// OR
nativeAdView.setTitleView(findViewById(R.id.titleView));
nativeAdView.setCallToActionView(findViewById(R.id.callToActionView));
nativeAdView.setDescriptionView(findViewById(R.id.descriptionView));
nativeAdView.setRatingView(findViewById(R.id.ratingView));
nativeAdView.setIconView(findViewById(R.id.iconView));
nativeAdView.setMediaView(findViewById(R.id.mediaView));
nativeAdView.setAdAttributionView(findViewById(R.id.adAttribution));
3.Когда NativeAd
загружен, просто зарегистрируйте его для показа:
- Для одного экземпляра
- Для нескольких экземпляров
- Kotlin
- Java
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
newsFeedView.registerView(Appodeal.getNativeAdCount(1))
}
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
newsFeedView.registerView(Appodeal.getNativeAdCount(1));
}
- Kotlin
- Java
val needToShow = 3
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
val nativeAds = Appodeal.getNativeAdCount(needToShow)
nativeAdView1.registerView(nativeAds[0])
nativeAdView2.registerView(nativeAds[1])
nativeAdView3.registerView(nativeAds[2])
}
int needToShow = 3;
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
List<NativeAd> nativeAds = Appodeal.getNativeAdCount(needToShow);
nativeAdView1.registerView(nativeAds.get(0));
nativeAdView2.registerView(nativeAds.get(1));
nativeAdView3.registerView(nativeAds.get(2));
}
- Когда показ завершен и вы больше не планируете использовать
NativeAdView
, необходимо вызвать методdestroy
:
- Kotlin
- Java
nativeAdView.destroy()
nativeAdView.destroy();
Если вы хотите показать новую NativeAd внутри используемого nativeAdView, просто вызовите
метод nativeAdView.registerView(newNativeAd)
.
Проверка, загружена ли реклама
Чтобы проверить, загружен ли хотя бы 1 экземпляр NativeAd
, используйте метод:
- Kotlin
- Java
Appodeal.isLoaded(Appodeal.NATIVE)
Appodeal.isLoaded(Appodeal.NATIVE);
Чтобы узнать, сколько экземпляров NativeAd
загружено, используйте метод:
- Kotlin
- Java
val nativeAmount = Appodeal.getAvailableNativeAdsCount()
int nativeAmount = Appodeal.getAvailableNativeAdsCount();
По умолчанию Appodeal SDK с включенной функцией AutoCahce загружает по 2 экземпляра NativeAd
.
Мы рекомендуем всегда проверять, доступно ли объявление, прежде чем пытаться его показать.
Получить загруженную рекламу
Чтобы получить загруженную нативную рекламу, воспользуйтесь следующим методом:
- Kotlin
- Java
val nativeAds: List<NativeAd> = Appodeal.getNativeAds(amount)
List<NativeAd> nativeAds = Appodeal.getNativeAds(int amount);
После получения рекламы она удаляется из нашего кэша SDK.
Отображение
Для отображения NativeAd
необходимо вызвать следующий код:
- Kotlin
- Java
NativeAdView.registerView(nativeAd: NativeAd)
NativeAdView.registerView(NativeAd nativeAd);
SDK не может показывать рекламу без подключения к сети!
NativeAdView.registerView()
возвращает значение boolean, указывающее, был ли вызов метода show
передан соответствующему SDK.
Перед вызовом метода registerView(nativeAd)
, NativeAdView
находится в состоянии visibility == GONE
.
После вызова состояние автоматически изменится на visibility == VISIBLE
.
Вам не нужно менять состояние видимости, Appodeal SDK делает это автоматически.
После вызова destroy()
состояние автоматически изменится на visibility == GONE
.
NativeAdView
и его наследники имеют встроенный атрибут tools:visibility="visible"
, поэтому представление
будет отображаться в разметке IDE во время разработки.
Плейменты
Appodeal SDK позволяет маркировать каждый показ различными плейсментами. Чтобы использовать плейсмент, необходимо создать его в Appodeal Dashboard. Узнайте больше о плейсментах.
Чтобы показать рекламу с плейсментом, необходимо вызвать метод show:
- Kotlin
- Java
NativeAdView.registerView(nativeAd: NativeAd, yourPlacementName: String)
NativeAdView.registerView(NativeAd nativeAd, String yourPlacementName)
Если загруженное объявление не может быть показано для конкретного размещения, то ничего показано не будет.
Если автоматическое кэширование включено, sdk начнет загружать очередную рекламу, что может повлиять на display rate. Чтобы сохранить загруженную рекламу для дальнейшего использования (например, для другого плейсмента), проверьте, может ли оно быть показано до вызова метода show:
- Kotlin
- Java
if (NativeAd.canShow(context: Context, yourPlacementName: String)){
NativeAdView.registerView(nativeAd: NativeAd, yourPlacementName: String)
}
if (NativeAd.canShow(Context context, String yourPlacementName)){
NativeAdView.registerView(NativeAd nativeAd, String yourPlacementName)
}
Для каждого плейсмента можно настроить свою логику показа.
Если у вас нет плейсментов, или вы вызываете NativeAdView.registerView
с несуществующим плейсментом,
показ будет помече как плейсмент 'по умолчанию' и будут применены его настройки.
Настройки плейсмента влияют ТОЛЬКО на показ рекламы, но не на загрузку или кэширование.
Прекращение трекинга показа
Для прекращение трекинга показа нативной рекламы с зарегистрированной в данный момент NativeAdView
используйте метод:
- Kotlin
- Java
NativeAdView.unregisterView()
NativeAdView.unregisterView();
Метод UnregisterView
не скрывает NativeAdView
. Он приостанавливает отслеживание отображения
нативной рекламы.
UnregisterView
имеет смысл использовать, например, если NativeAdView
находится за пределами
экрана во время прокрутки списка или временно перекрывается другим View
/Fragment
/Activity
.
Уничтожение нативной рекламы
Чтобы уничтожить NativeAdView и выполнить очистку ресурсов, а также скрыть ваш View, используйте метод:
- Kotlin
- Java
NativeAdView.destroy()
NativeAdView.destroy();
Этот метод следует вызывать, когда нативная реклама больше не нужна.
Кроме того, при вызове destroy()
срабатывает логика unregisterView
.
Методы обратного вызова
- Kotlin
- Java
Appodeal.setNativeCallbacks(object : NativeCallbacks {
override fun onNativeLoaded() {
// Срабатывает когда реклама была загружена
}
override fun onNativeFailedToLoad() {
// Срабатывает при невозможности загрузки рекламы в данный момент
}
override fun onNativeShown(nativeAd: NativeAd) {
// Срабатывает при отображении нативной рекламы
}
override fun onNativeShowFailed(nativeAd: NativeAd) {
// Срабатывает при ошибке показа нативной рекламы
}
override fun onNativeClicked(nativeAd: NativeAd) {
// Срабатыввает при клике на нативную рекламу
}
override fun onNativeExpired() {
// Срабатывает когда нативная рекламы была просрочена
}
})
Appodeal.setNativeCallbacks(new NativeCallbacks() {
@Override
public void onNativeLoaded() {
// Срабатывает когда реклама была загружена
}
@Override
public void onNativeFailedToLoad() {
// Срабатывает при невозможности загрузки рекламы в данный момент
}
@Override
public void onNativeShown(NativeAd nativeAd) {
// Срабатывает при отображении нативной рекламы
}
@Override
public void onNativeShowFailed(NativeAd nativeAd) {
// Срабатывает при ошибке показа нативной рекламы
}
@Override
public void onNativeClicked(NativeAd nativeAd) {
// Срабатыввает при клике на нативную рекламу
}
@Override
public void onNativeExpired() {
// Срабатывает когда нативная рекламы была просрочена
}
});
Все методы обратного вызова вызываются в главном потоке
Ручное кеширование
Чтобы отключить автоматическое кэширование нативной рекламы, используйте приведенный ниже код перед инициализацией SDK:
- Kotlin
- Java
Appodeal.setAutoCache(Appodeal.NATIVE, false)
Appodeal.setAutoCache(Appodeal.NATIVE, false);
Узнайте больше у ручном кешировании в нашем FAQ.
Кеширование
Для загрузки нативной рекламы используйте метод:
- Kotlin
- Java
Appodeal.cache(this, Appodeal.NATIVE)
Appodeal.cache(this, Appodeal.NATIVE);
Для загрузки несколькиъ экземпляров нативной рекламы используйте метод:
- Kotlin
- Java
Appodeal.cache(this, Appodeal.NATIVE, 3)
Appodeal.cache(this, Appodeal.NATIVE, 3);
Вы можете запросить максимум 5 NativeAd
.
Количество кэшированных объявлений не гарантируется и может быть меньше запрошенного.
Проверка инициализации рекламы
Проверить, инициализирована ли нативная реклама, можно с помощью метода:
- Kotlin
- Java
Appodeal.isInitialized(Appodeal.NATIVE)
Appodeal.isInitialized(Appodeal.NATIVE);
Возавращает true
, если нативная реклама была проинициализирована.
Провека, включен ли автокэш
Чтобы проверить, включен ли автокэш для нативной рекламы, можно воспользоваться методом:
- Kotlin
- Java
Appodeal.isAutoCacheEnabled(Appodeal.NATIVE)
Appodeal.isAutoCacheEnabled(Appodeal.NATIVE);
Возвращает true
, если автокеш включен для нативной рекламы.
Получение прогнозируемого eCPM
Чтобы получить прогнозируемый eCPM из следующего блока в очереди на опрос, используйте метод:
- Kotlin
- Java
NativeAd.predictedEcpm
NativeAd.getPredictedEcpm();
Конфигурация
Установка предпочтительного типа медиаконтента
Вы можете указать Appodeal SDK предпочтительный тип контента для NativeAd
.
Для этого используйте метод:
- Kotlin
- Java
// будут загружаться как статические изображения, так и видео контент
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Auto)
// будет загружаться только статические изображения
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.NoVideo)
// будет загружаться только видео контент
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Video)
// будут загружаться как статические изображения, так и видео контент
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Auto);
// будет загружаться только статические изображения
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.NoVideo);
// будет загружаться только видео контент
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Video);
Установка типа видео не гарантирует, что оно будет загружено, а лишь указывает предпочтительный тип.
Проверить, содержит ли загружаемая реклама видео, можно с помощью метода:
- Kotlin
- Java
NativeAd.containsVideo()
NativeAd.containsVideo();
Возвращает true
, если NativeAd
содержит видео.
Используйте этот метод для получения предпочтительного типа содержимого:
- Kotlin
- Java
Appodeal.getPreferredNativeContentType()
Appodeal.getPreferredNativeContentType();
Действует только на содержимое внутри NativeMediaView
. Поэтому имеет смысл использовать его только в случае
случае шаблона NativeAdViewContentStream
или собственной пользовательской реализации NativeAdView
.
Контент для NativeIconView
всегда представляет собой статическое изображение
указание позиции adChoice
Вы можете задать позицию в одном из углов NativeAdView
:
- XML
- Kotlin
- Java
app:adChoicePosition="end_top"
nativeAdView.setAdChoicesPosition(Position.END_TOP)
nativeAdView.setAdChoicesPosition(Position.END_TOP);
В качестве Position
можно указать один из 4 вариантов:
START_TOP
- совпадает с левым верхним углом NativeAdView
;
START_BOTTOM
- совпадает с левым нижним углом NativeAdView
;
END_TOP
- совпадает с правым верхним углом NativeAdView
;
END_BOTTOM
- совпадает с правым нижним углом NativeAdView
.
Настройка AdAttributionView
Цвет текста и цвет фона для AdAttributionView можно задать в NativeAdView
:
- XML
- Kotlin
- Java
app:adAttributionBackgroundColor="@color/red"
app:adAttributionTextColor="@color/black"
nativeAdView.setAdAttributionBackground(Color.RED)
nativeAdView.setAdAttributionTextColor(Color.BLACK)
nativeAdView.setAdAttributionBackground(Color.RED);
nativeAdView.setAdAttributionTextColor(Color.BLACK);
Цвет должен иметь формат ColorInt. См. раздел android.graphics.Color
.
Для пользовательского NativeAdView
вы можете сделать то же самое через вашу xml-разметку, используя
атрибуты android:textColor
и android:background
для adAttribution TextView
.
Работа со списками
Чтобы использовать NativeAd
в RecyclerView
, можно воспользоваться следующим примером:
- Создайте объект ListItem, который будет служить для определения
itemViewType
в RecyclerView.ListAdapter
- Kotlin
- Java
sealed interface ListItem {
fun getItemId(): Int
class NativeAdItem(val getNativeAd: () -> NativeAd?) : ListItem {
override fun getItemId() = NATIVE_AD_ITEM
companion object {
const val NATIVE_AD_ITEM = 3
}
}
data class YourDataItem(val userData: Int) : ListItem {
override fun getItemId() = USER_ITEM
companion object {
const val USER_ITEM = 2
}
}
}
public interface ListItem {
int getItemId();
int hashCode();
}
public final class NativeAdItem implements ListItem {
private final NativeAd nativeAd;
public NativeAdItem(NativeAd nativeAd) {
this.nativeAd = nativeAd;
}
@Override
public int getItemId() {
return NATIVE_AD_ITEM;
}
public NativeAd getNativeAd() {
return nativeAd;
}
public static final int NATIVE_AD_ITEM = 3;
}
public final class YourDataItem implements ListItem {
private final int userData;
public YourDataItem(int userData) {
this.userData = userData;
}
@Override
public int getItemId() {
return USER_ITEM;
}
public int getUserData() {
return userData;
}
public static final int USER_ITEM = 2;
}
- Создать объект
DiffUtil.ItemCallback<ListItem>
, который будет сообщатьListAdapter
различия между элементами
- Kotlin
- Java
internal class DiffUtils : DiffUtil.ItemCallback<ListItem>() {
override fun areItemsTheSame(oldItem: ListItem, newItem: ListItem) =
oldItem.getItemId() == newItem.getItemId()
override fun areContentsTheSame(oldItem: ListItem, newItem: ListItem) =
oldItem.hashCode() == newItem.hashCode()
}
class DiffUtils extends DiffUtil.ItemCallback<ListItem> {
@Override
public boolean areItemsTheSame(ListItem oldItem, ListItem newItem) {
return oldItem.getItemId() == newItem.getItemId();
}
@Override
public boolean areContentsTheSame(ListItem oldItem, ListItem newItem) {
return oldItem.hashCode() == newItem.hashCode();
}
}
- Создайте объект
ListAdapter
, который будет являться адаптером дляRecyclerView
:
- Kotlin
- Java
class NativeListAdapter : ListAdapter<ListItem, ListHolder>(DiffUtils()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListHolder {
return when (viewType) {
NATIVE_AD_ITEM -> { DynamicAdViewHolder(NativeAdViewContentStream(parent.context)) }
else -> {
YourViewHolder(
YourDataItemBinding.inflate(LayoutInflater.from(parent.context),
parent,
false
))
}
}
}
override fun onBindViewHolder(holder: ListHolder, position: Int) {
when (val item = getItem(position)) {
is ListItem.YourDataItem -> (holder as YourViewHolder).bind(item)
is ListItem.NativeAdItem -> (holder as DynamicAdViewHolder).bind(item)
}
}
override fun getItemViewType(position: Int): Int {
return when (currentList[position]) {
is ListItem.YourDataItem -> USER_ITEM
is ListItem.NativeAdItem -> NATIVE_AD_ITEM
}
}
sealed class ListHolder(root: View) : RecyclerView.ViewHolder(root) {
class YourViewHolder(private val binding: YourDataItemBinding) : ListHolder(binding.root) {
fun bind(item: ListItem.YourDataItem) {
binding.root.text = item.userData.toString()
}
}
class DynamicAdViewHolder(itemView: View) : ListHolder(itemView) {
fun bind(item: ListItem.NativeAdItem) {
val nativeAd = item.getNativeAd.invoke()
if (nativeAd != null) {
(itemView as NativeAdView).registerView(nativeAd)
}
}
}
}
}
public class NativeListAdapter extends ListAdapter<ListItem, NativeListAdapter.ListHolder> {
public NativeListAdapter() {
super(new DiffUtils());
}
@Override
public ListHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == NATIVE_AD_ITEM) {
return new DynamicAdViewHolder(new NativeAdViewContentStream(parent.getContext()));
} else {
YourDataItemBinding binding = YourDataItemBinding.inflate(inflater,
parent,
false);
return new YourViewHolder(binding);
}
}
@Override
public void onBindViewHolder(ListHolder holder, int position) {
ListItem item = getItem(position);
if (item instanceof YourDataItem) {
((YourViewHolder) holder).bind((YourDataItem) item);
} else if (item instanceof NativeAdItem) {
((DynamicAdViewHolder) holder).bind((NativeAdItem) item);
}
}
@Override
public int getItemViewType(int position) {
ListItem item = getItem(position);
if (item instanceof YourDataItem) {
return USER_ITEM;
} else if (item instanceof NativeAdItem) {
return NATIVE_AD_ITEM;
}
return super.getItemViewType(position);
}
abstract static class ListHolder extends RecyclerView.ViewHolder {
ListHolder(View root) {
super(root);
}
}
static class YourViewHolder extends ListHolder {
private YourDataItemBinding binding;
YourViewHolder(YourDataItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void bind(YourDataItem item) {
binding.getRoot().setText(String.valueOf(item.getUserData()));
}
}
static class DynamicAdViewHolder extends ListHolder {
DynamicAdViewHolder(View itemView) {
super(itemView);
}
void bind(NativeAdItem item) {
NativeAd nativeAd = item.getNativeAd();
if (nativeAd != null) {
((NativeAdView) itemView).registerView(nativeAd);
}
}
}
}
NATIVE_AD_ITEM
- NativeAdItem.NATIVE_AD_ITEM
- В качестве Activity/Fragment будем использовать разметку:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/colorBackground">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</FrameLayout>
Мы будем использовать этот пример в качестве разметки YourDataItem:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:textSize="64sp"
tools:text="1" />
- В вашем
Activity
/Fragment
, добавьте следующий код:
- Kotlin
- Java
class NativeActivity : AppCompatActivity() {
private val getNativeAd: () -> NativeAd? = { Appodeal.getNativeAds(1).firstOrNull() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityNativeBinding.inflate(layoutInflater)
setContentView(binding.root)
val nativeListAdapter = NativeListAdapter()
binding.recyclerView.adapter = nativeListAdapter
setUpAppodealSDK()
}
private fun setUpAppodealSDK() {
Appodeal.setLogLevel(LogLevel.verbose)
Appodeal.setTesting(true)
Appodeal.initialize(this, APPODEAL_APP_KEY, Appodeal.NATIVE) { errors ->
val initResult = if (errors.isNullOrEmpty()) "successfully" else "with ${errors.size} errors"
Log.d("TAG", "onInitializationFinished: $initResult")
}
}
private fun obtainData(nativeListAdapter: NativeListAdapter) {
val yourDataItems = generateYourData()
nativeListAdapter.submitList(yourDataItems.addNativeAdItems())
}
private fun List<ListItem>.addNativeAdItems() =
this.foldIndexed(
initial = listOf(),
operation = { index: Int, acc: List<ListItem>, yourDataItem: ListItem ->
val shouldAdd = index % STEPS == 0 && index != 0
if (shouldAdd) {
acc + createNativeAdItem() + yourDataItem
} else {
acc + yourDataItem
}
}
)
private fun generateYourData(): List<ListItem> =
(1..USER_DATA_SIZE).toList().map { ListItem.YourDataItem(userData = it) }
private fun createNativeAdItem(): ListItem.NativeAdItem =
ListItem.NativeAdItem(getNativeAd = getNativeAd)
}
private const val USER_DATA_SIZE = 200
private const val STEPS = 5
public class NativeActivity extends AppCompatActivity {
private static final String TAG = "NativeActivity";
private static final String APP_KEY = "YOUR_APP_KEY";
private static final int USER_DATA_SIZE = 200;
private static final int STEPS = 5;
private final GetNativeAdCallback getNativeAd = () -> {
List<NativeAd> nativeAds = Appodeal.getNativeAds(1);
return nativeAds.size() > 0 ? nativeAds.get(0) : null;
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityNativeBinding binding = ActivityNativeBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
NativeListAdapter nativeListAdapter = new NativeListAdapter();
binding.recyclerView.setAdapter(nativeListAdapter);
setUpAppodealSDK();
}
private void setUpAppodealSDK() {
Appodeal.setTesting(true);
Appodeal.initialize(this, APPODEAL_APP_KEY, Appodeal.NATIVE, errors -> {
if (errors == null || errors.isEmpty()) {
Log.d(TAG, "onInitializationFinished: successfully");
} else {
Log.d(TAG, "onInitializationFinished: with " + errors.size() + " errors");
}
});
}
private void obtainData(NativeListAdapter nativeListAdapter) {
List<ListItem> yourDataItems = generateYourData();
List<ListItem> itemsWithNativeAd = addNativeAdItems(yourDataItems);
nativeListAdapter.submitList(itemsWithNativeAd);
}
private List<ListItem> generateYourData() {
List<ListItem> yourDataItems = new ArrayList<>();
for (int i = 1; i <= USER_DATA_SIZE; i++) {
yourDataItems.add(new YourDataItem(i));
}
return yourDataItems;
}
private List<ListItem> addNativeAdItems(List<ListItem> yourDataItems) {
List<ListItem> itemsWithNativeAd = new ArrayList<>();
for (int i = 0; i < yourDataItems.size(); i++) {
ListItem yourDataItem = yourDataItems.get(i);
boolean shouldAdd = i % STEPS == 0 && i != 0;
if (shouldAdd) {
itemsWithNativeAd.add(createNativeAdItem());
}
itemsWithNativeAd.add(yourDataItem);
}
return itemsWithNativeAd;
}
private NativeAdItem createNativeAdItem() {
return new NativeAdItem(getNativeAd.getNativeAd());
}
interface GetNativeAdCallback {
NativeAd getNativeAd();
}
}
STEPS
- шаг, через который будет устанавливаться NativeAd
;
addNativeAdItems()
- логика вставки NativeAd
в список через определенное количество STEPS
.
Готово! Когда вы захотите вставить нативные объявления в RecyclerView
, просто вызовите метод obtainData()
.
Распространенные ошибки
- Отсутствует adAttributionView
Большинство рекламных сетей требуют от издателей добавлять специальную метку к нативным объявлениям, чтобы пользователи не приняли их за контент. Поэтому всегда нужно следить за тем, чтобы нативная реклама в вашей разметке имели adAttributionView (например, "Ad") и значок AdChoices.
- Отсутствие необходимых элементов нативной рекламы.
Каждое нативное объявление должно содержать:
titleView TextView;
callToActionView Button;
adAttribution TextView;
NativeIconView
илиNativeMedaiaView
.Изменение элементов нативной рекламы.
Рекламодатели ожидают, что их объявления будут отображаться четко и без каких-либо изменений. Вы можете масштабировать кнопки и изображения, но не следует их обрезать, закрывать или искажать.
- Наложение элементов нативной рекламы друг на друга.
Убедитесь, что все элементы нативного объявления видны и не накладываются друг на друга.
Требования к нативным объявлениям:
- Все поля нативной рекламы, отмеченные как обязательные, должны быть отображены.
- Размер изображений может быть изменен в соответствии с размерами рекламного пространства, но не
- должен быть значительно искажен или обрезаны.
Проверка отображения
Вы всегда можете проверить в логах, был ли отслежен показ и видно ли вашу рекламу.
Если показ был отслежен успешно, вы увидите журнал Native [Notify Shown].
- Log
Appodeal com.example.app D Native [Notify Shown]