AdMob Native Advanced Ads SDK send the advertisement segments specifically to your application, and you render them in your local application code, conveying an awesome user experience.
Developer have freedom to display Native Advanced Ads in Application according to their Application theme, required Ad format.
Unlike old styled Admob Banner Ads you have to design XML layout files for Ads to be displayed in your application.
So you can fully customize Native Advanced Ads in terms of fonts, color, ad format, action buttons according to your Application theme due to which ads closely resemble a natural piece of the application.
Say you need an ad format which fits naturally with your application content with AdMob Native Ads you can design CSS templates (XML layout files in case of Android) specifically for better user experience of your app.
For example if you want to show text Ads in your application you can only display Ads in TextView
in Android and if you want to show only image ad you can show Ads in ImageView
or you can add native buttons to ads to be shown in your Android Application.
This means that when you request Advanced Native Ads from Admob you get object of type NativeAd
which contains assets for the Ad and than your application is responsible to display Ad in your desired format.
In above screen shot we are displaying Advanced Native Ads in RecyclerView feed in Android using Admob Native Ads Sdk.
- As of today 15 Dec 2017 you cannot create ad unit ids for Advanced Native Ads in Google AdMob because they are in beta version and only available to selected publishers.
- Must Read Comments in Code for bettter understanding.
- AdMob includes Firebase SDK and you can link AdMob with your Firebase account to take advantage of free unlimited Firebase analytics.
We will be using Kotlin Programming language in this Tutorial. if you are familiar with basic syntax of Kotlin than you can easily covert this into Java if you want to do so.
buildscript {
ext.kotlin_version = '1.1.3-2'
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.google.gms:google-services:3.0.0'
}
}
dependencies {
//Firebase Ads Dependency
compile 'com.google.firebase:firebase-ads:10.2.1'
}
// place this at the bottom of the file.
apply plugin: 'com.google.gms.google-services'
We need AdMob application ID and AdMob Ad Unit ID for initializing SDK for displaying Ads in our application.
Create these ID’s from AdMob admin console and place in your application for
First of all insert Admob Ad Id and ApplicationId in strings.xml
<string name="admob_app_id">ca-app-pub-3940256099942544~3347511713</string>
<string name="ad_unit_id">ca-app-pub-3940256099942544/8135179316</string>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/my_album_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:titleTextColor="@color/colorIcons" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rvAlbumSelected"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:clipToPadding="false" />
</android.support.design.widget.CoordinatorLayout>
// we will be showing total 5 ads in our RecyclerView.
val NUMBER_OF_ADS = 5
private val mRecyclerViewItems = ArrayList<Any>()
// once we load NativeAd from Admob.
// we will add NativeAd in ArrayList.
private val mNativeAds = ArrayList<NativeAd>()
// SingleAlbumAdapter class will be our RecyclerView Adapter.
var adapter: SingleAlbumAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_album)
// Initialize the Mobile Ads SDK.
MobileAds.initialize(this, getString(R.string.admob_app_id))
init_ui_views("camera", false)
}
For populating RecyclerView I am loading images from camera folder on device. and showing Ads along with images.
You can implement your adapter accordingly, You will have to change only ViewHolder class for your own adapter, rest of the code (Native Ads related code) is same.
private fun init_ui_views(folderName: String?, isVideo: Boolean?) {
val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE).override(160, 160).skipMemoryCache(true).error(R.drawable.ic_image_unavailable)
val glide = Glide.with(this)
val builder = glide.asBitmap()
rvAlbumSelected?.setHasFixedSize(true)
adapter = SingleAlbumAdapter(mRecyclerViewItems, getAllShownImagesPath(this, folderName, isVideo), this, options, builder, glide, this)
rvAlbumSelected?.adapter = adapter
// Note i am loading Ads after populating RecyclerView.
// After application loads Ads we will call notifydatasetChnaged()
// and ads will be displayed in RecylclerView.
loadNativeAd()
)
private fun getAllShownImagesPath(activity: Activity, folderName: String?, isVideo: Boolean?): MutableList<String> {
val uri: Uri
val cursorBucket: Cursor
val column_index_data: Int
val listOfAllImages = ArrayList<String>()
var absolutePathOfImage: String? = null
val selectionArgs = arrayOf("%" + folderName + "%")
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val selection = MediaStore.Images.Media.DATA + " like ? "
val projectionOnlyBucket = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
cursorBucket = activity.contentResolver.query(uri, projectionOnlyBucket, selection, selectionArgs, null)
column_index_data = cursorBucket.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
while (cursorBucket.moveToNext()) {
absolutePathOfImage = cursorBucket.getString(column_index_data)
if (absolutePathOfImage != "" && absolutePathOfImage != null) {
listOfAllImages.add(absolutePathOfImage)
mRecyclerViewItems.add(absolutePathOfImage)
}
}
return listOfAllImages.asReversed()
}
First time we will call loadNativeAd function with 0 value. Every time we get new NativeAd object from Admob we will increment this value and when we reach 5 we will update our RecyclerView Adapter and will display Ads in our RecyclerView.
private fun loadNativeAd() {
loadNativeAd(0)
}
There are two types of Ads format one is Content Ads and the other is Native App Install Ads.
In code below we are using AdBuilder class to load both types of Ads.
Native App Install Ads are represented by object of type NativeAppInstallAd and Content Ads are represented by NativeContentAd.
When their respective Ad type is loaded call back method is called and we can get our Native Ad assets from their objects.
Since I wanted to display Native Ad 5 times in RecyclerView so we will keep loading Ads until we reach 5.
And after that we will populate Ads in RecyclerView.
private fun loadNativeAd(adLoadCount: Int) {
if (adLoadCount >= NUMBER_OF_ADS) {
// This method will insert Ads in list
// which is used to populate RecyclerView items.
insertAdsInRecyclerViewItems()
// Here after 5 Native Ads are loaded we will display them in adapter.
// Find below source code of our RecyclerView Adapter.
rvAlbumSelected.adapter.notifyDataSetChanged()
return
}
val builder = AdLoader.Builder(this, getString(R.string.ad_unit_id))
val adLoader = builder.forAppInstallAd { ad ->
// An app install ad loaded successfully, call this method again to
// load the next ad.
mNativeAds.add(ad)
loadNativeAd(adLoadCount + 1)
}.forContentAd { ad ->
// A content ad loaded successfully, call this method again to
// load the next ad.
mNativeAds.add(ad)
loadNativeAd(adLoadCount + 1)
}.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(errorCode: Int) {
// A native ad failed to load. Call this method again to load
// the next ad in the items list.
Log.e("AlbumsActivity", "The previous native ad failed to load. Attempting to" + " load another.")
loadNativeAd(adLoadCount + 1)
}
}).build()
// Load the Native Express ad.
adLoader.loadAd(AdRequest.Builder().build())
}
private fun insertAdsInRecyclerViewItems() {
if (mNativeAds.size <= 0) {
return
}
val offset = mRecyclerViewItems.size / mNativeAds.size + 1
var index = 0
for (ad in mNativeAds) {
mRecyclerViewItems.add(index, ad)
index = index + offset
}
}
We are done with
Now we will
// add_content.xml
<com.google.android.gms.ads.formats.NativeContentAdView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="170dp"
android:layout_height="170dp"
android:background="#FFFFFF"
android:minHeight="50dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/contentad_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:textColor="#0000FF"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.35"
android:orientation="vertical">
<ImageView
android:id="@+id/contentad_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:adjustViewBounds="true"
android:maxHeight="100dp" />
<TextView
android:id="@+id/contentad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:textColor="#0000FF"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:orientation="vertical">
<TextView
android:id="@+id/contentad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_marginTop="16dp"
android:gravity="bottom"
android:orientation="horizontal">
<TextView
android:id="@+id/contentad_advertiser"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="bottom"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/contentad_logo"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginRight="8dp"
android:gravity="bottom" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.formats.NativeContentAdView>
// ad_app_install.xml
<com.google.android.gms.ads.formats.NativeAppInstallAdView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="170dp"
android:layout_height="170dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#FFFFFF"
android:minHeight="50dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="3dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/appinstall_app_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:paddingBottom="5dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/appinstall_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold" />
<RatingBar
android:id="@+id/appinstall_stars"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="5"
android:stepSize="0.5" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/appinstall_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:textSize="12sp" />
<ImageView
android:id="@+id/appinstall_image"
android:layout_width="250dp"
android:layout_height="175dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp" />
<com.google.android.gms.ads.formats.MediaView
android:id="@+id/appinstall_media"
android:layout_width="250dp"
android:layout_height="175dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingTop="10dp">
<TextView
android:id="@+id/appinstall_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingStart="5dp"
android:textSize="12sp" />
<TextView
android:id="@+id/appinstall_store"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingStart="5dp"
android:textSize="12sp" />
<Button
android:id="@+id/appinstall_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.formats.NativeAppInstallAdView>
This layout file will be used for our own ViewType.
// list_single_album_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/five_dp"
android:elevation="3dp"
card_view:cardCornerRadius="@dimen/zero_dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless">
<ImageView
android:id="@+id/thumbnail_single"
android:layout_width="@dimen/album_cover_height"
android:layout_height="@dimen/album_cover_height"
android:scaleType="centerCrop" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
we will define two ViewHolder classes in our project. one to hold views of type Native Content Ads and one for Native Install Ads.
// NativeAppInstallAdViewHolder.kt
class NativeAppInstallAdViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
init {
val adView = view as NativeAppInstallAdView
// Register the view used for each individual asset.
// The MediaView will display a video asset if one is present in the ad, and the
// first image asset otherwise.
val mediaView = adView.appinstall_media as MediaView
adView.mediaView = mediaView
adView.headlineView = adView.findViewById(R.id.appinstall_headline)
adView.bodyView = adView.findViewById(R.id.appinstall_body)
adView.callToActionView = adView.findViewById(R.id.appinstall_call_to_action)
adView.iconView = adView.findViewById(R.id.appinstall_app_icon)
adView.priceView = adView.findViewById(R.id.appinstall_price)
adView.starRatingView = adView.findViewById(R.id.appinstall_stars)
adView.storeView = adView.findViewById(R.id.appinstall_store)
}
}
For Content Ads we will create separate ViewHolder class.
class NativeContentAdViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
init {
val adView = view as NativeContentAdView
// Register the view used for each individual asset.
adView.headlineView = adView.findViewById(R.id.contentad_headline)
adView.imageView = adView.findViewById(R.id.contentad_image)
adView.bodyView = adView.findViewById(R.id.contentad_body)
adView.callToActionView = adView.findViewById(R.id.contentad_call_to_action)
adView.logoView = adView.findViewById(R.id.contentad_logo)
adView.advertiserView = adView.findViewById(R.id.contentad_advertiser)
}
}
Now create a new class SingleAlbumAdapter.kt
We need to define three types of Views in our RecyclerViewAdapter class.
One for our own items, one for Native Content Ad and one for Native App Install Ad.
// declare these variables in SingleAlbumAdapter class
private val PHOTO_ITEM_VIEW_TYPE = 0
private val NATIVE_APP_INSTALL_AD_VIEW_TYPE = 1
private val NATIVE_CONTENT_AD_VIEW_TYPE = 2
override getItemViewType function in adapter class. which will check if item at a position is of type NativeAd, it will retun AD_VIEW_TYPE
otherwise it will return PHOTO_ITEM_VIEW_TYPE
.
override fun getItemViewType(position: Int): Int {
val recyclerViewItem = mRecyclerViewItems[position]
if (recyclerViewItem is NativeAppInstallAd) {
return NATIVE_APP_INSTALL_AD_VIEW_TYPE
} else if (recyclerViewItem is NativeContentAd) {
return NATIVE_CONTENT_AD_VIEW_TYPE
}
return PHOTO_ITEM_VIEW_TYPE
}
also implement override function getItemCount().
override fun getItemCount(): Int {
return mRecyclerViewItems.size
}
onCreateViewHolder will return RecyclerView.ViewHolder
object based on ViewType
.
We have already created ViewHolder
layout files and classes.
when
statement is equivalent to switch
in Java.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
NATIVE_APP_INSTALL_AD_VIEW_TYPE -> {
val nativeAppInstallLayoutView = LayoutInflater.from(
parent.context).inflate(R.layout.ad_app_install,
parent, false)
return NativeAppInstallAdViewHolder(nativeAppInstallLayoutView)
}
NATIVE_CONTENT_AD_VIEW_TYPE -> {
val nativeContentLayoutView = LayoutInflater.from(
parent.context).inflate(R.layout.ad_content,
parent, false)
return NativeContentAdViewHolder(nativeContentLayoutView)
}
PHOTO_ITEM_VIEW_TYPE -> {
val menuItemLayoutView = LayoutInflater.from(parent.context).inflate(
R.layout.list_single_album_layout, parent, false)
return ViewHolderPhotoItem(menuItemLayoutView)
}
else -> {
val menuItemLayoutView = LayoutInflater.from(parent.context).inflate(R.layout.list_single_album_layout, parent, false)
return ViewHolderPhotoItem(menuItemLayoutView)
}
}
}
Add below functions in RecyclerView adapter class.
Function populateContentAdView
will receive an object of type NativeContentAdView
& NativeContentAd
.
It will bind Native Content Ad with Native Content AdView
.
private fun populateContentAdView(nativeContentAd: NativeContentAd,
adView: NativeContentAdView) {
// Some assets are guaranteed to be in every NativeContentAd.
(adView.headlineView as TextView).text = nativeContentAd.headline
(adView.bodyView as TextView).text = nativeContentAd.body
(adView.callToActionView as TextView).text = nativeContentAd.callToAction
(adView.advertiserView as TextView).text = nativeContentAd.advertiser
val images = nativeContentAd.images
if (images.size > 0) {
(adView.imageView as ImageView).setImageDrawable(images[0].drawable)
}
// Some aren't guaranteed, however, and should be checked.
val logoImage = nativeContentAd.logo
if (logoImage == null) {
adView.logoView.visibility = View.INVISIBLE
} else {
(adView.logoView as ImageView).setImageDrawable(logoImage.drawable)
adView.logoView.visibility = View.VISIBLE
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeContentAd)
}
Function populateAppInstallAdView
will receive an object of type NativeAppInstallAdView
& NativeAppInstallAd
.
It will bind Native Install Ad object with Native Install AdView
.
private fun populateAppInstallAdView(nativeAppInstallAd: NativeAppInstallAd,
adView: NativeAppInstallAdView) {
// Some assets are guaranteed to be in every NativeAppInstallAd.
(adView.iconView as ImageView).setImageDrawable(nativeAppInstallAd.icon
.drawable)
(adView.headlineView as TextView).text = nativeAppInstallAd.headline
(adView.bodyView as TextView).text = nativeAppInstallAd.body
(adView.callToActionView as Button).text = nativeAppInstallAd.callToAction
// These assets aren't guaranteed to be in every NativeAppInstallAd, so it's important to
// check before trying to display them.
if (nativeAppInstallAd.price == null) {
adView.priceView.visibility = View.INVISIBLE
} else {
adView.priceView.visibility = View.VISIBLE
(adView.priceView as TextView).text = nativeAppInstallAd.price
}
if (nativeAppInstallAd.store == null) {
adView.storeView.visibility = View.INVISIBLE
} else {
adView.storeView.visibility = View.VISIBLE
(adView.storeView as TextView).text = nativeAppInstallAd.store
}
if (nativeAppInstallAd.starRating == null) {
adView.starRatingView.visibility = View.INVISIBLE
} else {
(adView.starRatingView as RatingBar).rating = nativeAppInstallAd.starRating!!.toFloat()
adView.starRatingView.visibility = View.VISIBLE
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAppInstallAd)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
// holder?.bindItems(albumList.get(position), glide, options, inOnItemClick)
val viewType = getItemViewType(position)
when (viewType) {
NATIVE_APP_INSTALL_AD_VIEW_TYPE -> {
val appInstallAd = mRecyclerViewItems[position] as NativeAppInstallAd
populateAppInstallAdView(appInstallAd, holder?.itemView as NativeAppInstallAdView)
}
NATIVE_CONTENT_AD_VIEW_TYPE -> {
val contentAd = mRecyclerViewItems[position] as NativeContentAd
populateContentAdView(contentAd, holder?.itemView as NativeContentAdView)
}
PHOTO_ITEM_VIEW_TYPE -> {
val menuItemHolder = holder as ViewHolderPhotoItem
val menuItem = mRecyclerViewItems[position] as String
glide.load(menuItem).apply { options }.thumbnail(0.4f)
.into(holder.itemView.thumbnail_single)
holder.itemView.setOnClickListener(object : View.OnClickListener {
override fun onClick(p0: View?) {
inOnItemClick.onItemClick(menuItem, false)
}
})
}
else -> {
val listItemHolder = holder as ViewHolderPhotoItem
val listItem = mRecyclerViewItems[position]
glide.load(listItem).apply { options }.thumbnail(0.4f)
.into(holder.itemView.thumbnail_single)
holder.itemView.setOnClickListener(object : View.OnClickListener {
override fun onClick(p0: View?) {
inOnItemClick.onItemClick(position.toString(), false)
}
})
}
}
}
Define ViewHolder class for your own view
inner class ViewHolderPhotoItem(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val menuItemImage: ImageView
init {
menuItemImage = itemView.thumbnail_single as ImageView
}
}
Conclusion:-
We have learned about Native Ads Advanced in Firebase and How to display Native Ads advanced in your Android Application.
We have learned how to implement multiple ViewTypes for RecyclerView items in Kotlin.