• Sponsored Links

libGDX Example Code : Implementing Google Play Services Leader Boards in LibGDX

Share this :

libGDX Example Code : Implementing Google Play Services Leader Boards in LibGDX

We have seen in previous sections how easy it is to make a game using libGDX but once we are done with a game and our game has High Scores, to make our game more exciting and competitive we would want to implement LeaderBoards  or High-Scores Screen to our Game .

Google Play Services have various ways by which  we can add fun to our game for example we can add 

  1. Achievements 
  2. Events
  3. Leaderboards

In this tutorial i will focus on how to implement Leaderboards in your android game made in libGDX   Events and Achievements can also be implemented in similar fashion .

Google  has provided a detailed documentations on the implementation of the same in its support page but that's a generic android documentation and not specific for libGDX

Google documentation on implementing Leaderboards in android Game

Below are some already available Tutorials on implementing Leader boards at Google Play Services and libGDX below ( I find most of them out of date and after reading for1 or 2 days i understood there is a issue and due to google update we cant do anything about it now )

http://fortheloss.org/tutorial-set-up-google-services-with-libgdx/

http://theinvader360.blogspot.in/2013/10/google-play-game-services-tutorial-example.html

How to setup Google Play Game Services in LibGDX using Android Studio

 

Below are some github repository with Open source code on the same

https://github.com/TheInvader360/libgdx-gameservices-tutorial

https://github.com/playgameservices/android-basic-samples

https://github.com/libgdx/libgdx/wiki/Google-Play-Games-Services-in-LibGDX

https://github.com/ahmetdenizyilmaz/connect

The issue with all those tutorials were that all those were out of date or there was something missing in each of them  , so plan to write this tutorial to help fellow libGDX developers .

I am dividing the implementation into 2 parts

Part 1 : Setting up of Leaderboards in Google Play Console

Part 2 : Implementation of Code using Google APIs in your libGDX program

I will be explaining all errors which I got while implementing this and will also provide the fix for that error to help you guys in case you get those error , if you don't get those errors just ignore and move to next step , if you get some new error , do a stackoverflow or google or mention in comment so i can help .

Part 1 : Setting up of Leaderboards in Google Play Console

If you wish to read googles documentation on this topic it can be read on below link

https://developers.google.com/games/services/console/enabling

Lets do it step by step

  1. Sign in to Google Play Console where you will see all of your games which you have published . use this link to sign in to google play console
    Signin In Google Play Console

    Signin In Google Play Console

  2. From the Google Play Game Console  , click on Game Services in left tab and then click add new Game button to add your game to Play Services
    Add New Game form

    Add New Game form

  3. A form will be opened 
    1. Enter name of the Game 
    2. Select "I don't use any Google APIs in my game yet" , if you have no idea about it yet
    3. Select Category
    4. Click Continue
  4. A game Details form will be opened
    1. Enter Display Name of the game
    2. Description of the game
    3. One High Resolution Icon
    4. One Feature Graphics
    5. Click Save
  5. Generate an OAuth 2.0 Client Id . This Step is most important , our game must have this OAuth 2.0 Client Id setup correctly in order to be authenticated and call to google play services .
    Linked App Screen

    Linked App Screen


    1. Click on linked app from left menu
    2. Enter Name of the app
    3. Package of the exact app which you have , this can be seen in your app manifest.xml at
      package="com.versionpb.game" 
    4. To use Google Play games services' real-time or turn-based multiplayer support, enable the appropriate multiplayer settings.
    5. Select whether or not to turn on Anti-Piracy.
    6. Click Save and Continue
  6. Create a Client ID
    1. When we clicked Save and Continue in Step 5 sub Step F , we will see a screen like below
      Authorize App

      Authorize App

    2. Click on Authorize your app button
    3. Now if your app is already live on play store google by it self will show you a SHA1 Certificate there , Let it be there but we need to add 2 more SHA Certificates here by adding 2 more apps . So for now click on Confirm
      Default SHA1 Certificate

      Default SHA1 Certificate

    4. Repeat Step 5 and Create another similar app .
    5. Repeat Step 6 but this time lets first create a new SHA1 certificate of the apk which we uploaded at play store . To Generate that .Execute below command where C:\Program Files\Java\jdk1.7.0_72\bin is the path where keytool utility is present according to your java installation and  D:\Java\libGdx\apk\keystore\android.jks is the path of your keystore which you generated when creating signed apk from Android studio
      1. C:\Program Files\Java\jdk1.7.0_72\bin>keytool -list -keystore D:\Java\libGdx\apk\keystore\android.jks
        Enter keystore password: Keystore type: JKS
        Keystore provider: SUN Your keystore contains 1 entry briskybird, Dec 9, 2017, PrivateKeyEntry,
        Certificate fingerprint (SHA1): 27:XX:XX:XX:XX:B2:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:BD:BF
    6. This time use this Certificate fingerprint in the SHA1 certificate and click confirm ( in this example i have added XX:XX as i dont want to tell you my exact certificate but it shouldn't look like XX:XX
    7. Repeat step 5 and 6 again i.e. create another app and this time add a certificate for your debug app using below command . where C:\Users\<USERNAME>\.android\debug.keystore is a default path of your debug.keystore and password for debug keystore by default is android
      1. C:\Program Files\Java\jdk1.7.0_72\bin>keytool -list -keystore C:\Users\USER\.android\debug.keystore
    8. Click Confirm and we are done
  7. Lets Create a Leader Board
    1. Click on leaderboard from left menu
    2. Click Add new leaderboard
    3. Give Name to your leaderboard
    4. Click Save by selecting appropriate options
  8. Steps for configuration in Play console are done lets do now Code part
    Part 2 : Setting up of Leaderboards in Google Play Console

  1. Download the zip of following repository https://github.com/PaarthBatra/connect  
    Download Git Repository

    Download Git Repository

  2. Unzip the connect-master.zip and you will see a directory named connect-master
  3. Open your project in android studio where you want to implement Leaderboards
  4. Click on File --> New --> Import Module and select the path of BaseGameUtils directory under connect-master and click finish
    Importing BaseGameUtils

    Importing BaseGameUtils

  5. You will now see BaseGameUtils as another project as library with your other libGDX projects like desktop,core and android
    BaseGameUtils Imported

    BaseGameUtils Imported

  6. Open AndroidManifest.xml  from android-->Manifest directory and add following 2 lines
    Addition Of Permissions AndroidManifest

    Addition Of Permissions AndroidManifest

    1. <uses-permission android:name="android.permission.INTERNET"/>
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    2. Also add below meta tag in your manifest file
    3. <meta-data
      android:name="com.google.android.gms.games.APP_ID"
      android:value="@string/app_id"/>
      <meta-data
      android:name="com.google.android.gms.version"
      android:value="@integer/google_play_services_version"/>
  7. Open your core project and create a new interface named PlayServices in it
    Creation Of PlayServices Interface

    Creation Of PlayServices Interface

  8. Write following code in this interface
    1. public interface PlayServices
      {
      public void onStartMethod();
      public void signIn();
      public void signOut();
      public void rateGame();
      public void unlockAchievement(String str);
      public void submitScore(String LeaderBoard,int highScore);
      public void submitLevel(int highLevel);
      public void showAchievement();
      public void showScore(String LeaderBoard);
      public void showLevel();
      public boolean isSignedIn();
      }
  9. Now Open your AndroidLauncher Class from android project and implement PlayServices there as below
    1. public class AndroidLauncher extends AndroidApplication implements AdHandler,PlayServices
  10. There will be errors because we have unimplemented methods which we created in this interface so lets generate implement methods right click --> Generate --> Implement Methods .
    Generate Implement Methods

    Generate Implement Methods

  11. Select All and now your errors will be gone  , we will add code to these  methods shortly
  12. Open the google Play services console which we created in steps 1 to 7 and open leader-board section and click on get Resources . Copy the code in the android tab
     Copy Resources From LeaderBoard

    Copy Resources From LeaderBoard

  13. Open file Strings.xml from android --> res -->values --> Strings.xml and paste all contents of this resources there . If you already have some data in your Strings.xml make sure you copy those resources too in the resources tag
  14. Lets create a GameHelper object in your Andoridlauncher .java
    game helper object

    game helper object

    1. private GameHelper gameHelper;
  15. Inside AndroidLauncher.java under onCreate Method add following code
    1. gameHelper = new GameHelper(this, GameHelper.CLIENT_GAMES);
      gameHelper.enableDebugLog(true);


      GameHelper.GameHelperListener gameHelperListener = new GameHelper.GameHelperListener() {
      @Override
      public void onSignInFailed() {
      }

      @Override
      public void onSignInSucceeded() {
      }
      };
  16. and just before finishing onCreate Method add following line
    1. gameHelper.setup(gameHelperListener);
  17. At this point you might see errors as android studio is unable to resolve GameHelper so lets import below statement
    1. import com.google.example.games.basegameutils.GameHelper;
  18. If there is still issues click on build --> rebuild . we will still get error  "Error:(20, 46) error: package com.google.example.games.basegameutils does not exist" , issue is that we haven't yet added the dependency to BaseGameUtils in gradle scripts .Lets add the dependency
  19. Open build.gradle of Module android and add following line in the end of file
    dependency to BaseGameUtils

    dependency to BaseGameUtils

    1. dependencies {
      compile project(path: ':BaseGameUtils')
      }
  20. sync gradle to build the project . In my case i got following error
    1. Error:Execution failed for task ':android:processDebugManifest'.
      > Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smaller than version 15 declared in library [BriskyBird:BaseGameUtils:1.0] D:\Java\libGdx\LeaderBoardTutorial\V1.6_10\BriskyBird\android\build\intermediates\exploded-aar\BriskyBird\BaseGameUtils\1.0\AndroidManifest.xml
      Suggestion: use tools:overrideLibrary="com.google.example.games.basegameutils" to force usage
    2. To fix this error i added com.google.example.games.basegameutils in AndroidManifest.xml under <uses-sdk tools:overrideLibrary tag as per below screenshot
      overrideLibrary Screenshot

      overrideLibrary Screenshot

  21. Either rebuild of click run button to build the project but this time in my case i got below error
    1. Error:Execution failed for task ':android:processDebugManifest'.
      > Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smaller than version 9 declared in library [com.google.android.gms:play-services-games:8.4.0] D:\Java\libGdx\LeaderBoardTutorial\V1.6_10\BriskyBird\android\build\intermediates\exploded-aar\com.google.android.gms\play-services-games\8.4.0\AndroidManifest.xml
      Suggestion: use tools:overrideLibrary="com.google.android.gms.games" to force usage
    2. To fix this i added com.google.android.gms.games in similar fashion as we added com.google.example.games.basegameutils in step 28 .
  22. On clicking rebuild i got many such errors to fix all of those , i had to add all below libraries in overrideLibrary Tag
    1. com.google.example.games.basegameutils,
      com.google.android.gms.games,
      com.google.android.gms.games.license,
      com.google.android.gms.base,
      com.google.android.gms.base.license,
      com.google.android.gms.tasks,
      com.google.android.gms.tasks.license,
      com.google.android.gms.drive,
      com.google.android.gms.drive.license,
      com.google.android.gms.plus,
      com.google.android.gms.plus.license,
      com.google.android.gms.auth,
      com.google.android.gms.auth.license,
      com.google.android.gms.auth.api,
      com.google.android.gms.auth.api.phone,
      com.google.android.gms.auth.api.phone.license
    2. Now I got below error
    3. Error:(105, 19) error: cannot access GoogleApiClient
      class file for com.google.android.gms.common.api.GoogleApiClient not found
    4. This is very obvious because we didnt add dependencies to google play games to gradle script, lets fix this
  23. Open Project gradle build script and under project android dependencies add below lines
    1. compile "com.google.android.gms:play-services-games:11.6.0"
      compile "com.google.android.gms:play-services-auth:11.6.0"
    2. In My case i also added below line becase i am using google ads as well
      compile "com.google.android.gms:play-services-ads:11.6.0" 
    3. Just make sure all these libraries should be of same versions i.e. in my case i am using 11.6.0 else we might get a lot of other unnecessary errors as well .
  24. On Running the project i got below error
    1. Error:Execution failed for task ':android:transformClassesWithDexForDebug'.
      > com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Android\Android Studio\jre\bin\java.exe'' finished with non-zero exit value 2
  25. To fix this lets add below line in gradle script of your android project
    multidexTrue

    multidexTrue


    multiDexEnabled true
  26. On Building and executing the project i this time got below error
    duplicate entry Error

    duplicate entry Error

    1. Error:Execution failed for task ':android:transformClassesWithJarMergingForDebug'.
      > com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: com/google/android/gms/internal/zzqx.class
    2. To fix this copy the class name i.e. zzqx.class and in your android studio go control n and paste this class name there . it will show all the occurrences of this class in it
    3. When We see this error clearly it shows that we have play-services-plus version 8.4.0 also imported somewehere in any library which is causing this issue , as i mentioned earlier its really important that we keep versions of all google libraries as same to prevent unnecessary errors .
    4. To fix this open gradle build file of the project and add below lines under project android
      zzqx ErrorFix

      zzqx ErrorFix

    5. configurations { natives
      all*.exclude group: 'com.google.android.gms', module: 'zzqx'
      }
    6. Below stackoverflow link gives idea about other issues which might be causing errors in your case .Have a look in case it isnt fixing the issue at your end
    7. https://stackoverflow.com/questions/26966843/java-util-zip-zipexception-duplicate-entry-during-packagealldebugclassesformult
    8. In my case also issue was still unresolved so i took a deeper look and understood that gradle build file for BaseGameUtils  project was using gms version 8.4.0 i.e. as below
    9. dependencies {
      // Set defaults so that BaseGameUtils can be used outside of BasicSamples
      if (!project.hasProperty('appcompat_library_version')) {
      ext.appcompat_library_version = '23.0.+'
      }
      if (!project.hasProperty('support_library_version')) {
      ext.support_library_version = '20.0.+'
      }
      if (!project.hasProperty('gms_library_version')) {
      ext.gms_library_version = '8.4.0'
      }
    10. Change this value to 11.6.0 . Sync gradle , clean ,rebuild and run and the app works .
  27.  you might not get above errors at all but i mentioned all errors so in case any of us who gets this error should be able to fix this easily . Difficult part is finish , lets go ahead and write code for our override methods in AndroidLauncher.java
  28. Open Android Launcher.java and create a variable as below , where CgkImfGK7LgbEAIQAQ is the leaderboard id the one which we have taken from google play console or the one which we have copied to the Strings.xml and is the value of leaderboard tag .
    1. private static final String leaderboard = "CgkImfGK7LgbEAIQAQ";
  29. Replace the implement methods of PlayServices interface by below methods , read comments for better understanding
    1. @Override
      protected void onStart() {
      super.onStart();
      gameHelper.onStart(this); // You will be logged in to google play services as soon as you open app , i,e on start
      }

      @Override
      public void onStartMethod() {
      super.onStart();
      gameHelper.onStart(this); // This is similar method but I am using this if i wish to login to google play services
      // from any other screen and not from splash screen of my code
      }

      @Override
      protected void onStop() {
      super.onStop();
      gameHelper.onStop();
      }

      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      gameHelper.onActivityResult(requestCode, resultCode, data);
      }

      @Override
      public void signIn() {
      try {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {

      gameHelper.beginUserInitiatedSignIn();

      }
      });
      } catch (Exception e) {

      }
      }

      @Override
      public void signOut() {
      try {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {

      gameHelper.signOut();
      }
      });
      } catch (Exception e) {

      }
      }

      @Override
      public void rateGame() {

      String str = "Your PlayStore Link";
      startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(str)));
      }

      @Override
      public void unlockAchievement(String str) {
      Games.Achievements.unlock(gameHelper.getApiClient(), str);
      }

      @Override
      public void submitScore(String LeaderBoard,int highScore) {
      if (isSignedIn()) {

      Games.Leaderboards.submitScore(gameHelper.getApiClient(), LeaderBoard, highScore);
      }
      else{
      System.out.println(" Not signin Yet ");
      }

      }



      @Override
      public void submitLevel(int highLevel) {
      if (isSignedIn()) {
      Games.Leaderboards.submitScore(gameHelper.getApiClient(),leaderboard, highLevel);
      }
      }

      @Override
      public void showAchievement() {
      if (isSignedIn()) {
      startActivityForResult(Games.Achievements.getAchievementsIntent(gameHelper.getApiClient()), 1);
      } else {
      signIn();
      }
      }

      @Override
      public void showScore(String leaderboard_Easy) {
      if (isSignedIn()) {
      startActivityForResult(Games.Leaderboards.getLeaderboardIntent(gameHelper.getApiClient(), leaderboard_Easy), 1);
      } else {
      signIn();
      }
      }



      @Override
      public void showLevel() {
      if (isSignedIn()) {
      startActivityForResult(Games.Leaderboards.getLeaderboardIntent(gameHelper.getApiClient(), leaderboard), 1);
      } else {
      signIn();
      }
      }
  30. Now , Everything is setup , We just need to call the methods in my core project according to my game . So lets say , i want to Call signIn method or lets say onStartethod in fro my MenuScreen . So i would first need an instance of this interface in this class , So inside Android Launcher.java call pass the object of PlayServices when initializing the game view as below
    1. View gameView = initializeForView(new BriskyBird(this,this), config);
    2. Here BriskyBird is my main project class name so I open it and change its constructor from
    3. public BriskyBird(AdHandler handler){
      this.handler = handler;

      }
    4. to
    5. public BriskyBird(AdHandler handler,PlayServices ply){
      this.handler = handler;
      this.ply = ply;
      }
    6. AdHandler is a similar interface for placing google AdMob on my game , code for this can also be added in PlayServices if you wish but for simplification i have kept it separate .
  31. In My project BriskyDemo as explained in the initial parts of this tutorial , i have a stack of States and all my screens extends Abstract class state , so to implement this from BriskyBird Class whenever i push a new state to gsm i pass the same ply object to it  as per below
    1. gsm.push(new MenuState(gsm,ply));
  32. Now inside Menu State we can call google play api's as per your own loagic
    1. if(ply.isSignedIn()) {
      System.out.println("C:MenuState : F:MenuState Constructor : Already SignedIn Google PlayServices");
      }
      else {
      ply.onStartMethod();
      ply.signIn();
      System.out.println("C:MenuState : F:MenuState Constructor : SignedIn Google PlayServices");
      }
  33. Similarly to Submit score to the leaderboard , use your own logic as if whener a new high score is created call below method of PlayServices interface
    1. System.out.println("PlayServices: Setting Score as : " + Score);
      ply.submitScore(BriskyBird.leaderboard_Easy,Score); //
      System.out.println("PlayServices: Submitted Score as : " + Score );
    2. Note that BriskyBird.leaderboard_Easy is the same leaderboard id we got from google play console , i have just set it in Class BriskyBird and i refer its value from there
  34. In order to view the highScores from Google Play Console , call showScore method as below from whichever Screen you wish to as per your business logic
    1. ply.showScore(BriskyBird.leaderboard_Easy);}
    2. Note that BriskyBird.leaderboard_Easy is the same leaderboard id we got from google play console , i have just set it in Class BriskyBird and i refer its value from there
  35. Clean , Rebuild and Execute the program and you will see that as soon as your game is started you will see that you are logged in as your gamer profile , whatever google play game services profile you are using , else it will ask you to login.
  36. In case you don't have internet connection you will get a popup open and should see an error i.e. unable to singin , check your internet connection
  37. The error i mentioned in step 44 might also come is you have any issues with your OAuth id setup , see details logcat for debugging .
  38. I have setup google game services setup in my game BriskyBird available at google play store at https://play.google.com/store/apps/details?id=com.versionpb.game get it and see how it looks
    Welcome Gamer

    Welcome Gamer

For any questions or issues , please use comment section .

 

 

 

 

Leave a Reply

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

55 + = 58