Native Ads Advanced is a format in which ad assets are
presented to users via UI components that are
native to the platform. They're shown using the same types of views with which
you're already building your layouts, and can be formatted to match the visual
design of the user experience in which they live. In coding terms, this means
that when a native ad loads, your app receives a
NativeAd
object that contains its assets, and the app (rather than the SDK) is then
responsible for displaying them.
NativeAppInstallAd
,
and content ads are represented by
NativeContentAd
.
These objects contain the assets for the native ad.
This guide shows you how to integrate Native Ads Advanced into an Android app.
Prerequisites
- Import the Google Mobile Ads SDK, either by itself or as part of Firebase.
Load an Ad
Native ads are loaded via the
AdLoader
class,
which has its own
Builder
class to customize it during creation. By adding listeners to the AdLoader
while building it, an app specifies which types of native ads it is ready to
receive. The AdLoader
then requests just those types.
Build an AdLoader
The following code demonstrates how to build anAdLoader
that can load either
an app install ad or a content ad in a single request:
Java
AdLoader adLoader = new AdLoader.Builder(context, "ca-app-pub-3940256099942544/2247696110") .forAppInstallAd(new OnAppInstallAdLoadedListener() { @Override public void onAppInstallAdLoaded(NativeAppInstallAd appInstallAd) { // Show the app install ad. } }) .forContentAd(new OnContentAdLoadedListener() { @Override public void onContentAdLoaded(NativeContentAd contentAd) { // Show the content ad. } }) .withAdListener(new AdListener() { @Override public void onAdFailedToLoad(int errorCode) { // Handle the failure by logging, altering the UI, and so on. } }) .withNativeAdOptions(new NativeAdOptions.Builder() // Methods in the NativeAdOptions.Builder class can be // used here to specify individual options settings. .build()) .build();
Kotlin
val adLoader = AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110") .forAppInstallAd { ad : NativeAppInstallAd -> // Show the app install ad. } .forContentAd { ad : NativeContentAd -> // Show the content ad. } .withAdListener(object : AdListener() { override fun onAdFailedToLoad(errorCode: Int) { // Handle the failure by logging, altering the UI, and so on. } }) .withNativeAdOptions(NativeAdOptions.Builder() // Methods in the NativeAdOptions.Builder class can be // used here to specify individual options settings. .build()) .build()
Prepare for the individual formats
The first two methods above are responsible for preparing the AdLoader
for a
particular type of native ad:
forAppInstallAd()
- Calling this method configures the
AdLoader
to request app install ads. When an ad has loaded successfully, the listener object'sonAppInstallAdLoaded()
method is called. forContentAd()
- This method works the same as
forAppInstallAd()
, but with content ads. When an ad has loaded successfully, theonContentAdLoaded()
method is invoked on the listener object.
Even when the AdLoader
has handlers for multiple native ad formats, the SDK
only makes a single ad request. Google selects and returns the ad that maximizes
publisher yield.
Use AdListener with an AdLoader
During creation of the AdLoader
above, the
withAdListener
function sets an
AdListener
.
This is an optional step. The method takes an AdListener
as its lone
parameter, which receives callbacks from the AdLoader
when ad lifecycle events
take place:
Java
.withAdListener(new AdListener() { // AdListener callbacks like OnAdFailedToLoad, OnAdOpened, and so on, // can be overridden here. })
Kotlin
.withAdListener(object : AdListener() { // AdListener callbacks like OnAdFailedToLoad, OnAdOpened, and so on, // can be overridden here. })
There is one important difference between the way AdListeners
work with
native ads and the way they work with banners and interstitials. Because the
AdLoader
has its own, format-specific listeners
(NativeAppInstallAd.OnAppInstallAdLoadedListener
and so on), to use when an ad has loaded, the onAdLoaded()
method
from AdListener
is not called when a native ad loads successfully.
Setting options
withNativeAdOptions()
The last function included in the creation of the AdLoader
above is another
optional method, withNativeAdOptions()
:
Java
.withNativeAdOptions(new NativeAdOptions.Builder() // Methods in the NativeAdOptions.Builder class can be // used here to specify individual options settings. .build() )
Kotlin
.withNativeAdOptions(NativeAdOptions.Builder() // Methods in the NativeAdOptions.Builder class can be // used here to specify individual options settings. .build() )
The
NativeAdOptions
object allows apps to set specific options used in making the request. Its
Builder
class offers these methods to use when creating an instance:
setReturnUrlsForImageAssets()
- Image assets for native ads are returned via instances of
NativeAd.Image
, which holds aDrawable
and aUri
. If this option is set to false (which is the default), the SDK fetches image assets automatically and populates both theDrawable
and theUri
for you. If it's set to true, however, the SDK instead populates just theUri
field, allowing you to download the actual images at your discretion.
setImageOrientation()
- Some creatives have multiple available images to match different device
orientations. Calling this method with one of the
NativeAdOptions
orientation constants (ORIENTATION_PORTRAIT
,ORIENTATION_LANDSCAPE
, orORIENTATION_ANY
) requests images for a particular orientation. If this method is not called, the default value ofORIENTATION_ANY
is used.
setRequestMultipleImages()
- Some image assets contain a series of images rather than just one. By setting this value to true, your app indicates that it's prepared to display all the images for any assets that have more than one. By setting it to false (default) your app instructs the SDK to provide just the first image for any assets that contain a series.
- If
withNativeAdOptions
is not called at all when creating anAdLoader
, the default value for each option is used.
setAdChoicesPlacement()
- The AdChoices overlay is set to the top right corner by default. Apps can change which corner this overlay is rendered in by setting this property to one of the following:
-
- ADCHOICES_TOP_LEFT
-
- ADCHOICES_TOP_RIGHT
-
- ADCHOICES_BOTTOM_RIGHT
-
- ADCHOICES_BOTTOM_LEFT
setVideoOptions()
- Apps can use this method to set options for video assets returned as part of a native ad. For more information, see the Native Video section later in this guide.
Loading ads
Once you've finished building an AdLoader
, it's time to use it to load ads.
There are two methods available for this: loadAd()
and loadAds()
.
loadAds()
method currently works only with AdMob ads. For mediated ads,
use loadAd()
instead.
The loadAd()
method sends a request for a single ad:
loadAd()
- This method sends a request for a single ad.
Java
adLoader.loadAd(new AdRequest.Builder().build());
Kotlin
adLoader.loadAd(AdRequest.Builder().build())
loadAds()
- This method sends a request for multiple ads (up to 5):.
Java
adLoader.loadAds(new AdRequest.Builder().build(), 3);
Kotlin
adLoader.loadAds(AdRequest.Builder().build(), 3)
Both of these methods take a
AdRequest
object as their first parameter. This is the same
AdRequest
class used by banners and interstitials, and you can use methods of the
AdRequest
class to add
targeting information, just as you
would with other ad formats.
loadAds()
takes an additional parameter: the number of ads the SDK
should attempt to load for the request. This number is capped at a maximum of
five, and it's not guaranteed that the SDK will return the exact number of ads
requested. If multiple ads are returned by a call to loadAds()
, they will be
different from each other.
After a call to loadAd()
, a single callback will be made to the listener
methods defined above to deliver the native ad
object or report an error.
After a call to loadAds()
, multiple such callbacks will be made (at least one,
and no more than the number of ads requested). Apps requesting multiple ads
should call AdLoader.isLoading()
in their callback implementations to
determine whether the loading process has finished.
isLoading()
in the onAppInstallAdLoaded()
callback:
Java
final AdLoader adLoader = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110") .forAppInstallAd(new NativeAppInstallAd.OnAppInstallAdLoadedListener() { @Override public void onAppInstallAdLoaded(NativeAppInstallAd ad) { ... // some code that displays the app install ad. ... if (adLoader.isLoading()) { // The AdLoader is still loading ads. // Expect more adLoaded or onAdFailedToLoad callbacks. } else { // The AdLoader has finished loading ads. } } }).build();adLoader.loadAds(new AdRequest.Builder().build(), 3);
Kotlin
lateinit var adLoader: AdLoader ... adLoader = AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110") .forAppInstallAd { ... // some code that displays the app install ad. ... if (adLoader.isLoading) { // The AdLoader is still loading ads. // Expect more adLoaded or onAdFailedToLoad callbacks. } else { // The AdLoader has finished loading ads. } }.build()adLoader.loadAds(AdRequest.Builder().build(), 3)
Always test with test ads
When building and testing your apps, make sure you use test ads rather than live, production ads. Failure to do so can lead to suspension of your account.
The easiest way to load test ads is to use our dedicated test ad unit ID for Native Advanced on Android:
ca-app-pub-3940256099942544/2247696110
It's been specially configured to return test ads for every request, and you're free to use it in your own apps while coding, testing, and debugging. Just make sure you replace it with your own ad unit ID before publishing your app.
For more information about how the Mobile Ads SDK's test ads work, see Test Ads.
When to request ads
Applications displaying native ads are free to request them in advance of when they'll actually be displayed. In many cases, this is the recommended practice. An app displaying a list of items with native ads mixed in, for example, can load native ads for the whole list, knowing that some will be shown only after the user scrolls the view and some may not be displayed at all.
Display an ad
When a native ad loads, the SDK invokes the listener for the corresponding ad format. Your app is then responsible for displaying the ad, though it doesn't necessarily have to do so immediately. To make displaying system-defined ad formats easier, the SDK offers some useful resources, as described below.
Ad view classes
For each of the system-defined formats, there is a corresponding ad view class:
NativeAppInstallAdView
for app install ads and
NativeContentAdView
for content ads. These ad view classes are
ViewGroup
that publishers should use as the roots for ads of the corresponding format. A
single NativeContentAdView
, for example, corresponds to a single content ad.
Each view used to display that ad's assets (the ImageView
that displays the
screenshot asset, for instance) should be a child of the NativeContentAdView
object.
The view hierarchy for a content ad that uses a
RelativeLayout
to display its asset views might look like this:
The ad view classes also provide methods used to register the view used for
each individual asset, and one to register the NativeAd
object itself.
Registering the views in this way allows the SDK to automatically handle tasks
such as:
- Recording clicks
- Recording impressions (when the first pixel is visible on the screen)
- Displaying the AdChoices overlay
AdChoices overlay
An AdChoices overlay is added to each ad view by the SDK. Leave space in your preferred corner of your native ad view for the automatically inserted AdChoices logo. Also, it's important that the AdChoices overlay be easily seen, so choose background colors and images appropriately. For more information on the overlay's appearance and function, see Native ads advanced field descriptions.Ad attribution
You must display an ad attribution to denote that the view is an advertisement. See this page for the policy guidelines.
Code example
These are the steps for displaying a system-defined native ad format:- Create an instance of the correct ad view class.
- For each ad asset to be displayed:
- Populate the asset view with the asset in the ad object.
- Register the asset view with the
ViewGroup
class.
- Register the
MediaView
, if one is being used. - Register the ad object with the
ViewGroup
class.
Here is an example function that displays a NativeAppInstallAd
:
Java
private void displayAppInstallAd(ViewGroup parent, NativeAppInstallAd ad) { // Inflate a layout and add it to the parent ViewGroup. LayoutInflater inflater = (LayoutInflater) parent.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); NativeAppInstallAdView adView = (NativeAppInstallAdView) inflater .inflate(R.layout.my_ad_layout, parent); // Locate the view that will hold the headline, set its text, and call the // NativeAppInstallAdView's setHeadlineView method to register it. TextView headlineView = adView.findViewById<TextView%>(R.id.ad_headline); headlineView.setText(ad.getHeadline()); adView.setHeadlineView(headlineView); ... // Repeat the above process for the other assets in the NativeAppInstallAd // using additional view objects (Buttons, ImageViews, etc). ... // If the app is using a MediaView to display video, it should be // instantiated and passed to setMediaView. This view is a little different // in that the asset is populated automatically, so there's one less step. MediaView mediaView = (MediaView) adView.findViewById(R.id.ad_media); adView.setMediaView(mediaView); // Call the NativeAppInstallAdView's setNativeAd method to register the // NativeAdObject. adView.setNativeAd(ad); // Place the AdView into the parent. parent.addView(adView); }
Kotlin
fun displayAppInstallAd(parent: ViewGroup, ad: NativeAppInstallAd) { // Inflate a layout and add it to the parent ViewGroup. val inflater = parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater val adView = inflater.inflate(R.layout.my_ad_layout, parent) as NativeAppInstallAdView // Locate the view that will hold the headline, set its text, and use the // NativeAppInstallAdView's headlineView property to register it. val headlineView = adView.findViewById<TextView>(R.id.ad_headline) headlineView.text = ad.headline adView.headlineView = headlineView ... // Repeat the above process for the other assets in the NativeAppInstallAd using // additional view objects (Buttons, ImageViews, etc). ... // If the app is using a MediaView to display video, it should be instantiated // and assign to the mediaView property. This view is a little different in that // the asset is populated automatically, so there's one less step. val mediaView = adView.findViewById<MediaView>(R.id.ad_media) adView.mediaView = mediaView // Call the NativeAppInstallAdView's setNativeAd method to register the // NativeAdObject. adView.setNativeAd(ad) // Place the AdView into the parent. parent.addView(adView) }
Let's take a look at the individual tasks:
Inflate the layout
Java
LayoutInflater inflater = (LayoutInflater) parent.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); NativeAppInstallAdView adView = (NativeAppInstallAdView) inflater .inflate(R.layout.my_ad_layout, parent);
Kotlin
val inflater = parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater val adView = inflater.inflate(R.layout.my_ad_layout, parent) as NativeAppInstallAdView
NativeAppInstallAdView
. Note that you could also reuse an existing
NativeAppInstallAdView
if there's one in your fragment or activity, or even
create an instance dynamically without using a layout file.
Populate and register the asset views
This sample code locates the view used to display the headline, sets its text
using the string asset provided by the ad object, and registers it with the
NativeAppInstallAdView
object:
Java
TextView headlineView = adView.findViewById<TextView>(R.id.ad_headline); headlineView.setText(ad.getHeadline()); adView.setHeadlineView(headlineView);
Kotlin
val headlineView = adView.findViewById<TextView>(R.id.ad_headline) headlineView.text = ad.headline adView.headlineView = headlineView
This process of locating the view, setting its value, and registering it with the ad view class should be repeated for each of the assets provided by the native ad object that the app will display.
Register the MediaView, if present
The MediaView
is a special View
designed to display video assets (it's
covered in detail in the Native Video section below). Apps
using a MediaView
don't need to populate it with an asset, but must register
it with the NativeAdView
like this:
Java
MediaView mediaView = adView.findViewById<MediaView>(R.id.ad_media); adView.setMediaView(mediaView);
Kotlin
val mediaView = adView.findViewById<MediaView>(R.id.ad_media) adView.mediaView = mediaView
Register the native ad object
This final step registers the native ad object with the view that's responsible for displaying it:
Java
adView.setNativeAd(ad);
Kotlin
adView.setNativeAd(ad)
Native video
In addition to images, text, and numbers, some native ads contain video assets. Not every ad includes a video asset, and apps are not required to display them.
To simplify the configuration and display of video, the Mobile Ads SDK provides the following video-related classes:
VideoOptions
The VideoOptions
class allows apps to configure how native video assets should behave.
VideoOptions
objects should be assigned to a NativeAdOptions
object that's
used when constructing the AdLoader
:
Java
VideoOptions videoOptions = new VideoOptions.Builder() .setStartMuted(false) .build(); NativeAdOptions adOptions = new NativeAdOptions.Builder() .setVideoOptions(videoOptions) .build(); AdLoader adLoader = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110") .forAppInstallAd( ... ) .forContentAd( ... ) .withNativeAdOptions(adOptions) .build();
Kotlin
val videoOptions = VideoOptions.Builder() .setStartMuted(false) .build() val adOptions = NativeAdOptions.Builder() .setVideoOptions(videoOptions) .build() val adLoader = AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110") .forAppInstallAd( ... ) .forContentAd( ... ) .withNativeAdOptions(adOptions) .build()
The VideoOptions.Builder
class currently offers one method,
setStartMuted()
,
which tells the SDK whether video assets should start in a muted state.
The default value is true
.
MediaView
Video assets are displayed to users via MediaView
. This is a View
that can be defined in an XML layout or constructed dynamically, and
should be placed within the view hierarchy of a NativeAdView
, just
like any other asset view.
Unlike other asset views, however, apps do not need to manually populate
a MediaView
with its asset. The SDK handles this automatically:
- If a video asset is available, it's buffered and starts playing
inside the
MediaView
. - If the ad does not contain a video asset, the first image asset is
downloaded and placed inside the
MediaView
instead.
This autopopulation of the MediaView
with an available image asset does not
always work when using mediation. Because not all mediation adapters guarantee
that they'll create a media view for every ad, it's possible for a blank one to
be returned for mediated ads. Publishers using mediation should check the
hasVideoContent()
function of an ad's VideoController
, to see if it contains
a video asset, before displaying the MediaView
. If there is no video content,
publishers should display an image view that they populate manually with a
relevant image.
Here's a snippet from the NativeAdvancedExample that shows/hides the relevant views according to whether the ad has video content:
Java
MediaView mediaView = adView.findViewById(R.id.appinstall_media); ImageView mainImageView = adView.findViewById(R.id.appinstall_image); // Apps can check the VideoController's hasVideoContent property to // determine if the ad has a video asset. if (videoController.hasVideoContent()) { mainImageView.setVisibility(View.GONE); adView.setMediaView(mediaView); // Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The // VideoController will call methods on this object when events occur in the video // lifecycle. videoController.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() { public void onVideoEnd() { // Publishers should allow native ads to complete video playback before // refreshing or replacing them with another ad in the same UI location. mRefresh.setEnabled(true); super.onVideoEnd(); } }); } else { mediaView.setVisibility(View.GONE); adView.setImageView(mainImageView); Listimages = nativeAppInstallAd.getImages(); if (images.size() > 0) { mainImageView.setImageDrawable(images.get(0).getDrawable()); } mRefresh.setEnabled(true); }
Kotlin
val mediaView = adView.findViewById(R.id.appinstall_media) val mainImageView = adView.findViewById (R.id.appinstall_image) // Apps can check the VideoController's hasVideoContent property to determine if the // ad has a video asset. if (videoController.hasVideoContent()) { mainImageView.visibility = View.GONE adView.mediaView = mediaView // Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The // VideoController will call methods on this object when events occur in the video // lifecycle. videoController.setVideoLifecycleCallbacks(object: VideoController.VideoLifecycleCallbacks() { override fun onVideoEnd() { // Publishers should allow native ads to complete video playback before // refreshing or replacing them with another ad in the same UI location. refresh_button.isEnabled = true super.onVideoEnd() } }) } else { mediaView.visibility = View.GONE adView.imageView = mainImageView // At least one image is guaranteed. val images = nativeAppInstallAd.images if (images.size > 0) { mainImageView.setImageDrawable(images[0].drawable) } refresh_button.isEnabled = true }
VideoController
The VideoController
class is used to retrieve information about video assets.
Apps can get a reference to the controller from a NativeAppInstallAd
by
calling the
getVideoController()
method:
Java
VideoController vc = myNativeAd.getVideoController();
Kotlin
val vc = myNativeAd.videoController
This method always returns a VideoController
object, even when
no video asset is present in the ad.
VideoController
offers these methods for querying video state:
hasVideoContent()
- Returns true if the ad has a video asset, and false if it doesn't.getAspectRatio()
- Returns the aspect ratio of the video (width/height), or zero if no video asset is present.
Apps can also use the
VideoController.VideoLifecycleCallbacks
class to get notifications when events occur in the lifecycle of a video asset:
Java
VideoController vc = nativeAd.getVideoController(); vc.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() { public void onVideoEnd() { // Here apps can take action knowing video playback is finished. // It's always a good idea to wait for playback to complete before // replacing or refreshing a native ad, for example. super.onVideoEnd(); } });
Kotlin
val vc = nativeAd.videoController vc.setVideoLifecycleCallbacks(object : VideoController.VideoLifecycleCallbacks() { override fun onVideoEnd() { // Here apps can take action knowing video playback is finished. // It's always a good idea to wait for playback to complete before // replacing or refreshing a native ad, for example. super.onVideoEnd() } })
Destroy ad
When you are done showing your native ad, you should destroy it so that the ad is properly garbage collected. This is especially important if you're using Native Video, or if you're going to reuse the NativeAdView that's showing the ad. Use the following code to destroy an ad:
Java
if (nativeAd.getVideoController().hasVideoContent()) { adView.setMediaView(null); // Warning: If you are reusing this native ad view for another ad, // make sure to destroy the ad before configuring your new ad with the // view. Otherwise, this call to setNativeAd() will override the // setNativeAd() call you made with your new ad. adView.setNativeAd(nativeAd); } nativeAd.destroy();
Kotlin
if (nativeAd.videoController.hasVideoContent()) { adView.mediaView = null // Warning: If you are reusing this native ad view for another ad, // make sure to destroy the ad before configuring your new ad with the // view. Otherwise, this call to setNativeAd() will override the // setNativeAd() call you made with your new ad. adView.nativeAd = nativeAd } nativeAd.destroy()
Additional resources
Samples on GitHub
Codelab
Next steps
- Learn about Ad Events and Ad Targeting.
- Try another ad format: