How to Implement Ads in an Android App

Preview image.

Mobile ads offer a powerful way to monetize your apps. This blog will show you how to implement four types of ads in Android including: banner ads, interstitial ads, native ads and rewarded ads. We have implemented ads in our to-do list mobile app Colorful Reminder as shown in the video below, check it out if you’re interested. Alright, let’s get started.

Introduction to Ads in Android

Warning!

Whenever you are testing ads code, always make sure you are using a test ad id provided by Google as we will be doing in this tutorial. Do not use the real ad ids you created in your Admob account as you risk getting your account suspended if you click your own ads.

Here is a quote from Google: “Publishers may not click their own ads or use any means to inflate impressions and/or clicks artificially, including manual methods. Testing your own ads by clicking on them is not allowed. You you can find the statement here: https://support.google.com/admob/answer/2753860#Invalid_clicks.

When you’re done testing and developing your app, replace the test ad ids with your real ad ids before you release your app.

Before diving into the technical details, let’s get a brief overview of the types of ads we will be covering in this blog.

Banner Ads

Banner ads are the simplest form of ads.They are rectangular units, usually placed at the bottom or top of the app view. They are the least intrusive as they occupy a fairly small part of the screen. You can find Google’s banner ads guidance here: https://support.google.com/admob/answer/6128877.

Banner ads illustrations.

Interstitial Ads

Interstitial ads cover the whole screen when they are displayed. They are very common in mobile games. When they appear, they can show a video or an image, commonly with a call to action such as a button to download an app from Google Play. The user has the choice between clicking the ad or closing it. They’re typically displayed during pauses or breaks, such as after winning a level in a game. You can find Google’s Interstitial ads’ guidance here https://support.google.com/admob/answer/6066980.

Interstitial ad illustration.

Native Ads

Native ads allow the developer to customize the appearance of the ad so that it blends seamlessly with the app’s UI or theme. Unlike banner or interstitial ads, which have predefined layouts, native ads provide flexibility to developers by allowing them to choose the ads’ colors, fonts, placements and more. However, always make sure to follow the guidelines that Google sets for native ads, you can find them here: https://support.google.com/admob/answer/6329638.

Rewarded Ads

Rewarded ads offer the user a reward for doing an action such as watching a video, taking a survey or playing a game. For instance, many mobile games offer the player extra coins or points by watching a video ad. You can find Google’s policies regarding rewarded ads here https://support.google.com/admob/answer/7313578.

More Details

This is a very brief introduction to mobile ads. If you would like more details, visit Google’s documentation on this link: https://developers.google.com/admob/android/quick-start

Android Studio Project Setup

First we start by creating a new project in Android Studio. We will be using the version Ladybug | 2024.2.1 Patch 1. Follow these steps to create an empty project:

1. Click on File -> New -> New Project.

2. Choose Phone and Tablet on the left menu and select No Activity on the right menu. Then click Next.

Project settings 1.

3. In the next window, set the following:

  • In the Name field, set the app name to AdsTutorial. 
  • Leave the Package name as is, it should be automatically set to com.example.adstutorial.
  • Set the location of your project in the Save location field to any location of your choosing.
  • We will be using Java for this blog, so set the Language box to Java. 
  • Set the Minimum SDK to your liking, we leave it at API 24 Nougat. 
  • Set the Build configuration language, we will leave it as recommended by Android Studio to Kotlin DSL. 
Project settings 2.

4. Click Finish and wait until Android Studio is done importing and setting up the project. 

Import the Google Mobile Ads SDK

To import the ads sdk, follow these steps:

1. Open the file settings.gradle.kts (Project Settings) by double clicking it.

Project setings kts file.

2. Make sure google() and mavenCentral() are included inside the pluginManagement and dependencyResolutionManagement sections as highlighted in the code below. Your file should already have these lines by default, but check just in case and add them if they are missing. 

pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()

}
}

rootProject.name = "AdsTutorial"
include(":app")

3. Open the build.gradle.kts (Module :app) file.

Build settings kts file.

4. Paste the line implementation("com.google.android.gms:play-services-ads:24.2.0") inside the dependencies section.

plugins {
    alias(libs.plugins.android.application)
}

android {
    namespace = "com.example.adstutorial"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.adstutorial"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
}

dependencies {

    implementation(libs.appcompat)
    implementation(libs.material)
    testImplementation(libs.junit)
    androidTestImplementation(libs.ext.junit)
    androidTestImplementation(libs.espresso.core)
    implementation("com.google.android.gms:play-services-ads:24.2.0")
}

5. Click Sync now on the top right and wait for it to finish syncing.

Sync now button.

Create the Code and User Interface (UI)

Now we create the UI, we will add a button for each type of ads: banner ads, interstitial ads, native ads and rewarded ads. When a button is clicked, it will load and display the corresponding ad. Follow the following steps:

1. Select File -> New -> Activity -> Empty Views Activity. This will create the main activity of our app, which is basically the starting point when the app is loaded.

Create activity.

2. In the next window, set the following:

  • Set Activity Name to MainActivity.
  • Check the Generate a Layout File checkbox.
  • Set Layout Name to activity_main.
  • Check the Launcher Activity checkbox. It will set this activity as the first screen displayed when the app is launched. 
  • Leave Package name as is, it should be already set to com.example.adstutorial.
  • Set Source Language to Java.
  • Set Target Source Set to main.
Activity settings.

3. Click Finish. You will now have a MainActivity.Java file along with the activity_main.xml file which contains the UI. 

Activity and layout files.

Open the libs.versions.toml file.

toml file.

Now try to build the project, click the hammer icon at the top right as shown below.

Build button.

If your project builds without any error, then you can skip this step. However, If you get this error “Dependency androidx.activity:activity:1.10.1′ requires libraries and applications that depend on it to compile against version 35 or later of the Android APIs.” then set the activity version to 1.8.0 as highlighted below.

[versions]
agp = "8.7.1"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
appcompat = "1.7.0"
material = "1.12.0"
activity = "1.8.0"
constraintlayout = "2.2.1"

[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }

If applicable, click Sync now as we did earlier and wait for it to finish. If you build the project now, it should not give you any errors.

Now we need to set an application id in the manifest file. We will be using the sample one provided by Google, you can find it here: https://developers.google.com/admob/android/quick-start#java. In your real app, you would get this app id from your Admob account and replace this sample one. To do this, open the AndroidManifest.xml.

Manifest file.

Add the highlighted code below.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AdsTutorial"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>

</application>

</manifest>

Warning!

When you use your real ads from Admob, replace this application id with your real app id. You can find it in your Admob account.

Open the activity_main.xml file, then click on the Code button on the top right as shown highlighted in red in the image below. This will switch to the XML view of the layout file. 

Code button.

Replace the XML code you have inside activity_main.xml with the following code.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/show_banner_ad_button"
        android:layout_width="200dp"
        android:layout_height="80dp"
        android:layout_marginTop="10dp"
        android:text="Show Banner Ad"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/show_interstitial_ad_button"
        android:layout_width="200dp"
        android:layout_height="80dp"
        android:layout_marginTop="10dp"
        android:text="Show Interstitial Ad"
        app:layout_constraintTop_toBottomOf="@id/show_banner_ad_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/show_native_ad_button"
        android:layout_width="200dp"
        android:layout_height="80dp"
        android:layout_marginTop="10dp"
        android:text="Show Native Ad"
        app:layout_constraintTop_toBottomOf="@id/show_interstitial_ad_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/show_rewarded_ad_button"
        android:layout_width="200dp"
        android:layout_height="80dp"
        android:layout_marginTop="10dp"
        android:text="Show Rewarded Ad"
        app:layout_constraintTop_toBottomOf="@id/show_native_ad_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <FrameLayout
        android:id="@+id/banner_ad_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_alignParentBottom="true"
        app:layout_constraintBottom_toBottomOf="parent"/>

    <FrameLayout
        android:id="@+id/native_ad_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_constraintTop_toBottomOf="@+id/show_rewarded_ad_button"/>

</androidx.constraintlayout.widget.ConstraintLayout>

It should look like this:

UI layout.

Here’s some basic information about this layout:

  • The parent container is a ConstraintLayout, it allows you to place items relative to other items. For example, the interstitial ad button is placed below the banner ad button using the line app:layout_constraintTop_toBottomOf="@id/show_banner_ad_button"
  • Inside the layout are four buttons, one for each type of ad. When clicked, it will load and display the corresponding ad. 
  • After the buttons, there are two FrameLayout components, one for the banner ad and the other for the native ad. These are just containers, they only reserve a space for the ads and currently do not display anything. Later, we will add components to them in code.

Now it’s time to code. First, let’s create some member and static variables that we will need. Copy the following code and paste it In the MainActivity class inside the MainActivity.java file.

package com.example.adstutorial;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdLoader;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.OnUserEarnedRewardListener;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import com.google.android.gms.ads.rewarded.RewardItem;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;

public class MainActivity extends AppCompatActivity {
    // Tag used to filter logs in the logcat
    private static final String TAG = "MainActivity";

    // For banner ad
    private AdView bannerAd;

    // for interstitial ad
    private InterstitialAd interstitialAd;

    // For native ad
    private NativeAd nativeAd;

    // For rewarded ad
    private RewardedAd rewardedAd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
    }
}

Next we create four empty methods that will later be used to request the ads. We leave them empty as placeholders for now so that we don’t get any compile errors when we set up our buttons below. We will fill the functions one by one later on. Copy the highlighted methods and paste them in the MainActivity class inside the MainActivity.java class. 

package com.example.adstest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdLoader;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.OnUserEarnedRewardListener;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import com.google.android.gms.ads.rewarded.RewardItem;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;

public class MainActivity extends AppCompatActivity {

    // Tag used to filter logs in the logcat
    private static final String TAG = "MainActivity";

    // For banner ad
    private AdView bannerAd;

    // for interstitial ad
    private InterstitialAd interstitialAd;

    // For native ad
    private NativeAd nativeAd;

    // For rewarded ad
    private RewardedAd rewardedAd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
    }

    private void RequestBannerAdd(){

    }

    private void RequestInterstitialAd(){

    }

    private void RequestNativeAd(){

    }

    private void RequestRewardedAd(){

    }
}

Now we initialize the Google Mobile Ads SDK and set click listeners to our buttons, add the highlighted code inside the onCreate method.

package com.example.adstest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdLoader;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.OnUserEarnedRewardListener;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import com.google.android.gms.ads.rewarded.RewardItem;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;

public class MainActivity extends AppCompatActivity {

    // Tag used to filter logs in the logcat
    private static final String TAG = "MainActivity";

    // For banner ad
    private AdView bannerAd;

    // for interstitial ad
    private InterstitialAd interstitialAd;

    // For native ad
    private NativeAd nativeAd;

    // For rewarded ad
    private RewardedAd rewardedAd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        // Initialize the ads SDK. Only need to do it once.
        MobileAds.initialize(this, initializationStatus -> {});

        // Create the click listeners for each button.
        Button showBannerAdButton = findViewById(R.id.show_banner_ad_button);
        showBannerAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestBannerAdd();
            }
        });

        Button showInterstitialAdButton = findViewById(R.id.show_interstitial_ad_button);
        showInterstitialAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestInterstitialAd();
            }
        });

        Button showNativeAdButton = findViewById(R.id.show_native_ad_button);
        showNativeAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestNativeAd();
            }
        });

        Button rewardedAdButton = findViewById(R.id.show_rewarded_ad_button);
        rewardedAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestRewardedAd();
            }
        });
    }

    private void RequestBannerAdd(){

    }

    private void RequestInterstitialAd(){

    }

    private void RequestNativeAd(){

    }

    private void RequestRewardedAd(){

    }
}

The line MobileAds.initialize(this, initializationStatus -> {}) initializes the ads SDK. You should only do this once in your code, this is why putting it in the onCreate method of your launcher activity is the best place. 

The rest of the code simply gets a reference to the buttons we created earlier in activity_main.xml by searching for their id. Then we set the click listener using setOnClickListener so everytime the button is clicked, the onClick method is executed. Inside onClick, we request the proper ad depending on the button clicked by calling the empty methods we created earlier. 

Banner Ad Implementation

Now we implement the empty methods we created earlier, which will load and display the ad. We start with RequestBannerAdd, copy the code below and paste it in the class to replace the empty method.

    // Requests and displays the banner ad.
    private void RequestBannerAdd(){
        // If Ad already exists, remove it first before creating a new one
        DestroyBannerAd();

        FrameLayout adViewContainer = findViewById(R.id.banner_ad_container);

        bannerAd = new AdView(this);

        // Always Use the test ad id when testing.
        bannerAd.setAdUnitId("ca-app-pub-3940256099942544/9214589741");

        bannerAd.setAdSize(AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(this, 360));

        adViewContainer.removeAllViews();
        adViewContainer.addView(bannerAd);

        AdRequest adRequest = new AdRequest.Builder().build();

        // Request the ad.
        bannerAd.loadAd(adRequest);
    }

    // Destroys the banner ad.
    private void DestroyBannerAd(){
        if(bannerAd != null){
            if (bannerAd.getParent() instanceof ViewGroup) {
                ((ViewGroup) bannerAd.getParent()).removeView(bannerAd);
            }
            bannerAd.destroy();
            bannerAd = null;
        }
    }

Here’s what it does:

  1. DestroyBannerAd is called to remove the ad if it has already been created, for example, if you have already clicked the button and you click it again. It also frees up memory and prevents memory leaks.
  2. Creates an AdView and sets the unit id using the method setAdUnitId. The id that is passed is the test ad id that we mentioned earlier.
  3. Finally, the bannerAd.loadAd line loads the ad.

If you now run the app and click the show banner ad button, after you wait for a few seconds, the banner ad will be shown at the bottom of the screen. If it doesn’t, then check the logcat in Android Studio and see if there were any errors.

Interstitial Ad Implementation

Let’s implement the interstitial ad now. Copy and paste the code below to replace the empty RequestInterstitialAd method.

    private void RequestInterstitialAd(){
        // If Ad already exists, remove it first before creating a new one.
        DestroyInterstitialAd();

        AdRequest adRequest = new AdRequest.Builder().build();

        // Always Use the test ad id when testing.
        InterstitialAd.load(this, "ca-app-pub-3940256099942544/1033173712", adRequest, new InterstitialAdLoadCallback() {

            // Callback that is called when it's loaded.
            @Override
            public void onAdLoaded(@NonNull InterstitialAd interstitialAd){
                MainActivity.this.interstitialAd = interstitialAd;

                MainActivity.this.interstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {

                    // Callback called when ad is dismissed.
                    @Override
                    public void onAdDismissedFullScreenContent() {
                        super.onAdDismissedFullScreenContent();

                        Log.d(TAG, "Ad was dismissed");

                        // Destroy the ad when dismissed by the user.
                        DestroyInterstitialAd();
                    }

                    // Callback called when ad failed show.
                    @Override
                    public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                        super.onAdFailedToShowFullScreenContent(adError);

                        Log.d(TAG, "Failed to show ad");

                        // Destroy the ad when loading fails.
                        DestroyInterstitialAd();
                    }
                });

                // Show the interstitial ad
                MainActivity.this.interstitialAd.show(MainActivity.this);

                Log.i(TAG, "Interstitial ad loaded");
            }

            // Callback that is called when ad fails to load.
            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                super.onAdFailedToLoad(loadAdError);

                Log.d(TAG, "Failed to load interstitial ad: " + loadAdError.toString());

                // Destroy the ad when it fails to load
                DestroyInterstitialAd();
            }
        });
    }

    // Destroys the interstitial ad.
    private void DestroyInterstitialAd(){
        interstitialAd = null;
    }

The logic of this code is a bit different than banner ads. The code loads the app using the InterstitialAd.load method and passes it a test ad id as we did before. But this time, we have to override the callbacks. Once the ad is loaded successfully, onAdLoaded is called. Then the ad can be shown. If the ad fails to load, onAdFailedToLoad will be called.

If you press the show interstitial ad button and wait a bit, it will show a full screen test ad and a button to close it.

Native Ad Implementation

Native ads let you customize the appearance of your ads, so we need to define our own UI. Create a new layout by selecting File -> New -> XML -> Layout XML File.

Create layout.

Set the Layout File Name to native_ad_layout and leave the Root Tag as is, we will overwrite the file anyways so it doesn’t matter which you choose. 

Layout settings.

Then click Finish. The file will be added to the res folder.

Layout file.

Open the native_ad_layout.xml file and paste the following XML in it.

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/native_adView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black">

    <TextView
        android:id="@+id/native_ad_headline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:textColor="@color/white"
         />
</com.google.android.gms.ads.nativead.NativeAdView>

The main container is of type NativeAdView, inside the container you can customize how your ad looks. Just for illustration purposes, we only included a TextView with a white text and black background, and we will set it from code. However, you can set many other things like icons, images and more. 

Go back to MainActivity class, and paste the following code to replace the empty RequestNativeAd method. 

    // Requests and displays the native ad.
    private void RequestNativeAd(){
        // If Ad already exists, remove it first before creating a new one.
        DestroyNativeAd();

        // Always Use the test ad id when testing.
        AdLoader adLoader = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110").forNativeAd(new NativeAd.OnNativeAdLoadedListener() {

                    // Callback that is called when it's loaded.
                    @Override
                    public void onNativeAdLoaded(@NonNull NativeAd nativeAd) {
                        Log.d(TAG, "Native ad loaded.");

                        // If callback occurs after native ad is destroyed.
                        if (isDestroyed()) {
                            DestroyNativeAd();
                            return;
                        }

                        MainActivity.this.nativeAd = nativeAd;

                        ViewGroup parent = findViewById(R.id.native_ad_container);

                        NativeAdView adView = (NativeAdView) getLayoutInflater().inflate(R.layout.native_ad_layout, null);

                        // Set the TextView's text.
                        if(nativeAd.getHeadline() != null){
                            TextView headLineText = adView.findViewById(R.id.native_ad_headline);
                            headLineText.setText(nativeAd.getHeadline());
                            adView.setHeadlineView(headLineText);
                        }

                        adView.setNativeAd(nativeAd);
                        parent.removeAllViews();

                        parent.addView(adView);
                    }
                }).withAdListener(new AdListener() {

                    // Callback that's called when ad fails to load.
                    @Override
                    public void onAdFailedToLoad(LoadAdError adError) {
                        Log.e(TAG, "Failed to load native add: " + adError.getMessage());

                        DestroyNativeAd();
                    }
                }).build();

        // Load the ad
        adLoader.loadAd(new AdRequest.Builder().build());
    }

    // Destroys the native ad.
    private void DestroyNativeAd(){
        if(nativeAd != null){
            nativeAd.destroy();
        }
    }

This is pretty similar to the interstitial ad, we request the ad and then wait for it to load, then display the ad. The main difference is because we set our own UI, we have to manually set the TextView we created in our layout using the setHeadlineView method.

If you click the show native ad button and wait a bit, the test ad will show a white text on a black background.

Note

This is just an example, review Google’s native ads guidelines here https://support.google.com/admob/answer/6329638 to make sure your native ad meets the requirements.

Rewarded Ad Implementation

Rewarded ads take the whole screen and prompt you to watch a video or do another action, and in return, the user is rewarded with coins or points or other types of reward. Copy the code below to implement it to replace the empty RequestRewardedAd method. 

    // Requests and displays the rewarded ad.
    private void RequestRewardedAd(){
        // If Ad already exists, remove it first before creating a new one.
        DestroyRewardedAd();

        AdRequest adRequest = new AdRequest.Builder().build();

        // Always Use the test ad id when testing.
        RewardedAd.load(this, "ca-app-pub-3940256099942544/5224354917", adRequest, new RewardedAdLoadCallback() {

                // Callback that's called when ad fails to load.
                @Override
                public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                    Log.d(TAG, "Failed to load rewarded ad: " + loadAdError.toString());

                    DestroyRewardedAd();
                }

                // Callback that is called when it's loaded.
                @Override
                public void onAdLoaded(@NonNull RewardedAd ad) {
                    Log.d(TAG, "Rewarded ad was loaded.");

                    rewardedAd = ad;

                    Activity activityContext = MainActivity.this;

                    // show the ad.
                    rewardedAd.show(activityContext, new OnUserEarnedRewardListener() {

                        // Callback called when the user receives the reward.
                        @Override
                        public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
                            Log.d(TAG, "The user earned the reward.");

                            int rewardAmount = rewardItem.getAmount();
                            String rewardType = rewardItem.getType();

                            Toast.makeText(activityContext, "The user earned the reward: " + rewardAmount + " " + rewardType, Toast.LENGTH_LONG).show();
                        }
                    });

                    rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {

                        // Callback called when ad is dismissed.
                        @Override
                        public void onAdDismissedFullScreenContent() {
                            Log.d(TAG, "Ad dismissed fullscreen content.");

                            DestroyRewardedAd();
                        }

                        // Callback called when ad failed to show.
                        @Override
                        public void onAdFailedToShowFullScreenContent(AdError adError) {
                            Log.e(TAG, "Ad failed to show fullscreen content.");

                            DestroyRewardedAd();
                        }
                    });

                }
            });
    }

    // Destroys the rewarded ad.
    private void DestroyRewardedAd(){
        rewardedAd = null;
    }

Again, as with native and interstitial ads, the code makes the request for an ad and waits for it to load. When loaded successfully, the code enters the onAdLoaded method. The main difference here is the onUserEarnedReward is called once the user is rewarded. Here, we only display a message using a Toast. In a real app, like a game, this is where you would reward the player with extra coins or points. 

If you click the show rewarded ad and wait a bit, you will get a full screen ad. If you watch the video to the end, a Toast will be displayed saying: “The user earned the reward” and some number of coins.

Full Code

Here’s the full code for MainActivity.java:

package com.example.adstutorial;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdLoader;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.OnUserEarnedRewardListener;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import com.google.android.gms.ads.rewarded.RewardItem;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;

public class MainActivity extends AppCompatActivity {
    // Tag used to filter logs in the logcat
    private static final String TAG = "MainActivity";

    // For banner ad
    private AdView bannerAd;

    // for interstitial ad
    private InterstitialAd interstitialAd;

    // For native ad
    private NativeAd nativeAd;

    // For rewarded ad
    private RewardedAd rewardedAd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        // Initialize the ads SDK. Only need to do it once.
        MobileAds.initialize(this, initializationStatus -> {});

        // Create the click listeners for each button.
        Button showBannerAdButton = findViewById(R.id.show_banner_ad_button);
        showBannerAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestBannerAdd();
            }
        });

        Button showInterstitialAdButton = findViewById(R.id.show_interstitial_ad_button);
        showInterstitialAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestInterstitialAd();
            }
        });

        Button showNativeAdButton = findViewById(R.id.show_native_ad_button);
        showNativeAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestNativeAd();
            }
        });

        Button rewardedAdButton = findViewById(R.id.show_rewarded_ad_button);
        rewardedAdButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestRewardedAd();
            }
        });
    }

    // Requests and displays the banner ad
    private void RequestBannerAdd(){
        // If Ad already exists, remove it first before creating a new one
        DestroyBannerAd();

        FrameLayout adViewContainer = findViewById(R.id.banner_ad_container);

        bannerAd = new AdView(this);

        // Always Use the test ad id when testing.
        bannerAd.setAdUnitId("ca-app-pub-3940256099942544/9214589741");

        bannerAd.setAdSize(AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(this, 360));

        adViewContainer.removeAllViews();
        adViewContainer.addView(bannerAd);

        AdRequest adRequest = new AdRequest.Builder().build();

        // Request the ad.
        bannerAd.loadAd(adRequest);
    }

    // Destroys the banner ad.
    private void DestroyBannerAd(){
        if(bannerAd != null){
            if (bannerAd.getParent() instanceof ViewGroup) {
                ((ViewGroup) bannerAd.getParent()).removeView(bannerAd);
            }
            bannerAd.destroy();
            bannerAd = null;
        }
    }

    private void RequestInterstitialAd(){
        // If Ad already exists, remove it first before creating a new one.
        DestroyInterstitialAd();

        AdRequest adRequest = new AdRequest.Builder().build();

        // Always Use the test ad id when testing.
        InterstitialAd.load(this, "ca-app-pub-3940256099942544/1033173712", adRequest, new InterstitialAdLoadCallback() {

            // Callback that is called when it's loaded.
            @Override
            public void onAdLoaded(@NonNull InterstitialAd interstitialAd){
                MainActivity.this.interstitialAd = interstitialAd;

                MainActivity.this.interstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {

                    // Callback called when ad is dismissed.
                    @Override
                    public void onAdDismissedFullScreenContent() {
                        super.onAdDismissedFullScreenContent();

                        Log.d(TAG, "Ad was dismissed");

                        // Destroy the ad when dismissed by the user.
                        DestroyInterstitialAd();
                    }

                    // Callback called when ad failed show.
                    @Override
                    public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                        super.onAdFailedToShowFullScreenContent(adError);

                        Log.d(TAG, "Failed to show ad");

                        // Destroy the ad when loading fails.
                        DestroyInterstitialAd();
                    }
                });

                // Show the interstitial ad
                MainActivity.this.interstitialAd.show(MainActivity.this);

                Log.i(TAG, "Interstitial ad loaded");
            }

            // Callback that is called when ad fails to load.
            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                super.onAdFailedToLoad(loadAdError);

                Log.d(TAG, "Failed to load interstitial ad: " + loadAdError.toString());

                // Destroy the ad when it fails to load
                DestroyInterstitialAd();
            }
        });
    }

    // Destroys the interstitial ad.
    private void DestroyInterstitialAd(){
        interstitialAd = null;
    }

    // Requests and displays the native ad.
    private void RequestNativeAd(){
        // If Ad already exists, remove it first before creating a new one.
        DestroyNativeAd();

        // Always Use the test ad id when testing.
        AdLoader adLoader = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110").forNativeAd(new NativeAd.OnNativeAdLoadedListener() {

            // Callback that is called when it's loaded.
            @Override
            public void onNativeAdLoaded(@NonNull NativeAd nativeAd) {
                Log.d(TAG, "Native ad loaded.");

                // If callback occurs after native ad is destroyed.
                if (isDestroyed()) {
                    DestroyNativeAd();
                    return;
                }

                MainActivity.this.nativeAd = nativeAd;

                ViewGroup parent = findViewById(R.id.native_ad_container);

                NativeAdView adView = (NativeAdView) getLayoutInflater().inflate(R.layout.native_ad_layout, null);

                // Set the TextView's text.
                if(nativeAd.getHeadline() != null){
                    TextView headLineText = adView.findViewById(R.id.native_ad_headline);
                    headLineText.setText(nativeAd.getHeadline());
                    adView.setHeadlineView(headLineText);
                }

                adView.setNativeAd(nativeAd);
                parent.removeAllViews();

                parent.addView(adView);
            }
        }).withAdListener(new AdListener() {

            // Callback that's called when ad fails to load.
            @Override
            public void onAdFailedToLoad(LoadAdError adError) {
                Log.e(TAG, "Failed to load native add: " + adError.getMessage());

                DestroyNativeAd();
            }
        }).build();

        // Load the ad
        adLoader.loadAd(new AdRequest.Builder().build());
    }

    // Destroys the native ad.
    private void DestroyNativeAd(){
        if(nativeAd != null){
            nativeAd.destroy();
        }
    }

    // Requests and displays the rewarded ad.
    private void RequestRewardedAd(){
        // If Ad already exists, remove it first before creating a new one.
        DestroyRewardedAd();

        AdRequest adRequest = new AdRequest.Builder().build();

        // Always Use the test ad id when testing.
        RewardedAd.load(this, "ca-app-pub-3940256099942544/5224354917", adRequest, new RewardedAdLoadCallback() {

            // Callback that's called when ad fails to load.
            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                Log.d(TAG, "Failed to load rewarded ad: " + loadAdError.toString());

                DestroyRewardedAd();
            }

            // Callback that is called when it's loaded.
            @Override
            public void onAdLoaded(@NonNull RewardedAd ad) {
                Log.d(TAG, "Rewarded ad was loaded.");

                rewardedAd = ad;

                Activity activityContext = MainActivity.this;

                // show the ad.
                rewardedAd.show(activityContext, new OnUserEarnedRewardListener() {

                    // Callback called when the user receives the reward.
                    @Override
                    public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
                        Log.d(TAG, "The user earned the reward.");

                        int rewardAmount = rewardItem.getAmount();
                        String rewardType = rewardItem.getType();

                        Toast.makeText(activityContext, "The user earned the reward: " + rewardAmount + " " + rewardType, Toast.LENGTH_LONG).show();
                    }
                });

                rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {

                    // Callback called when ad is dismissed.
                    @Override
                    public void onAdDismissedFullScreenContent() {
                        Log.d(TAG, "Ad dismissed fullscreen content.");

                        DestroyRewardedAd();
                    }

                    // Callback called when ad failed to show.
                    @Override
                    public void onAdFailedToShowFullScreenContent(AdError adError) {
                        Log.e(TAG, "Ad failed to show fullscreen content.");

                        DestroyRewardedAd();
                    }
                });

            }
        });
    }

    // Destroys the rewarded ad.
    private void DestroyRewardedAd(){
        rewardedAd = null;
    }
}

Real Ads

You’ve seen in this blog how to display test ads. For real ads, you will need to create an Admob account https://admob.google.com/home/, which is a Google platform that allows developers to create and manage ad units. Then, you will simply copy the real ad ids from your account and replace the test ad ids. You will also have to copy the app id from your account and replace the test app id in the AndroidManifest.xml.

Privacy Considerations

When implementing ads in your app, you need to be aware of some privacy issues. Many ad networks collect user data to serve personalized ads, i.e. ads that are tailored to individual users based on their online activity, interests, and demographic information. To reduce data collection, you can serve only non-personalized ads, meaning ads not based on individual user data, such as browsing history or interests. Disabling personalized ads is outside of the scope of this blog, so check how you can do it from your Admob account or from inside the app itself. 

Useful Links

Here are a few links to Google’s documentation that will help you follow the guidelines and optimize your ads:

Conclusion

Ads are a great way to monetize your app, and fairly easy to implement on Android. While generating revenue is crucial, so is user experience. Make sure your ads are not intrusive and do not degrade user experience. If you use interstitial ads, be mindful about when to show the them to avoid frustrating users. Finally, always review the privacy compliance of your app. If you enjoyed this blog, then please checkout our apps and products below. 

We Need Your Help!

Please check out our apps and games, we also have a few Unity icon packs in the Unity Asset Store if you need them for your game or app. Your support is very much appreciated!