Menu Close

How to integrate Google Play Games Services and Admob in libGDX using Kotlin | Android | #6

The Google Play Games Services was one of the most difficult API I have ever integrated in libGDX, for Android and iOS (Multi-OS Engine – RoboVM was closed). LibGDX has a official tutorial collection here. Also the BaseGameUtils sample project on Github can be used for help. In my case I could not get into the idea of integrating another project (too much stuff I do not need), so I figured out how to interface with platform specific code. The basic idea is to write a simple interface with the needed methods and put it into the core-part of your game. Then you write implementations of this interface for each target (Android / iOS) and set this implementation in your core module.

Our interface for the core project

interface GameEventListener {
    fun login()
    fun displayLeaderBoard()
    fun showAd()
    fun hideAd()
    fun submitScore()
    fun showInterstitialAd()
    fun loadHighScore()
}

As you can see in my Splinter Sweets example app on Github, I use a GameManager class as a singleton, to manage things like the game timer or removing and adding bodies. In this class we set the GameEventListener:

var listener: GameEventListener? = null
    @Synchronized get

The Listener is explicitely declared as a nullable object, which means that if you do not set this listener, the application will not throw a NullPointerException, which makes sense if you target desktop / web or for non-release builds.

So if we want to show the Admob interstitial ad (make it visible to the user), we just need to call either of the following:

GameManager.listener?.showInterstitialAd() // if we do not want a NullPointerException
GameManager.listener!!.showInterstitialAd() // if we want a NullPointerException

The Android implementation

The Android part was easy, compared to the iOS part. Basically, follow the official instructions to get the newest information. At first, you have to add the dependencies to your android/build.gradle file:

dependencies {
    classpath 'com.google.gms:google-services:3.0.0'
    compile 'com.google.android.gms:play-services-games:9.6.1'
}

Then we have to write a implementation of the GameEventListener interface, and name it AndroidGameEventListener:

class AndroidGameEventListener : GameEventListener {
    private lateinit var context: Context
    private val SHOW = 1
    private val HIDE = 0
    private var adView: AdView? = null
    private var interstitialAd: InterstitialAd
    private var handler: Handler? = null
...
}

In the constructor we initialize things like the ad related stuff. When the user closed the interstitial ad, we want to request a new one, that is why we use the requestNewInterstitial() method. When the 50 seconds game time is over, a game over page is shown to the user. While that, the banner ad should be hidden, because the user might want to make a screenshot, that is why we use an Android Handler.

constructor(adView: AdView?, context: Context) {
    this.adView = adView
    this.context = context
    interstitialAd = InterstitialAd(context)
    interstitialAd.adUnitId = GameSettings.ADMOB_INTERSTITIAL_ID
    interstitialAd.adListener = object : AdListener() {
        override fun onAdClosed() {
            requestNewInterstitial()
            super.onAdClosed()
        }
    }
    requestNewInterstitial()
    handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                HIDE -> {
                    adView?.visibility = View.GONE
                }
                SHOW -> {
                    adView?.visibility = View.VISIBLE
                }
            }
        }
    }
}
private fun requestNewInterstitial() {
    val adRequestBuilder = AdRequest.Builder()
    adRequestBuilder.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
    interstitialAd.loadAd(adRequestBuilder.build())
}

Initializing the Google API Client

At first, we need to initialize the GoogleApiClient, using the Android context and a listener to handle the connection failed and other callbacks:

val playServiceListener = PlayServiceListener()
mGoogleApiClient = GoogleApiClient.Builder(context!!)
        .addConnectionCallbacks(playServiceListener)
        .addOnConnectionFailedListener(playServiceListener)
        .addApi(Games.API)
        .addScope(Games.SCOPE_GAMES)
        .setViewForPopups(view)
        .build()

And the PlayServiceListener:

private class PlayServiceListener : GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    
    override fun onConnected(bundle: Bundle?) {
        Toast.makeText(context, R.string.login_succeed, Toast.LENGTH_SHORT).show()
        GameManager.listener?.loadHighScore()
    }
    override fun onConnectionSuspended(i: Int) {
        // Attempt to reconnect
        mGoogleApiClient?.connect()
    }
    override fun onConnectionFailed(connectionResult: ConnectionResult) {
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return
        } else if (connectionResult.hasResolution()) {
            try {
                mResolvingError = true
                connectionResult.startResolutionForResult(context as Activity, REQUEST_RESOLVE_ERROR)
            } catch (e: IntentSender.SendIntentException) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient?.connect()
            }
        } else {
            // Show dialog using GoogleApiAvailability.getErrorDialog()
            Toast.makeText(context, R.string.login_failed, Toast.LENGTH_SHORT).show()
            mResolvingError = true
        }
    }
}

Submitting the high score

Games.Leaderboards.submitScore(mGoogleApiClient, GameSettings.PLAY_SERVICE_LEADERBOARD, GameManager.score.toLong())

Displaying the Leaderboard

fun callLeaderBoard(targetActivity: Activity) {
   targetActivity.startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
        GameSettings.PLAY_SERVICE_LEADERBOARD), REQUEST_LEADERBOARD)
}

Note: To make this post not too big, I have let out some methods, for example to check if the user is logged in and connected to the Google Play Service.

Leave a Reply

Your email address will not be published. Required fields are marked *

3 × one =

This site uses Akismet to reduce spam. Learn how your comment data is processed.