LibGDX Tutorial - Setup admob ads (How To 13)

Edit:: As of 18/05/2019, the latest version of google ads services has been changed and the post has been updated to latest version. If you still encounter any problems visit this post.

Original Post

Heeeello everyone! This tutorial will be the last of the LibGDX tutorial series and i really hope that you leaned and loved the procedure of developing a fully working game from scratch. As i promised you, in today's tutorial i will show you how to implement admob ads in our game.

You don't need to make an admob account yet, because we are going to use test ads (recommended from admob if a game isn't published) which can be used by everyone for debugging purposes. If you decide to publish a game though, then you need to create an admob account and follow a procedure that you can easily find with a quick search on Google.

Setting up admob ads with LibGDX

First of all, go to the " Gradle Scripts " (below our core folder) and open the  " build.gradle (Project: Getest) " file. Find the dependencies which look like this;

// Rest of the code

project(":android") {
    apply plugin: "android"
    configurations { natives }

    dependencies {
        implementation project(":core")
        implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"

        // Rest of the code

     }
    
    // Rest of the code
}

After the line

implementation project(":core")

paste this code;

implementation 'com.google.android.gms:play-services-ads:17.2.0'

The file should look like this;

buildscript {
    

    repositories {
        mavenLocal()
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'        
    }
}

allprojects {
    apply plugin: "eclipse"
    apply plugin: "idea"
    version = '1.0'
    ext {
        appName = "getest"
        gdxVersion = '1.9.9'
        roboVMVersion = '2.3.5'
        box2DLightsVersion = '1.4'
        ashleyVersion = '1.7.0'
        aiVersion = '1.8.0'
    }

    repositories {
        mavenLocal()
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
        maven { url "https://oss.sonatype.org/content/repositories/releases/" }
        maven { url "https://maven.google.com/"}
    }
}

project(":android") {
    apply plugin: "android"
    configurations { natives }

    dependencies {
        implementation project(":core")
        implementation 'com.google.android.gms:play-services-ads:17.2.0'
        implementation 'com.android.support:multidex:1.0.3'
        implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
        implementation "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
        natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi"
        natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi-v7a"
        natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-arm64-v8a"
        natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86"
        natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86_64"
        implementation "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
        implementation "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
        implementation "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
        natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi"
        natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a"
        natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a"
        natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86"
        natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86_64"
        implementation "com.badlogicgames.gdx:gdx-bullet:$gdxVersion"
        natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-armeabi"
        natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-armeabi-v7a"
        natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-arm64-v8a"
        natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-x86"
        natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-x86_64"
        implementation "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion"
     }
}

project(":core") {
    apply plugin: "java"

    dependencies {
        implementation "com.badlogicgames.gdx:gdx:$gdxVersion"
        implementation "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
        implementation "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
        implementation "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
        implementation "com.badlogicgames.gdx:gdx-bullet:$gdxVersion"
        implementation "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion" 
   }
}

tasks.eclipse.doLast {
    delete ".project"
}

 We added these lines:

        implementation 'com.google.android.gms:play-services-ads:17.2.0'
        implementation 'com.android.support:multidex:1.0.3'

for the google ads and multidex (the multidex is important for the latest update of Android Studio and has nothing to do with the ads), also this line

maven { url "https://maven.google.com/"}

for the google ads as well and finally we changed the

        google()
        jcenter()

" jcenter() " function's position to be underneath the " google() " function.

Then, open  " build.gradle (Module: Android) ", find the minSdkVersion and change it from 9 to 14. After you are done, you must sync your project (a sync option will pop up at the top of  Android Studio, so just click it).

// Rest of the code

defaultConfig {
    applicationId "com.getest.game"
    minSdkVersion 14
    targetSdkVersion 27
    versionCode 1
    versionName "1.0"
}

// Rest of the code


The file should look like this;

android {
    buildToolsVersion "28.0.3"
    compileSdkVersion 27
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }

    }
    packagingOptions {
        exclude 'META-INF/robovm/ios/robovm.xml'
    }
    defaultConfig {
        applicationId "com.getest.game"
        minSdkVersion 14
        targetSdkVersion 27
        multiDexEnabled true
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


// called every time gradle gets executed, takes the native dependencies of// the natives configuration, and extracts them to the proper libs/ folders// so they get packed with the APK.
task copyAndroidNatives() { 
    file("libs/armeabi/").mkdirs();
    file("libs/armeabi-v7a/").mkdirs();
    file("libs/arm64-v8a/").mkdirs();
    file("libs/x86_64/").mkdirs();
    file("libs/x86/").mkdirs();

    configurations.natives.files.each { jar ->
        def outputDir = null
        if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
        if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")        
        if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
        if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64")
        if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
        if(outputDir != null) {
            copy {
                from zipTree(jar)
                into outputDir
                include "*.so"
            }
        }
    }
}

task run(type: Exec) {
    def path
    def localProperties = project.file("../local.properties")
    if (localProperties.exists()) {
        Properties properties = new Properties()
        localProperties.withInputStream { instr ->
            properties.load(instr)
        }
        def sdkDir = properties.getProperty('sdk.dir')
        if (sdkDir) {
            path = sdkDir
        } else {
            path = "$System.env.ANDROID_HOME"
        }
    } else {
        path = "$System.env.ANDROID_HOME"
    }

    def adb = path + "/platform-tools/adb"
    commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.getest.game/com.getest.game.AndroidLauncher'
}

// sets up the Android Eclipse project, using the old Ant based build.
eclipse {
    // need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin    // ignores any nodes added in classpath.file.withXml
    sourceSets {
        main {
            java.srcDirs "src", 'gen'
        }
    }

    jdt {
        sourceCompatibility = 1.6 
        targetCompatibility = 1.6
    }

    classpath {
        plusConfigurations += [ project.configurations.compile ]        
        containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
    }

    project {
        name = appName + "-android"
        natures 'com.android.ide.eclipse.adt.AndroidNature'
        buildCommands.clear();
        buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
        buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
        buildCommand "org.eclipse.jdt.core.javabuilder"
        buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
    }
}

// sets up the Android Idea project, using the old Ant based build.
idea {
    module {
        sourceDirs += file("src");
        scopes = [ COMPILE: [plus:[project.configurations.compile]]]        

        iml {
            withXml {
                def node = it.asNode()
                def builder = NodeBuilder.newInstance();
                builder.current = node;
                builder.component(name: "FacetManager") {
                    facet(type: "android", name: "Android") {
                        configuration {
                            option(name: "UPDATE_PROPERTY_FILES", value:"true")
                        }
                    }
                }
            }
        }
    }
}

We basically added the " multiDexEnabled true " line which is important for an error - free build, as i mentioned before.

Go to the " AndroidManifest.xml ", in which we must add internet permision, an ad activity.

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/GdxTheme" >
        <activity
            android:name="com.getest.game.AndroidLauncher"
            android:label="@string/app_name"
            android:screenOrientation="landscape"
            android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.google.android.gms.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
        <meta-data android:name="com.google.android.gms.ads.AD_MANAGER_APP"
            android:value="true" />
    </application>
</manifest>

Note that in order to display your real ads, if you have an admob account and a published game, then you have to change the following lines;

        <meta-data android:name="com.google.android.gms.ads.AD_MANAGER_APP"
            android:value="true" />

to

     <meta-data android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="YOUR_ADMOB_APP_ID" />

where the ID of your app can be found in the Admob page after your log in with your account. If that's the case, you also have to change the " AndroidLauncher.java " in order to initialize the Mobile Ads SDK with your Admob app ID. This class now becomes;

 //Rest of the code
public void setupAds() { MobileAds.initialize(this, "YOUR_ADMOB_APP_ID"); bannerAd = new AdView(this); bannerAd.setVisibility(View.INVISIBLE); bannerAd.setBackgroundColor(0xff000000); // black bannerAd.setAdUnitId(BANNER_AD_UNIT_ID); bannerAd.setAdSize(AdSize.SMART_BANNER); interstitialAd = new InterstitialAd(this); interstitialAd.setAdUnitId(INTERSTITIAL_AD_UNIT_ID); rewardedVideoAd= MobileAds.getRewardedVideoAdInstance(this); AdRequest.Builder builder = new AdRequest.Builder(); AdRequest ad = builder.build(); interstitialAd.loadAd(ad); loadRewardedVideoAd(); } // Rest of the code

Until now, we have done nothing special. We just did all the procedural stuff. Next, create a package (as usual in our core folder) with the name " ads " and inside create a java class interface (just like the way we created an enum but this time you must choose interface) with the name " AdsController " and paste the code below;

package com.getest.game.ads;

public interface AdsController {
    public boolean isWifiConnected();
    public boolean isInterstitialLoaded();
    public void showBannerAd();
    public void hideBannerAd();
    public void showInterstitialAd(Runnable then);
}

We now have to modify the " AndroidLauncher.java " class and add the functions which we will call in order for our ads to be shown.

package com.getest.game;

import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.getest.game.ads.AdsController;
import com.getest.game.game.GeTest;
import com.google.android.gms.ads.AdListener;
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.InterstitialAd;

public class AndroidLauncher extends AndroidApplication implements AdsController {

   private static final String BANNER_AD_UNIT_ID = "ca-app-pub-3940256099942544/6300978111";
   private static final String INTERSTITIAL_AD_UNIT_ID = "ca-app-pub-3940256099942544/1033173712";
   AdView bannerAd;
   InterstitialAd interstitialAd;

   @Override
   protected void onCreate (Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);
      AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
      //initialize(new BlackDodger(), config);
      View gameView = initializeForView(new GeTest(this), config);
      setupAds();
      RelativeLayout layout = new RelativeLayout(this);
      layout.addView(gameView, ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT);
      RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
      params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
      layout.addView(bannerAd, params);
      setContentView(layout);
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
         hideVirtualButtons();
      }
   }

   public void setupAds() {
      bannerAd = new AdView(this);
      bannerAd.setVisibility(View.INVISIBLE);
      bannerAd.setBackgroundColor(0xff000000); // black
      bannerAd.setAdUnitId(BANNER_AD_UNIT_ID);
      bannerAd.setAdSize(AdSize.SMART_BANNER);
      interstitialAd = new InterstitialAd(this);
      interstitialAd.setAdUnitId(INTERSTITIAL_AD_UNIT_ID);
      AdRequest.Builder builder = new AdRequest.Builder();
      AdRequest ad = builder.build();
      interstitialAd.loadAd(ad);
   }

   @Override
   public boolean isWifiConnected() {
      ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);      NetworkInfo ni = cm.getActiveNetworkInfo();
      return (ni != null && ni.isConnected());
   }

   @Override
   public boolean isInterstitialLoaded(){
      return interstitialAd.isLoaded();
   }

   @Override
   public void showBannerAd() {
      runOnUiThread(new Runnable() {
         @Override
         public void run() {
            bannerAd.setVisibility(View.VISIBLE);
            AdRequest.Builder builder = new AdRequest.Builder();
            AdRequest ad = builder.build();
            bannerAd.loadAd(ad);
         }
      });
   }

   @Override
   public void hideBannerAd() {
      runOnUiThread(new Runnable() {
         @Override
         public void run() {
            bannerAd.setVisibility(View.INVISIBLE);
         }
      });
   }

   @Override
   public void showInterstitialAd(final Runnable then) {
      runOnUiThread(new Runnable() {
         @Override
         public void run() {
            if (then != null) {
               interstitialAd.setAdListener(new AdListener() {
                  @Override
                  public void onAdClosed() {
                     Gdx.app.postRunnable(then);
                     AdRequest.Builder builder = new AdRequest.Builder();
                     AdRequest ad = builder.build();
                     interstitialAd.loadAd(ad);
                  }
               });
            }
            if (interstitialAd.isLoaded()) {
               interstitialAd.show();
            }
            else{
               AdRequest.Builder builder = new AdRequest.Builder();
               AdRequest ad = builder.build();
               interstitialAd.loadAd(ad);
               Gdx.app.postRunnable(then);
            }

         }
      });
   }

  // Rest of the code

}

We just created a new view for our game (because we will also show ads) and we defined the functions that call the banner and the interstitial ads. Because we also need a function that informs us for the Internet connectivity (we must show ads and make requests for them only if we are connected to the Internet), we created the isWifiConnected() function. 

" Where do we want to show ads? "

The decision is all yours, but for the purpose of this tutorial, we will add the banner ad at the top of the game screen and show the interstitial ad each time an enemy hits us. For that, it is necessary to pass the adsController instance all the way from the " AndroidLauncher " to our " GameStage ".

We first modify the " GeTest " class.

package com.getest.game.game;

import com.badlogic.gdx.Game;
import com.getest.game.ads.AdsController;
import com.getest.game.screens.SplashScreen;

public class GeTest extends Game {

   private AdsController adsController;

   public GeTest(AdsController adsController){
      this.adsController = adsController;
   }

   public void create() {
      setScreen(new SplashScreen(adsController));
   }

   public void render() {
      super.render();
   }
}

Then we modify the " SplashScreen " and " MainMenuScreen ".

package com.getest.game.screens;

// Imports...

public class SplashScreen implements Screen {

    private Texture splashtexture;
    private Image splashimage;
    private Stage splashstage; 
    private float WIDTH,HEIGHT;
    private AssetMan manager;
    private AdsController adsController;
    private boolean startLoading = false;

    public SplashScreen(AdsController adsController) {
        manager = new AssetMan();
        this.adsController = adsController;
    }

    // Rest of the code

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        splashstage.act();
        splashstage.draw();
        if(manager.update() && startLoading){
            ((Game)Gdx.app.getApplicationListener()).setScreen(new MainMenuScreen(manager,adsController));
        }
    }

     // Rest of the code
}

and

package com.getest.game.screens;

// Imports...

public class MainMenuScreen implements Screen {

    private Stage mainmenuStage;
    private Skin mainmenuSkinPlay;
    private ImageButton mainmenuimagebuttonPlay;
    private Table mainmenuTablePlay;
    private Texture mainmenuTexture;
    private Image mainmenuImage;
    private float WIDTH,HEIGHT;
    private AssetMan manager;
    private AdsController adsController;

    public MainMenuScreen(AssetMan manager, AdsController adsController) {
        this.manager = manager;
        this.adsController = adsController;
    }

    @Override
    public void show() {
        WIDTH = 1280;
        HEIGHT = 720;
        mainmenuTexture = manager.getMainMenu();
        mainmenuTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
        mainmenuImage = new Image(mainmenuTexture);
        mainmenuImage.setSize(1280,720);
        mainmenuStage = new Stage(new FitViewport(WIDTH,HEIGHT, new AndroidCamera(WIDTH,HEIGHT)));
        mainmenuTablePlay = new Table();
        mainmenuSkinPlay = manager.getPlay();
        mainmenuimagebuttonPlay = new ImageButton(mainmenuSkinPlay);
        mainmenuTablePlay.bottom().add(mainmenuimagebuttonPlay).size( 152F, 164F).padBottom(20F);
        mainmenuStage.addActor(mainmenuImage);
        mainmenuStage.addActor(mainmenuTablePlay);
        Gdx.input.setInputProcessor(mainmenuStage);
        mainmenuTablePlay.addAction(Actions.sequence(Actions.moveBy(0.0F, -250F), Actions.delay(1.0F), Actions.moveBy(0.0F, 250F, 1.0F, Interpolation.swing)));
        mainmenuImage.addAction(Actions.sequence(Actions.alpha(0.0F), Actions.fadeIn(1.0F)));

        mainmenuimagebuttonPlay.addListener(new ClickListener() {
            public void clicked(InputEvent event, float x, float y) {

                ((Game)Gdx.app.getApplicationListener()).setScreen(new GameScreen(manager, adsController));
            }
        }); 
   }
   
   // Rest of the code

}

Patience! We are almost there. What's left is to modify the " GameScreen ";

package com.getest.game.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.getest.game.ads.AdsController;
import com.getest.game.data.AssetMan;
import com.getest.game.stages.GameStage;

public class GameScreen implements Screen {

    private GameStage gameStage;
    private AssetMan manager;
    private AdsController adsController;

    public GameScreen(AssetMan manager, AdsController adsController) {
        this.manager = manager;
        this.adsController = adsController;
    }

    @Override
    public void show() {
        gameStage = new GameStage(manager, adsController);
    }

   // Rest of the code

}

and then the " GameStage ", to actually call the functions that create the banner and the interstitial ads.

package com.getest.game.stages;

// Imports...

public class GameStage extends Stage implements ContactListener{

    private float accumulator, TIME_STEP, alpha;
    private Box2DDebugRenderer renderer;
    private WorldMisc wrl;
    private World world;
    private GroundActor ground;
    private LeftWallActor leftWall;
    private RightWallActor rightWall;
    private HeroActor hero;
    private Boolean right = false, left = false;
    private Skin leftButtonSkin, rightButtonSkin, jumpButtonSkin, slideButtonSkin;
    private ImageButton leftButton, rightButton, jumpButton, slideButton;
    private Texture backGroundTexture;
    private Image backGroundImage;
    private Timer timerEnemy = new Timer();
    private AssetMan manager;
    private AdsController adsController;

    public GameStage(AssetMan manager, AdsController adsController){

        super(new MyViewport(16f, 9f,
                new AndroidCamera(16f, 9f)));
        accumulator = 0.0F;
        TIME_STEP = 1/300F; // Recomended by libgdx
        this.manager = manager;
        this.adsController = adsController;
        setupWorld();
        if(adsController.isWifiConnected())
            adsController.showBannerAd();
    }

    // Rest of the code

    @Override
    public void beginContact(Contact contact) {
        Body a = contact.getFixtureA().getBody();
        Body b = contact.getFixtureB().getBody();

        if((BodyMisc.bodyIsHero(a) && (BodyMisc.bodyIsGround(b) )) || ((BodyMisc.bodyIsGround(a) && (BodyMisc.bodyIsHero(b))))) {
            hero.landed();
        }

        if(BodyMisc.bodyIsHero(a) && BodyMisc.bodyIsEnemy(b) || BodyMisc.bodyIsHero(b) && BodyMisc.bodyIsEnemy(a)){
            adsController.showInterstitialAd(new Runnable() {
                @Override
                public void run() {
                }
            });
        }
    }

    @Override
    public void endContact(Contact contact) {

    }

    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {

    }

    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {

    }
}

Run the complete version of the game and make sure that you are connected on the Internet.


Finally, after almost 2 months the tutorials have come to an end. If you need any help or you want me to create more tutorials then all that you have to do is simple; Ask me in the comments or send me an e - mail!

Comments

  1. Thanks for creating this tutorial. Exactly what I was looking for. I was trying to implement ads in my own game so I have not followed the whole game step by step, but I have found some issues that I don't think is related to that.

    After editing the AndroidManifest.xml I see errors:
    "Error: No resource found that matches the given name (at 'value' with value '@integer/google_play_services_version')."

    Should that be found in some dependency? Previously I think that was added under res/ in some xml file.

    That might also be related to the problem that the classes under com.google.android.gms.ads.* does not seem to be found either. A play services .aar file appears under Gradle dependencies, but the classes in the jar files in the .aar file does not appear on the class path (using eclipse so I exchanged "sync option" with gradle refresh all).

    Also you are using version 11.04 which seems to be quite old. What is the reason for that?

    I found it hard to simply go back to previous tutorials, no previous or next... Maybe I just missed something in some other post?

    Anyway, some clarification would be great if you can!

    ReplyDelete
    Replies
    1. Thank you for your kind words. I will try to answer your questions and then provide you with a possible fix.

      1) There is not a specific reason for using 11.0.4 version, you can always use the latest one and it actually is preferable.

      2)This tutorial is independent from the previous (well, to actually add the ads inside the game world obviously needs the previous tutorials).

      Now for the possible solution. If you read the tutorial carefully you will see that you need to add this line in the dependencies;

      compile 'com.google.android.gms:play-services-ads:11.0.4'

      That also justifies the reason why the classes are not found. All the other problems that you may occur, probably have to do with the fact that you are using Eclipse.

      Hope that this will fix your problem. For any further explanation or if the problem persists, please don't hesitate to ask again!

      Delete
    2. Thanks for the quick feedback.

      After reading it I dug further and it looks like Eclipse together with ADT simply does not know how to handle .aar files. I could look at the contents of the .aar files and see the jars and even classes directly in Eclipse and yet Eclipse could not understand what to do with it... That almost certainly explains the problem with the google_play_services_version as well. It looks like some people already have gone through the pain of converting the dependency to an Eclipse project that one can add as a dependency in eclipse setting instead of line in the build.gradle. Not as elegant, but it is better than an elegant solution that isn't working.

      Have not tested yet, but for anybody else with same issues this might be a good start:
      https://github.com/dandar3/android-google-play-services-ads-lite

      Or I have to change to Android Studio, that I think I saw you are using.

      Delete
    3. I researched the topic myself too. Those issues are always kinda complicated. If you decide to go through debugging this problem then i am sure that you will learn a lot our of this!

      In any case, i trully suggest you to move from Eclipse to Android Studio as it will make your life easier!

      P.S; Yes, i am using Android Studio!

      Delete
  2. Can you please post a tutorial on a space game shooter game please?

    ReplyDelete
    Replies
    1. Hello! If you follow the tutorials from the beginning then in the end, you will have gained the knowledge that is required to create your own unique game.

      In any case, i will try to make a space shooter game and share the tutorials with you when i find the time!

      This might take some time though, so i suggest that you try to create your own space shooter game in the meantime.

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. I was getting an error with this line in AndroidManifest.xml: `android:name="com.google.android.gms.ads.AdActivity"`

    I moved the dependency `implementation 'com.google.android.gms:play-services-ads:20.4.0'` (Note the updated version.) from build.gradle(Project) to build.gradle(Module: MyGame.android). The error went away. I'll try to complete the tutorial in the next 24 hours.

    Also, jcenter() is deprecated. As I understand, most of that functionality is now available with maven().

    ReplyDelete
  5. I had to downgrade my `implementation 'com.google.android.gms:play-services-ads:` back to 17.2.0 because there was a lot of deprecation in 20.4.0 and I don't yet have the knowledge and skill to adapt to the new version. If you could update this page again, it might be helpful to the next person.

    ReplyDelete
    Replies
    1. When I find the time I will update both the LibGDX and the google ads versions to the latest!

      Delete
  6. Please fix the typo in...ads.APPLCATION_ID.... Took me a while to figure out :D Thanks for this tutorial !

    ReplyDelete

Post a Comment