原生广告

在 Android 自定义布局中加载和渲染 CloudX 原生广告

原生广告会公开标题、正文、图标、媒体和行动号召等独立素材,让您能够按照应用的视觉风格进行布局。CloudX 会填充已绑定的视图,并由中标网络的适配器处理展示和点击跟踪。

集成分为三个步骤:

  1. 绑定布局中的 UI 组件。
  2. 创建加载器,然后加载或渲染原生广告。
  3. 不再需要广告和加载器时将其销毁。

支持的网络

各网络的 Native 支持情况(包括 Native Banner 和 Native MREC 变体)以 Native 广告格式矩阵为准。各适配器的依赖和网络特定配置请参阅对应的概览页。

1. 绑定 UI 组件

创建包含所需原生广告素材的布局,然后使用 CloudXNativeAdViewBinder 映射各视图 ID。网络可能不会返回所有可选素材,因此布局应能够收起或隐藏没有内容的视图。

选项容器是必需的:CloudX 通过它显示网络提供的 AdChoices 或隐私控制。

res/layout/native_ad_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">

        <FrameLayout
            android:id="@+id/native_ad_options"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical">

            <ImageView
                android:id="@+id/native_ad_icon"
                android:layout_width="48dp"
                android:layout_height="48dp" />

            <TextView
                android:id="@+id/native_ad_title"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginStart="8dp"
                android:textSize="16sp"
                android:textStyle="bold" />
        </LinearLayout>

        <TextView
            android:id="@+id/native_ad_body"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp" />

        <FrameLayout
            android:id="@+id/native_ad_media_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:gravity="center_vertical">

            <TextView
                android:id="@+id/native_ad_advertiser"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:textColor="#888" />

            <FrameLayout
                android:id="@+id/native_ad_star_rating"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <Button
                android:id="@+id/native_ad_cta"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>

    </LinearLayout>
</FrameLayout>
val binder = CloudXNativeAdViewBinder.Builder(R.layout.native_ad_layout)
    .setTitleTextViewId(R.id.native_ad_title)
    .setBodyTextViewId(R.id.native_ad_body)
    .setIconImageViewId(R.id.native_ad_icon)
    .setMediaContentViewGroupId(R.id.native_ad_media_container)
    .setCallToActionButtonId(R.id.native_ad_cta)
    .setOptionsContentViewGroupId(R.id.native_ad_options)
    .setAdvertiserTextViewId(R.id.native_ad_advertiser)
    .setStarRatingContentViewGroupId(R.id.native_ad_star_rating)
    .build()

星级评分

只有当网络提供的评分不低于 3.0 时,CloudX 才会填充星级评分容器;否则容器保持为空。请确保布局在星级评分容器为空时能够收起或隐藏。

2. 创建加载器

class YourActivity : AppCompatActivity(), CloudXNativeAdListener, CloudXAdRevenueListener {
    private lateinit var nativeAdLoader: CloudXNativeAdLoader

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        nativeAdLoader = CloudX.createNativeAdLoader(this, "your-native-ad-unit-id")
        nativeAdLoader.nativeAdListener = this
        nativeAdLoader.revenueListener = this
    }

    override fun onDestroy() {
        super.onDestroy()
        nativeAdLoader.destroy()
    }
}

加载广告

请选择一种加载流程。

加载到预构建视图

目标布局已经存在时使用此流程。CloudX 会先填充并注册视图,然后通过 onNativeAdLoaded 返回该视图。

val adView = CloudXNativeAdView(this, binder)
nativeAdLoader.loadAd(adView)

分别加载和渲染

如果希望在目标视图创建前预先加载广告,请使用延迟渲染。在将视图添加到视图层级之前调用 render(...)

nativeAdLoader.loadAd()

override fun onNativeAdLoaded(adView: CloudXNativeAdView?, ad: CloudXAd) {
    val newAdView = CloudXNativeAdView(this@YourActivity, binder)
    nativeAdLoader.render(newAdView, ad)
    container.addView(newAdView)
}

处理回调

已加载的原生广告会在加载后一小时过期;届时会触发 onNativeAdExpired,您可以销毁过期广告并加载新广告。在 onNativeAdLoadFailed 中,请避免立即循环重试——应延迟一段时间或在下一个自然展示时机重试。

// 必选回调

override fun onNativeAdLoaded(adView: CloudXNativeAdView?, ad: CloudXAd) {
    Log.d("CloudX", "Native ad loaded from ${ad.networkName}")

    ad.nativeAd?.let { nativeAd ->
        if (nativeAd.isVideoContent) {
            Log.d("CloudX", "Video duration: ${nativeAd.videoDuration}s")
        }
    }

    adView?.let { container.addView(it) }
}

override fun onNativeAdLoadFailed(adUnitId: String, error: CloudXError) {
    Log.e("CloudX", "Native ad failed to load: ${error.message}")
}

override fun onNativeAdClicked(ad: CloudXAd) {
    Log.d("CloudX", "Native ad clicked")
}

// 可选回调(默认空实现)

override fun onNativeAdExpired(ad: CloudXAd) {
    Log.d("CloudX", "Native ad expired — destroy and reload")
    nativeAdLoader.destroy(ad)
    nativeAdLoader.loadAd()
}

override fun onNativeAdClosed(ad: CloudXAd) {
    Log.d("CloudX", "User dismissed the ad via AdChoices")
    nativeAdLoader.destroy(ad)
}

// 收入回调

override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
    Log.d("CloudX", "Native ad revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}

3. 销毁原生广告

广告被替换或过期时销毁单个广告;所属页面或组件结束时销毁加载器。这样可以释放网络媒体视图,防止资源随时间不断累积。

// 销毁特定已加载的广告
nativeAdLoader.destroy(ad)

// 销毁加载器及所有关联资源
nativeAdLoader.destroy()

原生广告素材

CloudXNativeAd 接口可通过监听回调中的 ad.nativeAd 获取:

属性类型描述
titleString?标题文本
bodyString?正文/描述文本
callToActionString?CTA 按钮文本(例如 “Install Now”)
advertiserString?广告主名称
iconCloudXNativeAdImage?应用图标(DrawableUri
mainImageCloudXNativeAdImage?主图片(静态素材)
mediaViewView?视频/媒体播放器视图(适配器提供)
optionsViewView?AdChoices 或选项视图(适配器提供)
mediaContentAspectRatioFloat媒体内容的宽高比
starRatingDouble?应用商店评分(0–5)
isVideoContentBoolean素材是否为视频
videoDurationDouble视频时长(秒),未知时为 0.0
isExpiredBoolean广告是否已过期

不同网络和素材返回的资源可能不同。请将可空值视为可选值,并在素材不可用时隐藏对应 UI。mediaContentAspectRatiovideoDuration0 表示网络尚未提供可用值。

原生视频元数据

使用 isVideoContent 区分视频和静态原生素材。当其值为 true 时,如果网络已提供时长,videoDuration 会返回以秒为单位的视频时长。渲染完成后查询时长可获得最准确的值。