Нативная реклама
Нативная реклама (Native) — реклама, внешний вид которой может определяться на стороне приложения. Эта особенность позволяет изменять визуальный стиль объявлений и места их размещения с учетом особенностей дизайна приложения.
Примечание
Пример работы всех типов форматов есть в демопроекте.
|
Сущность |
Описание |
|
|
При получении ошибки в |
|
|
В параметрах запроса вы можете указать идентификатор рекламного блока ( |
|
|
Используйте:
|
Пример создания нативной рекламы
Добавьте создание класса CustomNative и NativeAdView.xml:
class CustomNativeAdActivity : AppCompatActivity(), NativeAdEventListener {
private val nativeAdView get() = binding.nativeAd.root
private val additionalContainer get() = binding.additionalContainer
private val adUnitId = "demo-native-app-yandex" // Use R-M-XXXXXX-Y or demo-block (look for the description below)
private var nativeAdLoader: NativeAdLoader? = null
private lateinit var binding: ActivityCustomNativeAdBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCustomNativeAdBinding.inflate(layoutInflater)
binding.btnShowBanner.setOnClickListener {
loadNative()
}
setContentView(binding.root)
}
private fun loadNative() {
createNative()
additionalContainer.removeAllViews()
nativeAdView.isVisible = false
nativeAdLoader?.loadAd(buildAdRequestConfiguration())
}
private fun createNative() {
nativeAdLoader = NativeAdLoader(this).apply {
setNativeAdLoadListener(object : NativeAdLoadListener {
override fun onAdLoaded(ad: NativeAd) {
bindNative(ad)
}
override fun onAdFailedToLoad(error: AdRequestError) {}
})
}
}
private fun buildAdRequestConfiguration(): NativeAdRequestConfiguration {
return NativeAdRequestConfiguration
.Builder(adUnitId)
.setShouldLoadImagesAutomatically(true)
.build()
}
private fun bindNative(nativeAd: NativeAd) {
val nativeAdViewBinder = binding.nativeAd.run {
NativeAdViewBinder.Builder(nativeAdView)
.setAgeView(age)
.setBodyView(body)
.setCallToActionView(callToAction)
.setDomainView(domain)
.setFaviconView(favicon)
.setFeedbackView(feedback)
.setIconView(icon)
.setMediaView(media)
.setPriceView(price)
.setRatingView(rating)
.setReviewCountView(reviewCount)
.setSponsoredView(sponsored)
.setTitleView(title)
.setWarningView(warning)
.build()
}
try {
nativeAd.bindNativeAd(nativeAdViewBinder)
nativeAd.info?.let { processAdditionalText(it) }
nativeAd.setNativeAdEventListener(this@CustomNativeAdActivity)
nativeAdView.isVisible = true
} catch (exception: NativeAdException) {
println("Error binding native ad: ${exception.message}")
}
}
private fun processAdditionalText(rawJson: String) {
try {
val jsonObject = JSONObject(rawJson)
val contentJSONArray = jsonObject.getJSONArray("content")
repeat(contentJSONArray.length()) { index ->
val elementName = contentJSONArray.getString(index)
val elementConfiguration = jsonObject.getJSONObject(elementName)
when (elementName) {
"text" -> addTextToLayout(elementConfiguration, index)
"button" -> addButtonToLayout(elementConfiguration, index)
}
}
} catch (e: JSONException) {
println("Error processing additional text: ${e.message}")
}
}
private fun addTextToLayout(textConfiguration: JSONObject, index: Int) {
val textView = TextView(this).apply {
setPadding(16)
text = textConfiguration.getString("value")
}
additionalContainer.addView(textView, index)
}
private fun addButtonToLayout(buttonConfiguration: JSONObject, index: Int) {
val buttonView = Button(this).apply {
setPadding(16)
text = buttonConfiguration.getString("label")
val colorHex = buttonConfiguration.getString("backgroundColor")
setBackgroundColor(Color.parseColor(colorHex))
setOnClickListener {
val link = buttonConfiguration.getString("link")
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
startActivity(intent)
}
}
additionalContainer.addView(buttonView, index)
}
override fun onDestroy() {
nativeAdLoader?.setNativeAdLoadListener(null)
nativeAdLoader = null
super.onDestroy()
}
override fun onAdClicked() {}
override fun onImpression(impressionData: ImpressionData?) {}
override fun onLeftApplication() {}
override fun onReturnedToApplication() {}
}
public class CustomNativeAdActivity extends AppCompatActivity implements NativeAdEventListener {
private ActivityCustomNativeAdBinding binding;
private NativeAdLoader nativeAdLoader;
private NativeAdViewBinder nativeAdViewBinder;
private final String adUnitId = "demo-native-app-yandex"; // Use R-M-XXXXXX-Y or demo-block (look for the description below)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.btnShowBanner.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadNative();
}
});
}
private void loadNative() {
createNative();
binding.additionalContainer.removeAllViews();
binding.nativeAd.getRoot().setVisibility(View.GONE);
if (nativeAdLoader != null) {
nativeAdLoader.loadAd(buildAdRequestConfiguration());
}
}
private void createNative() {
nativeAdLoader = new NativeAdLoader(this);
nativeAdLoader.setNativeAdLoadListener(new NativeAdLoadListener() {
@Override
public void onAdLoaded(NativeAd ad) {
bindNative(ad);
}
@Override
public void onAdFailedToLoad(AdRequestError error) {}
});
}
private NativeAdRequestConfiguration buildAdRequestConfiguration() {
return new NativeAdRequestConfiguration.Builder(adUnitId)
.setShouldLoadImagesAutomatically(true)
.build();
}
private void bindNative(NativeAd nativeAd) {
NativeAdLayoutBinding adBinding = binding.nativeAd;
// Сборка биндинга вручную (или если auto-generated ViewBinding)
nativeAdViewBinder = new NativeAdViewBinder.Builder(adBinding.getRoot())
.setAgeView(adBinding.age)
.setBodyView(adBinding.body)
.setCallToActionView(adBinding.callToAction)
.setDomainView(adBinding.domain)
.setFaviconView(adBinding.favicon)
.setFeedbackView(adBinding.feedback)
.setIconView(adBinding.icon)
.setMediaView(adBinding.media)
.setPriceView(adBinding.price)
.setRatingView(adBinding.rating)
.setReviewCountView(adBinding.reviewCount)
.setSponsoredView(adBinding.sponsored)
.setTitleView(adBinding.title)
.setWarningView(adBinding.warning)
.build();
try {
nativeAd.bindNativeAd(nativeAdViewBinder);
String infoJson = nativeAd.getInfo();
if (infoJson != null) {
processAdditionalText(infoJson);
}
nativeAd.setNativeAdEventListener(this);
adBinding.getRoot().setVisibility(View.VISIBLE);
} catch (NativeAdException exception) {
System.out.println("Error binding native ad: " + exception.getMessage());
}
}
private void processAdditionalText(String rawJson) {
try {
JSONObject jsonObject = new JSONObject(rawJson);
JSONArray contentJSONArray = jsonObject.getJSONArray("content");
for (int i = 0; i < contentJSONArray.length(); ++i) {
String elementName = contentJSONArray.getString(i);
JSONObject elementConfiguration = jsonObject.getJSONObject(elementName);
switch (elementName) {
case "text":
addTextToLayout(elementConfiguration, i);
break;
case "button":
addButtonToLayout(elementConfiguration, i);
break;
}
}
} catch (JSONException e) {
System.out.println("Error processing additional text: " + e.getMessage());
}
}
private void addTextToLayout(JSONObject textConfiguration, int index) {
TextView textView = new TextView(this);
textView.setPadding(16, 16, 16, 16);
try {
textView.setText(textConfiguration.getString("value"));
} catch (JSONException ignored) { }
binding.additionalContainer.addView(textView, index);
}
private void addButtonToLayout(final JSONObject buttonConfiguration, int index) {
Button buttonView = new Button(this);
buttonView.setPadding(16, 16, 16, 16);
try {
buttonView.setText(buttonConfiguration.getString("label"));
String colorHex = buttonConfiguration.getString("backgroundColor");
buttonView.setBackgroundColor(Color.parseColor(colorHex));
buttonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String link = buttonConfiguration.getString("link");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
startActivity(intent);
} catch (JSONException ignored) { }
}
});
} catch (JSONException ignored) { }
binding.additionalContainer.addView(buttonView, index);
}
@Override
protected void onDestroy() {
if (nativeAdLoader != null) {
nativeAdLoader.setNativeAdLoadListener(null);
nativeAdLoader = null;
}
super.onDestroy();
}
@Override
public void onAdClicked() {}
@Override
public void onImpression(@Nullable ImpressionData impressionData) {}
@Override
public void onLeftApplication() {}
@Override
public void onReturnedToApplication() {}
}
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CustomNativeAdActivity">
<Button
android:id="@+id/btnShowBanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load NativeAd"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<include
android:id="@+id/native_ad"
layout="@layout/native_ad_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintVertical_weight="1"
app:layout_constraintBottom_toTopOf="@+id/additional_container"/>
<LinearLayout
android:id="@+id/additional_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.yandex.mobile.ads.nativeads.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/native_ad_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp">
<androidx.constraintlayout.widget.Group
android:id="@+id/components"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="age,sponsored,feedback,title" />
<TextView
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#7f7f7f"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
app:layout_constraintEnd_toStartOf="@id/sponsored"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="18+"
tools:visibility="visible" />
<TextView
android:id="@+id/sponsored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#7f7f7f"
android:textSize="11sp"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
app:layout_constraintEnd_toStartOf="@id/feedback"
app:layout_constraintStart_toEndOf="@id/age"
app:layout_constraintTop_toTopOf="parent"
tools:text="Yandex.Direct"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/feedback"
android:layout_width="16dp"
android:layout_height="16dp"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
android:src="@drawable/close_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/sponsored"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="age,sponsored,feedback" />
<ImageView
android:id="@+id/icon"
android:layout_width="80dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/barrier_body"
app:layout_constraintEnd_toStartOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/barrier_top"
tools:visibility="visible" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:maxLines="2"
android:textSize="15sp"
style="@style/TextAppearance.Material3.TitleSmall"
app:layout_constraintBottom_toTopOf="@id/body"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/barrier_top"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Yandex.Browser for iPhone and Android"
tools:visibility="visible" />
<TextView
android:id="@+id/body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="3"
android:textSize="13sp"
style="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toTopOf="@id/barrier_domain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="Your bookmarks and favorite sites are available to you on any device with Yandex.Browser. You will never lose them, even if you lose your device or break it."
tools:visibility="visible" />
<ImageView
android:id="@+id/favicon"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:layout_constraintBottom_toTopOf="@id/barrier_domain"
app:layout_constraintEnd_toStartOf="@id/domain"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/body"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_domain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="domain,favicon" />
<TextView
android:id="@+id/domain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#7f7f7f"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/barrier_body"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/favicon"
app:layout_constraintTop_toBottomOf="@id/body"
tools:text="https://browser.yandex.com"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="title,icon,body,domain,favicon" />
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toTopOf="@id/rating"
app:layout_constraintEnd_toStartOf="@id/barrier_rating"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/barrier_body"
tools:text="Free"
tools:visibility="visible" />
<com.example.myapplication.RatingView
android:id="@+id/rating"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:numStars="5"
android:stepSize="0.5"
app:layout_constraintBottom_toTopOf="@id/review_count"
app:layout_constraintEnd_toStartOf="@id/barrier_rating"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/price"
tools:visibility="visible" />
<TextView
android:id="@+id/review_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#7f7f7f"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/barrier_footer"
app:layout_constraintEnd_toStartOf="@id/barrier_rating"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/barrier_icon"
app:layout_constraintTop_toBottomOf="@id/rating"
tools:text="review count"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="icon" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="rating,price,review_count" />
<Button
android:id="@+id/call_to_action"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/call_to_action_background"
android:maxLines="1"
android:minHeight="36dp"
android:textAllCaps="false"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/barrier_footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_rating"
app:layout_constraintTop_toBottomOf="@id/barrier_body"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintVertical_bias="1"
tools:text="Install"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="price,domain,call_to_action,review_count" />
<com.yandex.mobile.ads.nativeads.MediaView
android:id="@+id/media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier_footer"
app:layout_constraintBottom_toTopOf="@id/warning"
tools:visibility="visible" />
<TextView
android:id="@+id/warning"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#f5f5f5"
android:paddingLeft="8dp"
android:paddingTop="4dp"
android:paddingRight="8dp"
android:textColor="#7f7f7f"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/media"
android:visibility="gone"
tools:text="We strongly recommend avoiding this type of website and not clicking the Ignore this warning button!"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.yandex.mobile.ads.nativeads.NativeAdView>
Проверка интеграции
Соберите и запустите проект. Успешную интеграцию SDK можно проверить в Logcat по ключевому слову YandexAds:
[Integration] Ad type native was integrated successfully