Integrate AdMob Native Ads in Flutter

Create a blank flutter project:

flutter create native_ads_flutter

Add provider package: 

flutter pub add google_mobile_ads

AdMob app ID

Add the Highlighted lines to the AndroidManifest.xml file with your own AdMob app ID.

android/app/src/main/AndroidManifest.xml

<manifest>
    ...
    <application>
       ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/>
    </application>

</manifest>

Change "minSdkVersion 19" and "multiDexEnabled true"

android/app/build.gradle
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.native_ads_flutter"
minSdkVersion 19
multiDexEnabled true
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
Native ad layout template.
android/app/src/main/res/layout/list_tile_native_ad.xml:

<com.google.android.gms.ads.nativead.NativeAdView
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" />





ListTileNativeAdFactory class for list_tile_native_ad template.
android/app/src/main/kotlin/com/example/native_ads_flutter/ListTileNativeAdFactory.kt:
package com.example.native_ads_flutter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin

class ListTileNativeAdFactory(val context: Context) : GoogleMobileAdsPlugin.NativeAdFactory {

override fun createNativeAd(
nativeAd: NativeAd,
customOptions: MutableMap<String, Any>?
): NativeAdView {
val nativeAdView = LayoutInflater.from(context)
.inflate(R.layout.list_tile_native_ad, null) as NativeAdView

with(nativeAdView) {
val attributionViewSmall =
findViewById(R.id.tv_list_tile_native_ad_attribution_small)
val attributionViewLarge =
findViewById(R.id.tv_list_tile_native_ad_attribution_large)

val iconView = findViewById(R.id.iv_list_tile_native_ad_icon)
val icon = nativeAd.icon
if (icon != null) {
attributionViewSmall.visibility = View.VISIBLE
attributionViewLarge.visibility = View.INVISIBLE
iconView.setImageDrawable(icon.drawable)
} else {
attributionViewSmall.visibility = View.INVISIBLE
attributionViewLarge.visibility = View.VISIBLE
}
this.iconView = iconView

val headlineView = findViewById(R.id.tv_list_tile_native_ad_headline)
headlineView.text = nativeAd.headline
this.headlineView = headlineView

val bodyView = findViewById(R.id.tv_list_tile_native_ad_body)
with(bodyView) {
text = nativeAd.body
visibility = if (nativeAd.body.isNotEmpty()) View.VISIBLE else View.INVISIBLE
}
this.bodyView = bodyView

setNativeAd(nativeAd)
}

return nativeAdView
}
}
MainActivity for(Kotlin)
ListTileNativeAdFactory should be registered to the GoogleMobileAdsPlugin
if your flutter app project using kotlin then use these code.
android/app/src/main/kotlin/com/example/native_ads_flutter/MainActivity.kt:
package com.example.native_ads_flutter

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin

//This is the final version of kotlin main activity
class MainActivity: FlutterActivity() {

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)

GoogleMobileAdsPlugin.registerNativeAdFactory(
flutterEngine, "listTile", ListTileNativeAdFactory(context))
}

override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
super.cleanUpFlutterEngine(flutterEngine)
GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile")
}

}

Here is our main.dart file and our UI.
lib/main.dart:
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
runApp(const MaterialApp(
home: NativeAdExample(),
));
}


///An App to demonstrate how to use admob native ads in flutter
///make sure to change the value of APPLICATION_ID in android manifest
///make sure to use a real ad unit id from admob and change it below

class NativeAdExample extends StatefulWidget {
const NativeAdExample({Key? key}) : super(key: key);

@override
_NativeAdExampleState createState() => _NativeAdExampleState();
}

class _NativeAdExampleState extends State {

late NativeAd _ad;
bool isLoaded = false;

@override
void initState() {
super.initState();
loadNativeAd();
}

///Important make sure to dispose the ad when disposing the screen
@override
void dispose() {
_ad.dispose();
super.dispose();
}


void loadNativeAd() {
_ad = NativeAd(
request: const AdRequest(),
///This is a test adUnitId make sure to change it
adUnitId: 'ca-app-pub-3940256099942544/2247696110',
factoryId: 'listTile',
listener: NativeAdListener(
onAdLoaded: (ad){
setState(() {
isLoaded = true;
});
},
onAdFailedToLoad: (ad, error){
ad.dispose();
print('failed to load the ad ${error.message}, ${error.code}');
}
)
);

_ad.load();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Native Ad'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(12.0),
child: ListView.builder(
itemCount: 5,
itemBuilder: (context, index){
if(isLoaded && index == 2){
return Container(
child: AdWidget(ad: _ad,),
alignment: Alignment.center,
height: 170,
color: Colors.black12,
);
}else{
return ListTile(
title: Text('Item ${index + 1}'),
leading: const FlutterLogo(size: 25,),
subtitle: Text('Sub Title for item ${index + 1}'),
);
}

}
),
),
);
}
}

Video Demo and Source Code

 

Source Code