Skip to content

Issue in Native Ad Flutter using google_mobile_sdk

I want to monetise my Flutter app using google_mobile_ads library with Native ads. I am facing some issues while facing this documentation – https://developers.google.com/admob/flutter/native I am not sure where to put the my_native_ad.xml file so that it can be referred by the Kotlin Main Activity File.

Also, in the MainActivity file, I am facing some errors :-

  1. e: /Users/yash/AndroidStudioProjects/VideoPlayer/android/app/src/main/kotlin/dev/jideguru/filex/MainActivity.kt: (26, 5): ‘cleanUpFlutterEngine’ overrides nothing
  2. e: /Users/yash/AndroidStudioProjects/VideoPlayer/android/app/src/main/kotlin/dev/jideguru/filex/MainActivity.kt: (46, 113): No value passed for parameter ‘layoutInflater’
  3. e: /Users/yash/AndroidStudioProjects/VideoPlayer/android/app/src/main/kotlin/dev/jideguru/filex/MainActivity.kt: (83, 54): Unresolved reference: my_native_ad e: /Users/yash/AndroidStudioProjects/VideoPlayer/android/app/src/main/kotlin/dev/jideguru/filex/NativeAdFactoryExample.kt: (14, 58): Unresolved reference: R
  4. e:/Users/yash/AndroidStudioProjects/VideoPlayer/android/app/src/main/kotlin/dev/jideguru/filex/NativeAdFactoryExample.kt: (14, 58): Unresolved reference: R

Here is my MainActivity.kotlin file

import android.os.Build
import android.os.Environment
import android.os.StatFs
import android.util.Log
import androidx.annotation.NonNull
import androidx.annotation.RequiresApi
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import androidx.core.content.ContextCompat.*
import java.io.File
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import com.google.android.gms.ads.formats.UnifiedNativeAd
import com.google.android.gms.ads.formats.UnifiedNativeAdView
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin.NativeAdFactory

class MainActivity: FlutterActivity() {

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine?) {
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "adFactoryExample")
    }

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {

        flutterEngine.getPlugins().add(GoogleMobileAdsPlugin())
        super.configureFlutterEngine(flutterEngine)
        GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "adFactoryExample", NativeAdFactoryExample())
    }

}

internal class NativeAdFactoryExample(private val layoutInflater: LayoutInflater) : NativeAdFactory {
    override fun createNativeAd(
            nativeAd: UnifiedNativeAd, customOptions: Map<String, Any>?): UnifiedNativeAdView {
        val adView = layoutInflater.inflate(R.layout.my_native_ad, null) as UnifiedNativeAdView
        val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
        val bodyView = adView.findViewById<TextView>(R.id.ad_body)
        headlineView.text = nativeAd.headline
        bodyView.text = nativeAd.body
        adView.setBackgroundColor(Color.YELLOW)
        adView.setNativeAd(nativeAd)
        adView.bodyView = bodyView
        adView.headlineView = headlineView
        return adView
    }
}

Please let me know if any other details are required.

Answer

For those who are stuck on the same issue :-

list_tile_native_ad.xml :-

<?xml version="1.0" encoding="utf-8"?>
  <com.google.android.gms.ads.formats.UnifiedNativeAdView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_list_tile_native_ad_attribution_small"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#F19938"
        android:text="Ad"
        android:textColor="#FFFFFF"
        android:textSize="12sp" />

    <ImageView
        android:id="@+id/iv_list_tile_native_ad_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:scaleType="fitXY"
        tools:background="#EDEDED" />

    <TextView
        android:id="@+id/tv_list_tile_native_ad_attribution_large"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:background="#F19938"
        android:gravity="center"
        android:text="Ad"
        android:textColor="#FFFFFF"
        android:visibility="invisible" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="80dp"
        android:layout_marginLeft="80dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_list_tile_native_ad_headline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:maxLines="1"
            android:textColor="#000000"
            android:textSize="16sp"
            tools:text="Headline" />

        <TextView
            android:id="@+id/tv_list_tile_native_ad_body"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:maxLines="1"
            android:textColor="#828282"
            android:textSize="14sp"
            tools:text="body" />

    </LinearLayout>

</FrameLayout>

</com.google.android.gms.ads.formats.UnifiedNativeAdView>

MainActivity.kt :-

package com.customapp.videoplayer

import android.os.Build
import android.os.Environment
import android.os.StatFs
import android.util.Log
import androidx.annotation.NonNull
import androidx.annotation.RequiresApi
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import androidx.core.content.ContextCompat.*
import android.content.Context
import java.io.File
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import android.widget.ImageView
import com.google.android.gms.ads.formats.UnifiedNativeAd
import com.google.android.gms.ads.formats.UnifiedNativeAdView
import com.google.android.gms.ads.formats.NativeAd
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin.NativeAdFactory

class MainActivity: FlutterActivity() {

    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        val factory: NativeAdFactory = NativeAdFactoryExample(layoutInflater)
        GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "adFactoryExample", factory)
    }

}

internal class NativeAdFactoryExample(private val layoutInflater: LayoutInflater) : NativeAdFactory {
    override fun createNativeAd(
            nativeAd: UnifiedNativeAd, customOptions: Map<String, Any>?): UnifiedNativeAdView {
        val adView = layoutInflater.inflate(R.layout.list_tile_native_ad, null) as UnifiedNativeAdView
//        val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
//        val bodyView = adView.findViewById<TextView>(R.id.ad_body)
//        headlineView.text = nativeAd.headline
//        bodyView.text = nativeAd.body

        adView.setNativeAd(nativeAd)

        val attributionViewSmall: TextView = adView
                .findViewById(R.id.tv_list_tile_native_ad_attribution_small)
        val attributionViewLarge: TextView = adView
                .findViewById(R.id.tv_list_tile_native_ad_attribution_large)

        val iconView: ImageView = adView.findViewById(R.id.iv_list_tile_native_ad_icon)
        val icon: NativeAd.Image = nativeAd.getIcon()
        if (icon != null) {
            attributionViewSmall.setVisibility(View.VISIBLE)
            attributionViewLarge.setVisibility(View.INVISIBLE)
            iconView.setImageDrawable(icon.getDrawable())
        } else {
            attributionViewSmall.setVisibility(View.INVISIBLE)
            attributionViewLarge.setVisibility(View.VISIBLE)
        }
        adView.setIconView(iconView)

        val headlineView: TextView = adView.findViewById(R.id.tv_list_tile_native_ad_headline)
        headlineView.setText(nativeAd.getHeadline())
        adView.setHeadlineView(headlineView)

        val bodyView: TextView = adView.findViewById(R.id.tv_list_tile_native_ad_body)
        bodyView.setText(nativeAd.getBody())
        bodyView.setVisibility(if (nativeAd.getBody() != null) View.VISIBLE else View.INVISIBLE)
        adView.setBodyView(bodyView)

        return adView
    }


}

Keep your list_tile_native_ad.xml inside android/app/src/main/res/layout

NOTE :- I couldn’t add a dispose method because it kept throwing me an error.

Cheers!!