原生广告

原生广告是一种可由应用端自定义广告外观的广告格式。使用此功能可以调整广告的视觉风格和版位,使其与您的应用设计相匹配。

备注

演示项目 中提供了展示所有格式类型运作原理的示例。

实体

描述

onAdFailedToLoad

如果 onAdFailedToLoad() 返回错误,请勿尝试使用相同方法再次加载新广告。

NativeAdRequestConfiguration

在请求参数中,您可以指定广告单元编号(RM-id)、图片加载方式、年龄、性别,以及其他可以使展示的广告更具相关性的数据。如需详细了解,请参阅广告定位

adUnitId

使用:

  • Development mode,用于配合演示广告单元 使用。

  • Production mode,用于配合 R-M-XXXXXX-Y 使用(实际 ID 请在 Yandex Advertising Network 界面查询)。R-M-XXXXXX-Y 是您实际广告单元 ID 的模板,将用于接收各种广告创意。

创建原生广告示例

定义 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" // 使用 R-M-XXXXXX-Y 或演示广告单元(请参阅下方说明)
    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"; // 使用 R-M-XXXXXX-Y 或演示广告单元(请参阅下方说明)

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

        // 手动创建绑定(或 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>

检查集成

创建并运行您的项目。您可以通过在 Logcat 中搜索 YandexAds 关键字来检查集成是否成功:

[Integration] Ad type native was integrated successfully
上一篇
下一篇