Skip to main content

Overview

Native ads are an ad format that allows you to freely customize the ad UI to match your app’s design. You can provide a natural user experience by individually placing elements such as ad creatives (images, videos), headline, body, and CTA buttons.

Key Features

  • Complete UI Customization: Freely configure ad layout to match your app’s design system
  • Various Media Support: Image and video ad creative support
  • Flexible Click Area Settings: Full click or individual element click handling
  • Profile Information Display: Advertiser profile logo, name, and link support

Classes and Interfaces

AdropNativeAd

Main class for loading and managing native ads.
unitId
String
required
Ad unit ID (issued from console)
contextId
String
ID for context targeting (optional)
listener
AdropNativeAdListener
Listener to handle ad events
useCustomClick
Boolean
default:"false"
Whether to use custom click handling

Key Properties

PropertyTypeDescription
headlineStringAd headline
bodyStringAd body text
iconStringIcon image URL
coverStringCover image URL
advertiserStringAdvertiser name
callToActionStringCall-to-action text (e.g., “Learn More”)
profileAdropNativeAdProfileAdvertiser profile information
isLoadedBooleanWhether ad loading is complete
isDestroyedBooleanWhether ad is destroyed

AdropNativeAdView

Container view for displaying native ads.
isEntireClick
Boolean
default:"false"
Whether to enable entire area click. When set to true, click events occur on the entire ad view area.

Key Methods

MethodDescription
setIconView(view, listener)Set icon image view (ImageView type)
setHeadLineView(view, listener)Set headline text view (TextView type)
setBodyView(view)Set body text view (TextView type)
setMediaView(view)Set media container view (AdropMediaView type)
setAdvertiserView(view, listener)Set advertiser text view (TextView type)
setCallToActionView(view)Set CTA button or text view
setProfileLogoView(view, listener)Set profile logo image view (ImageView type)
setProfileNameView(view, listener)Set profile name text view (TextView type)
setNativeAd(ad)Bind ad data to view
destroy()Release resources

AdropMediaView

Media container view for displaying ad images or videos.
<io.adrop.ads.nativeAd.AdropMediaView
    android:id="@+id/ad_media"
    android:layout_width="match_parent"
    android:layout_height="200dp" />

AdropNativeAdListener

Interface for handling ad events.
interface AdropNativeAdListener {
    fun onAdReceived(ad: AdropNativeAd)
    fun onAdClick(ad: AdropNativeAd)
    fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode)
    fun onAdImpression(ad: AdropNativeAd) // Optional implementation
}

AdropNativeAdProfile

Data class containing advertiser profile information.
PropertyTypeDescription
displayLogoStringProfile logo image URL
displayNameStringProfile display name
linkStringProfile link URL

Implementation Guide

1. XML Layout Setup

Define the layout to display native ads. Use AdropNativeAdView as the root and place ad elements inside.
res/layout/native_ad_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<io.adrop.ads.nativeAd.AdropNativeAdView
    android:id="@+id/native_ad_view"
    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="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">

        <!-- Profile area -->
        <ImageView
            android:id="@+id/ad_profile_logo"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:scaleType="centerCrop"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/ad_profile_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:textSize="16sp"
            android:textStyle="bold"
            app:layout_constraintStart_toEndOf="@id/ad_profile_logo"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/ad_badge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="4dp"
            android:text="Ad"
            android:textSize="12sp"
            app:layout_constraintStart_toEndOf="@id/ad_profile_logo"
            app:layout_constraintTop_toBottomOf="@id/ad_profile_name" />

        <!-- Media area -->
        <io.adrop.ads.nativeAd.AdropMediaView
            android:id="@+id/ad_media"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:layout_marginTop="12dp"
            app:layout_constraintTop_toBottomOf="@id/ad_profile_logo" />

        <!-- Ad content -->
        <TextView
            android:id="@+id/ad_headline"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:textSize="18sp"
            android:textStyle="bold"
            app:layout_constraintTop_toBottomOf="@id/ad_media" />

        <TextView
            android:id="@+id/ad_body"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:textSize="14sp"
            app:layout_constraintTop_toBottomOf="@id/ad_headline" />

        <!-- Bottom area -->
        <TextView
            android:id="@+id/ad_advertiser"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:textSize="14sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/ad_body" />

        <Button
            android:id="@+id/ad_call_to_action"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/ad_body" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</io.adrop.ads.nativeAd.AdropNativeAdView>

2. Load and Display Ad (Kotlin)

import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import io.adrop.ads.model.AdropErrorCode
import io.adrop.ads.nativeAd.AdropMediaView
import io.adrop.ads.nativeAd.AdropNativeAd
import io.adrop.ads.nativeAd.AdropNativeAdListener
import io.adrop.ads.nativeAd.AdropNativeAdView

class NativeAdActivity : AppCompatActivity() {

    private lateinit var nativeAd: AdropNativeAd
    private lateinit var nativeAdView: AdropNativeAdView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_native_ad)

        nativeAdView = findViewById(R.id.native_ad_view)
        loadNativeAd()
    }

    private fun loadNativeAd() {
        // 1. Create native ad instance
        nativeAd = AdropNativeAd(
            context = this,
            unitId = "YOUR_UNIT_ID"  // Replace with actual unit ID
        )

        // 2. Set listener
        nativeAd.listener = object : AdropNativeAdListener {
            override fun onAdReceived(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad received successfully")
                populateNativeAdView(ad)
            }

            override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
                Log.e("Adrop", "Ad failed to receive: $errorCode")
            }

            override fun onAdClick(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad clicked")
            }

            override fun onAdImpression(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad impression")
            }
        }

        // 3. Load ad
        nativeAd.load()
    }

    private fun populateNativeAdView(ad: AdropNativeAd) {
        // Set profile
        val profileLogoView = findViewById<ImageView>(R.id.ad_profile_logo)
        Glide.with(this).load(ad.profile.displayLogo).into(profileLogoView)
        nativeAdView.setProfileLogoView(profileLogoView)

        val profileNameView = findViewById<TextView>(R.id.ad_profile_name)
        profileNameView.text = ad.profile.displayName
        nativeAdView.setProfileNameView(profileNameView)

        // Set headline
        val headlineView = findViewById<TextView>(R.id.ad_headline)
        headlineView.text = ad.headline
        nativeAdView.setHeadLineView(headlineView)

        // Set media
        val mediaView = findViewById<AdropMediaView>(R.id.ad_media)
        nativeAdView.setMediaView(mediaView)

        // Set body
        val bodyView = findViewById<TextView>(R.id.ad_body)
        bodyView.text = ad.body
        nativeAdView.setBodyView(bodyView)

        // Set advertiser
        val advertiserView = findViewById<TextView>(R.id.ad_advertiser)
        advertiserView.text = ad.advertiser
        nativeAdView.setAdvertiserView(advertiserView)

        // Set CTA button
        val ctaView = findViewById<Button>(R.id.ad_call_to_action)
        ctaView.text = ad.callToAction
        nativeAdView.setCallToActionView(ctaView)

        // Bind ad data
        nativeAdView.setNativeAd(ad)
    }

    override fun onDestroy() {
        // Release resources
        nativeAdView.destroy()
        nativeAd.destroy()
        super.onDestroy()
    }
}

3. Load and Display Ad (Java)

Java
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import io.adrop.ads.model.AdropErrorCode;
import io.adrop.ads.nativeAd.AdropMediaView;
import io.adrop.ads.nativeAd.AdropNativeAd;
import io.adrop.ads.nativeAd.AdropNativeAdListener;
import io.adrop.ads.nativeAd.AdropNativeAdView;

public class NativeAdActivity extends AppCompatActivity {

    private AdropNativeAd nativeAd;
    private AdropNativeAdView nativeAdView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_native_ad);

        nativeAdView = findViewById(R.id.native_ad_view);
        loadNativeAd();
    }

    private void loadNativeAd() {
        // 1. Create native ad instance
        nativeAd = new AdropNativeAd(
            this,
            "YOUR_UNIT_ID",  // Replace with actual unit ID
            null  // contextId (optional)
        );

        // 2. Set listener
        nativeAd.setListener(new AdropNativeAdListener() {
            @Override
            public void onAdReceived(AdropNativeAd ad) {
                Log.d("Adrop", "Ad received successfully");
                populateNativeAdView(ad);
            }

            @Override
            public void onAdFailedToReceive(AdropNativeAd ad, AdropErrorCode errorCode) {
                Log.e("Adrop", "Ad failed to receive: " + errorCode);
            }

            @Override
            public void onAdClick(AdropNativeAd ad) {
                Log.d("Adrop", "Ad clicked");
            }

            @Override
            public void onAdImpression(AdropNativeAd ad) {
                Log.d("Adrop", "Ad impression");
            }
        });

        // 3. Load ad
        nativeAd.load();
    }

    private void populateNativeAdView(AdropNativeAd ad) {
        // Set profile logo
        ImageView profileLogoView = findViewById(R.id.ad_profile_logo);
        Glide.with(this).load(ad.getProfile().getDisplayLogo()).into(profileLogoView);
        nativeAdView.setProfileLogoView(profileLogoView, null);

        // Set profile name
        TextView profileNameView = findViewById(R.id.ad_profile_name);
        profileNameView.setText(ad.getProfile().getDisplayName());
        nativeAdView.setProfileNameView(profileNameView, null);

        // Set headline
        TextView headlineView = findViewById(R.id.ad_headline);
        headlineView.setText(ad.getHeadline());
        nativeAdView.setHeadLineView(headlineView, null);

        // Set media
        AdropMediaView mediaView = findViewById(R.id.ad_media);
        nativeAdView.setMediaView(mediaView);

        // Set body
        TextView bodyView = findViewById(R.id.ad_body);
        bodyView.setText(ad.getBody());
        nativeAdView.setBodyView(bodyView);

        // Set advertiser
        TextView advertiserView = findViewById(R.id.ad_advertiser);
        advertiserView.setText(ad.getAdvertiser());
        nativeAdView.setAdvertiserView(advertiserView, null);

        // Set CTA button
        Button ctaView = findViewById(R.id.ad_call_to_action);
        ctaView.setText(ad.getCallToAction());
        nativeAdView.setCallToActionView(ctaView);

        // Bind ad data
        nativeAdView.setNativeAd(ad);
    }

    @Override
    protected void onDestroy() {
        // Release resources
        if (nativeAdView != null) {
            nativeAdView.destroy();
        }
        if (nativeAd != null) {
            nativeAd.destroy();
        }
        super.onDestroy();
    }
}

Advanced Features

Entire Click Area Setting

You can set the entire ad view area to trigger click events.
nativeAdView.isEntireClick = true
When isEntireClick is set to true, the entire ad view becomes a clickable area. Individual element click listeners will not work.

Individual Element Click Listeners

You can set custom click listeners on specific ad elements.
// Custom action on advertiser click
nativeAdView.setAdvertiserView(advertiserView) {
    Log.d("Adrop", "Advertiser clicked")
    // Implement custom action
}

// Custom action on profile logo click
nativeAdView.setProfileLogoView(profileLogoView) {
    Log.d("Adrop", "Profile logo clicked")
    // Implement custom action
}

Context Targeting

You can request ads matching a specific context.
val nativeAd = AdropNativeAd(
    context = this,
    unitId = "YOUR_UNIT_ID",
    contextId = "SPORTS_NEWS"  // Context ID
)

Using in RecyclerView

You can display native ads as items in a RecyclerView.
RecyclerView Adapter
class ContentAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        const val VIEW_TYPE_CONTENT = 0
        const val VIEW_TYPE_AD = 1
        const val AD_INTERVAL = 5  // Show ad every 5 items
    }

    private val items = mutableListOf<Any>()
    private val nativeAds = mutableMapOf<Int, AdropNativeAd>()

    override fun getItemViewType(position: Int): Int {
        return if (position % (AD_INTERVAL + 1) == AD_INTERVAL) {
            VIEW_TYPE_AD
        } else {
            VIEW_TYPE_CONTENT
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            VIEW_TYPE_AD -> {
                val view = LayoutInflater.from(parent.context)
                    .inflate(R.layout.item_native_ad, parent, false)
                NativeAdViewHolder(view)
            }
            else -> {
                val view = LayoutInflater.from(parent.context)
                    .inflate(R.layout.item_content, parent, false)
                ContentViewHolder(view)
            }
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is NativeAdViewHolder -> loadNativeAd(holder, position)
            is ContentViewHolder -> holder.bind(items[position])
        }
    }

    private fun loadNativeAd(holder: NativeAdViewHolder, position: Int) {
        // Reuse already loaded ad
        nativeAds[position]?.let { ad ->
            if (ad.isLoaded) {
                holder.bind(ad)
                return
            }
        }

        // Load new ad
        val nativeAd = AdropNativeAd(holder.itemView.context, "YOUR_UNIT_ID")
        nativeAd.listener = object : AdropNativeAdListener {
            override fun onAdReceived(ad: AdropNativeAd) {
                nativeAds[position] = ad
                holder.bind(ad)
            }

            override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
                Log.e("Adrop", "Ad load failed: $errorCode")
            }

            override fun onAdClick(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad clicked")
            }
        }
        nativeAd.load()
    }

    class NativeAdViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val nativeAdView: AdropNativeAdView = itemView.findViewById(R.id.native_ad_view)

        fun bind(ad: AdropNativeAd) {
            val profileLogo = itemView.findViewById<ImageView>(R.id.ad_profile_logo)
            Glide.with(itemView.context).load(ad.profile.displayLogo).into(profileLogo)
            nativeAdView.setProfileLogoView(profileLogo)

            val profileName = itemView.findViewById<TextView>(R.id.ad_profile_name)
            profileName.text = ad.profile.displayName
            nativeAdView.setProfileNameView(profileName)

            val headline = itemView.findViewById<TextView>(R.id.ad_headline)
            headline.text = ad.headline
            nativeAdView.setHeadLineView(headline)

            val media = itemView.findViewById<AdropMediaView>(R.id.ad_media)
            nativeAdView.setMediaView(media)

            val body = itemView.findViewById<TextView>(R.id.ad_body)
            body.text = ad.body
            nativeAdView.setBodyView(body)

            val advertiser = itemView.findViewById<TextView>(R.id.ad_advertiser)
            advertiser.text = ad.advertiser
            nativeAdView.setAdvertiserView(advertiser)

            val cta = itemView.findViewById<Button>(R.id.ad_call_to_action)
            cta.text = ad.callToAction
            nativeAdView.setCallToActionView(cta)

            nativeAdView.setNativeAd(ad)
        }
    }

    fun destroy() {
        nativeAds.values.forEach { it.destroy() }
        nativeAds.clear()
    }
}

Test Unit IDs

Use the following test unit IDs during development and testing.
FormatTest Unit ID
Native (Image)PUBLIC_TEST_UNIT_ID_NATIVE
Native Video (16:9)PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_16_9
Native Video (9:16)PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_9_16
Be sure to replace with actual unit IDs before production deployment.

Lifecycle Management

Resource Release in Activity/Fragment

Native ads must be released when no longer in use to prevent memory leaks.
override fun onDestroy() {
    nativeAdView.destroy()
    nativeAd.destroy()
    super.onDestroy()
}

Resource Release in RecyclerView

When using ads in a RecyclerView Adapter, all ads must be released when the Activity or Fragment is destroyed.
override fun onDestroy() {
    adapter.destroy()
    super.onDestroy()
}

Best Practices

1. Display Only Required Elements

You don’t need to display all ad elements. Selectively use only the elements needed to match your app’s design.
// Minimal configuration example (media + CTA only)
nativeAdView.setMediaView(mediaView)
nativeAdView.setCallToActionView(ctaView)
nativeAdView.setNativeAd(ad)

2. Use Image Loading Libraries

Use image loading libraries like Glide or Coil when displaying icon, cover, and profile images.
// Glide example
Glide.with(context)
    .load(ad.icon)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .into(iconView)

3. Reuse Ad Views

When displaying ads in a RecyclerView, cache and reuse ad instances.

4. Appropriate Ad Placement

Place ads naturally without degrading user experience.
  • Content feed: 1 ad every 5-10 items
  • Detail screen: Place at bottom of content
  • Scroll view: Place to match natural content flow

5. Error Handling

Implement appropriate fallback handling for ad load failures.
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
    when (errorCode) {
        AdropErrorCode.ERROR_CODE_AD_NO_FILL -> {
            // No ad available - hide ad area
            nativeAdView.visibility = View.GONE
        }
        AdropErrorCode.ERROR_CODE_NETWORK -> {
            // Network error - retry logic
            Handler(Looper.getMainLooper()).postDelayed({
                nativeAd.load()
            }, 3000)
        }
        else -> {
            Log.e("Adrop", "Ad load failed: $errorCode")
        }
    }
}

Complete Example

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import io.adrop.ads.model.AdropErrorCode
import io.adrop.ads.nativeAd.AdropMediaView
import io.adrop.ads.nativeAd.AdropNativeAd
import io.adrop.ads.nativeAd.AdropNativeAdListener
import io.adrop.ads.nativeAd.AdropNativeAdView

class NativeAdExampleActivity : AppCompatActivity() {

    private lateinit var nativeAd: AdropNativeAd
    private lateinit var nativeAdView: AdropNativeAdView
    private lateinit var loadingView: View
    private lateinit var errorView: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_native_ad_example)

        nativeAdView = findViewById(R.id.native_ad_view)
        loadingView = findViewById(R.id.loading_view)
        errorView = findViewById(R.id.error_view)

        findViewById<Button>(R.id.retry_button).setOnClickListener {
            loadNativeAd()
        }

        loadNativeAd()
    }

    private fun loadNativeAd() {
        showLoading()

        nativeAd = AdropNativeAd(
            context = this,
            unitId = "PUBLIC_TEST_UNIT_ID_NATIVE"
        )

        nativeAd.listener = object : AdropNativeAdListener {
            override fun onAdReceived(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad received: unitId=${ad.unitId}, txId=${ad.txId}")
                populateNativeAdView(ad)
                showAd()
            }

            override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
                Log.e("Adrop", "Ad failed to receive: $errorCode")
                showError()
            }

            override fun onAdClick(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad clicked: txId=${ad.txId}")
            }

            override fun onAdImpression(ad: AdropNativeAd) {
                Log.d("Adrop", "Ad impression: txId=${ad.txId}")
            }
        }

        nativeAd.load()
    }

    private fun populateNativeAdView(ad: AdropNativeAd) {
        // Enable entire click area (optional)
        // nativeAdView.isEntireClick = true

        // Profile logo
        val profileLogoView = findViewById<ImageView>(R.id.ad_profile_logo)
        Glide.with(this)
            .load(ad.profile.displayLogo)
            .circleCrop()
            .into(profileLogoView)
        nativeAdView.setProfileLogoView(profileLogoView)

        // Profile name
        val profileNameView = findViewById<TextView>(R.id.ad_profile_name)
        profileNameView.text = ad.profile.displayName
        nativeAdView.setProfileNameView(profileNameView)

        // Headline
        val headlineView = findViewById<TextView>(R.id.ad_headline)
        headlineView.text = ad.headline
        nativeAdView.setHeadLineView(headlineView)

        // Media (image or video)
        val mediaView = findViewById<AdropMediaView>(R.id.ad_media)
        nativeAdView.setMediaView(mediaView)

        // Body
        val bodyView = findViewById<TextView>(R.id.ad_body)
        bodyView.text = ad.body
        nativeAdView.setBodyView(bodyView)

        // Advertiser
        val advertiserView = findViewById<TextView>(R.id.ad_advertiser)
        advertiserView.text = ad.advertiser
        nativeAdView.setAdvertiserView(advertiserView) {
            Log.d("Adrop", "Advertiser clicked: ${ad.advertiser}")
        }

        // CTA button
        val ctaView = findViewById<Button>(R.id.ad_call_to_action)
        ctaView.text = ad.callToAction
        nativeAdView.setCallToActionView(ctaView)

        // Bind ad data
        nativeAdView.setNativeAd(ad)
    }

    private fun showLoading() {
        loadingView.visibility = View.VISIBLE
        nativeAdView.visibility = View.GONE
        errorView.visibility = View.GONE
    }

    private fun showAd() {
        loadingView.visibility = View.GONE
        nativeAdView.visibility = View.VISIBLE
        errorView.visibility = View.GONE
    }

    private fun showError() {
        loadingView.visibility = View.GONE
        nativeAdView.visibility = View.GONE
        errorView.visibility = View.VISIBLE
    }

    override fun onDestroy() {
        nativeAdView.destroy()
        nativeAd.destroy()
        super.onDestroy()
    }
}

Next Steps