Skip to content

Android Native Ad Integration

Overview

Native ads are customizable ad formats that seamlessly blend with the application interface, with the following characteristics:

  • Highly customizable appearance
  • Natural integration with application content
  • Better user experience
  • Higher click-through and conversion rates

Integration Steps

Refer to the NativeAdHelper in the demo example

1. Initialize Native Ad

Initialize native ads in Activity or Fragment:

kotlin
/**
 * Native ad helper class
 * 
 * Responsible for native ad loading, display, and lifecycle management
 * Supports both template feed and self-rendering feed display methods
 * 
 * @param activity Context Activity
 * @param logger Log printing tool
 */
class NativeAdHelper(private val activity: Activity, private val logger: PrintLogger) {

    /**
     * Native ad object
     * 
     * Used to manage native ad loading, display, and destruction
     */
    private var nativeAdObject: NativeAdObject? = null

    /**
     * Load native ad
     * 
     * This method creates ad configuration, initializes native ad object, sets ad listener
     * Finally calls load() method to start loading ads
     */
    fun load() {
        // Create ad configuration object, set placement ID and ad size
        val adConfig = UjuAdConfig(
            placementId = DemoConfig.getNativePlacementId(), // Native ad placement ID
            adViewSize = AdViewSize(width = 320, height = 100) // Ad size: 320x100
        )
        
        // Initialize native ad object
        nativeAdObject = NativeAdObject(activity, adConfig)
        
        // Set ad listener to monitor various ad events
        nativeAdObject?.setAdObjectListener(object : FeedAdObjectListener {
            /**
             * Ad loaded successfully callback
             * 
             * @param placementId Ad placement ID
             */
            override fun onLoadSuccess(placementId: String) {
                // Ad loaded successfully, can be displayed now, recommended to check isReady before display
                logger.add("Native: onLoadSuccess")
            }

            /**
             * Ad loading failed callback
             * 
             * @param error Error information
             * @param placementId Ad placement ID
             */
            override fun onLoadError(
                error: UjuException,
                placementId: String
            ) {
                // Record loading error information
                logger.add("Native: onLoadError")
                DemoLogUtils.d("Native: onLoadError")
            }

            /**
             * Ad display error callback
             * 
             * @param error Error information
             * @param placementId Ad placement ID
             */
            override fun onAdError(
                error: UjuException,
                placementId: String
            ) {
                // Record ad error information, including error message and error code
                logger.add("Native: onAdError:message:${error.message}, code:${error.code}")
                DemoLogUtils.e("Native: onAdError:message:${error.message}, code:${error.code}")
            }

            /**
             * Ad displayed successfully callback
             */
            override fun onAdShow() {
                // Get ad information, record ecpm value
                val adInfo = nativeAdObject?.getAdInfo()
                logger.add("Native: onAdShow: ecpm:${adInfo?.ecpm}")
                DemoLogUtils.d("Native: onAdShow: ecpm:${adInfo?.ecpm}")
            }

            /**
             * Ad clicked callback
             */
            override fun onAdClicked() {
                // Record ad click event
                logger.add("Native: onAdClicked")
            }

            /**
             * Ad closed callback
             */
            override fun onAdClosed() {
                // Record ad close event
                logger.add("Native: onAdClosed")
            }

            /**
             * Ad landing page closed callback
             */
            override fun onLpClosed() {
                // Record landing page close event
                logger.add("Native: onLpClosed")
            }

        })
        
        // Start loading ad
        nativeAdObject?.load()
        // Record ad loading event
        logger.add("Native: load, placementId:${adConfig.placementId}")
        DemoLogUtils.d("Native: load, placementId:${adConfig.placementId}")
    }

    /**
     * Display native ad
     * 
     * Uses different display methods based on ad type (template feed or self-rendering feed)
     * Template feed: Directly call show() method to display
     * Self-rendering feed: Custom layout, populate data and bind interactions
     * 
     * @param viewGroup ViewGroup for containing the ad
     */
    fun show(viewGroup: ViewGroup) {
        // Check if ad object is created
        val adObject = nativeAdObject ?: run {
            logger.add("Native: Please load ad first")
            return
        }

        // Check if ad is ready
        if (adObject.isReady()) {
            // Determine ad type: template feed or self-rendering feed
            if (adObject.getFeedType() == FeedType.EXPRESS) {
                // Template feed: Directly call show() method to display
                adObject.show(activity, viewGroup)
            } else {
                // Self-rendering feed: Custom layout, populate data and bind interactions
                
                // Get material data
                val data = adObject.getAdData()
                if (data == null) {
                    // Material data is empty, prompt user
                    Toast.makeText(activity, "Missing material data", Toast.LENGTH_SHORT).show()
                    return
                }

                // Load custom ad layout
                val adView = activity.layoutInflater.inflate(R.layout.banner_feed_ad_view_layout, null)
                
                // Populate ad data
                adView.findViewById<TextView>(R.id.tvADTitle).text = data.title // Ad title
                adView.findViewById<TextView>(R.id.tvADDesc).text = data.desc // Ad description
                adView.findViewById<TextView>(R.id.tvADSource).text = data.source // Ad source
                adView.findViewById<TextView>(R.id.btnADCreative).text = data.callToAction // Call to action button

                // Get image views
                val ivAdPic = adView.findViewById<ImageView>(R.id.ivADPic) // Ad large image
                val ivAdSmall = adView.findViewById<ImageView>(R.id.ivADSmall) // Advertiser icon

                // Determine ad image URL
                var imageUrl = ""
                if (data.imageUrl != null) {
                    imageUrl = data.imageUrl.toString() // Use single image URL
                } else if (!data.imageUrlList.isNullOrEmpty()) {
                    imageUrl = data.imageUrlList?.get(0) ?: "" // Use first image in image list
                }

                // Load ad image
                Glide.with(activity).load(imageUrl).into(ivAdPic)

                // Load advertiser icon
                Glide.with(activity).load(data.iconUrl).into(ivAdSmall)

                // Create ad view binder for binding ad data and views
                val binder = NativeAdViewBinder(
                    titleId = R.id.tvADTitle, // Title view ID
                    descId = R.id.tvADDesc, // Description view ID
                    sourceId = R.id.tvADSource, // Source view ID
                    imageId = R.id.ivADPic, // Image view ID
                    imageViews = listOf(ivAdPic), // Image view list
                    mediaViewId = R.id.flVideo, // Media view ID (for video ads)
                    iconId = R.id.ivADSmall, // Icon view ID
                    callToActionId = R.id.btnADCreative, // Call to action button ID
                    logoLayoutId = R.id.flADLogo // Ad logo layout ID
                )

                // Bind click response to make ad clickable
                adObject.registerViewForInteraction(
                    activity, // Context Activity
                    adView, // Ad view
                    viewGroup, // Container view
                    binder // View binder
                )
            }
        } else {
            // Ad is not ready, record log
            logger.add("Native: Ad not ready yet")
        }
    }

    /**
     * Check if ad is loaded
     * 
     * @return true if ad object is created, false otherwise
     * Note: This method only checks if ad object exists, does not guarantee ad is ready
     * To check if ad can be displayed, use isReady() method
     */
    fun isLoaded(): Boolean {
        return nativeAdObject != null
    }

    /**
     * Destroy ad object
     * 
     * When ad is no longer needed, call this method to destroy ad object and release resources
     */
    fun destroy() {
        // Destroy ad object
        nativeAdObject?.destroy()
        // Set ad object reference to null
        nativeAdObject = null
    }
}

Best Practices

1. Ad Layout Design

  • Consistent with app style: Use the same design language as the application
  • Clear ad identification: Ensure users can recognize this is an ad
  • Reasonable information hierarchy: Title, description, brand information clearly visible
  • Responsive design: Adapt to different screen sizes

2. Optimization Suggestions

  • Preload ads: Load ads in advance before they need to be displayed
  • Cache mechanism: Implement ad caching to improve display speed
  • Alternating layouts: Create multiple layouts for different ads
  • Performance optimization: Avoid over-rendering and memory leaks

3. Avoidable Issues

  • Don't hide ad identification
  • Don't modify ad content
  • Don't interfere with normal ad display
  • Don't add irrelevant content to ads

Common Questions

Q: Why isn't the native ad displaying?

A: Possible reasons:

  • Incorrect ad unit ID
  • Network connection issues
  • Insufficient ad inventory
  • Layout issues (container is invisible or size is 0)
  • Rendering code issues

Q: How to improve native ad effectiveness?

A: Recommendations:

  • Carefully design ad layouts
  • Ensure ads are relevant to application content
  • Optimize ad loading and rendering
  • Test different ad placements
  • Analyze ad performance data

Q: Can native ads be used in RecyclerView?

A: Yes, implementation method:

  • Manage native ads in ViewHolder
  • Create dedicated layouts for ad items
  • Correctly handle ad loading and rendering
  • Avoid frequent creation and destruction of ads