Hands down, one of the most nerve wracking API integration I’ve ever done! Mostly due to the jargon-filled Google documentation and the lack of libGDX-specific tutorials. Hopefully, this post would give you more clarity to implement the same.
1) Create a new Game Service
Head over to your dashboard and select Game services
Note: You don’t need to have your game added under All applications in order to test Play Services.
Click on Add new game. Choose I don’t use any Google APIs in my game yet tab and Fill out your game name and category.
- Game details: Make sure to fill in all mandatory fields like description, graphic assets etc.
- Linked apps: Choose Android, fill in the package name ( This package name should match with the one in your AndroidManifest file ) To properly authorize your app, follow my guide
- Events: This is not mandatory, leave it for now.
- Achievements: It is mandatory that you have at least 5 achievements in your game. If you don’t plan on having them just leave them unimplemented in your game but make sure to fill these up and obtain the tick mark.
- Leaderboards: You can add as many leaderboards as you want depending upon your game.
- Testing: Make sure you have filled in all the necessary fields and the game service is ready to be tested. Add testers: Only the users you specify will be able to use the game service when it is unpublished, make sure to add an account other than your dev account as the dev account may not work sometimes.
- Publishing: It’s better to publish it with the whole game when it’s ready. You can still test all the features with the test accounts.
2) Install Play Services packages
Open up SDK Manager in Android Studio, ( Click the button next to the AVD manager in the top toolbar ) click Launch Standalone SDK Manager
Scroll down to the Extras section and make sure these 2 packages are installed and updated to the latest :
- Google Play services
- Google Repository
3) Add BaseGameUtils Library
Didn’t we just add the Play services packages, what is this for?
This repository contains a lot of sample projects including libraries, each one implementing a different play service. So that means they’ve written all the code for you! You don’t have to talk to the API and handle all those lousy exceptions, you just have to add it as a library module for your project and call the necessary methods. Good job Google 😀
Here’s the repository, Clone it or Download it as ZIP.
Extract it inside your project folder. Inside the extracted folder, open the BasicSamples folder and you’d find all the sample projects. These are only for reference, you essentially need the libraries folder.
Open Android Studio, goto File > New > Import Module
Point the Source directory to BasicSamples\libraries\BaseGameUtils
4) Add dependencies
Now that we’ve added all the necessary packages and libraries, we need to explicitly tell our build system ( Gradle ) to compile them. In the project tree on the left, under Gradle Scripts,
Open the build.grade(Project: <Project name>) file, add these 2 lines
project(":android") { ... dependencies { ... compile 'com.google.android.gms:play-services-games:8.4.0' // 8.4 is the latest as of now, keep it updated compile project(':BaseGameUtils') ... } ... }
If you are using other play-services APIs, add them in the dependencies list. But if the number of method references in your app exceeds the 65K limit, your app may fail to compile, in that case you need to enable multidex support.
Open the build.gradle(Module: android) file, add these 2 lines
android { defaultConfig { ... multiDexEnabled true ... } } dependencies { ... compile 'com.android.support:multidex:1.0.0' ... }
Let Gradle sync the project.
5) Update Android Manifest
We’ve linked our project with the play services api, but our game still doesn’t know which game service to connect to and obviously the game would have to access the google play game servers over the internet. For that, in the Android Manifest file, we need to pass in the details of our game service and obtain permission to access the internet.
Go back to your dashboard. Open up Game services > Leaderboards and click on Get resources. This will pop-up a window with XML content, copy it. Inside your android Project, go to res > values and create a new Values XML File, name it ids and paste the contents inside it. It’ll look something like this.
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_id">767948611622</string> <string name="achievement_dum_dum">CgkIpsC36qwWEAIQAw</string> <string name="leaderboard_highest">CgkIpsC36qwWEAIQAA</string> </resources>
Open up AndroidManifest.xml and add these 4 lines
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> ... <application> ... <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" /> </application> ... <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> </manifest>
6) Implementation
Now that everything is set up, we are ready to implement play services. Since all our game classes are inside the libGDX core project, we can’t directly call these methods because these are Android methods. So we create an interface inside our core project and implement this interface inside the Android Project. Makes sense ?
So inside the core Project, create a new interface and call it PlayServices. In this example we will implementing these basic play game services.
public interface PlayServices { public void signIn(); public void signOut(); public void rateGame(); public void unlockAchievement(); public void submitScore(int highScore); public void showAchievement() public void showScore(); public boolean isSignedIn(); }
Inside the android Project, open up the default Activity, in my case it is called AndroidLauncher.java
Declare these 2 members inside the class
private GameHelper gameHelper; private final static int requestCode = 1;
Inside the onCreate() method, initialize these members
gameHelper = new GameHelper(this, GameHelper.CLIENT_GAMES); gameHelper.enableDebugLog(false); GameHelper.GameHelperListener gameHelperListener = new GameHelper.GameHelperListener() { @Override public void onSignInFailed(){ } @Override public void onSignInSucceeded(){ } }; gameHelper.setup(gameHelperListener);
Now we want play services to start automatically when the game begins and stop when the game exits, also we need to handle exceptions when the user fails to sign in. This is where the BaseGameUtil libraries come in, it takes care of all this, we just have to override our Activity methods and pass it on to them.
@Override protected void onStart() { super.onStart(); gameHelper.onStart(this); } @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); }
Now, let’s implement the interface we created.
public class AndroidLauncher extends AndroidApplication implements PlayServices
Define the implemented methods like this.
@Override public void signIn() { try { runOnUiThread(new Runnable() { @Override public void run() { gameHelper.beginUserInitiatedSignIn(); } }); } catch (Exception e) { Gdx.app.log("MainActivity", "Log in failed: " + e.getMessage() + "."); } } @Override public void signOut() { try { runOnUiThread(new Runnable() { @Override public void run() { gameHelper.signOut(); } }); } catch (Exception e) { Gdx.app.log("MainActivity", "Log out failed: " + e.getMessage() + "."); } } @Override public void rateGame() { String str = "Your PlayStore Link"; startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(str))); } @Override public void unlockAchievement() { Games.Achievements.unlock(gameHelper.getApiClient(), getString(R.string.achievement_dum_dum)); } @Override public void submitScore(int highScore) { if (isSignedIn() == true) { Games.Leaderboards.submitScore(gameHelper.getApiClient(), getString(R.string.leaderboard_highest), highScore); } } @Override public void showAchievement() { if (isSignedIn() == true) { startActivityForResult(Games.Achievements.getAchievementsIntent(gameHelper.getApiClient(), getString(R.string.achievement_dum_dum)), requestCode); } else { signIn() } } @Override public void showScore() { if (isSignedIn() == true) { startActivityForResult(Games.Leaderboards.getLeaderboardIntent(gameHelper.getApiClient(), getString(R.string.leaderboard_highest)), requestCode); } else { signIn() } } @Override public boolean isSignedIn() { return gameHelper.isSignedIn(); }
But how can the core Project reference these methods ? For that we need to pass an object of this activity to the core Project class. Here MainGame is my core Project class, I’m passing an object of AndroidLauncher which is my default Activity.
initialize(new MainGame(this), config);
Now inside the MainGame class, we create a constructor to pass this reference to the interface PlayServices
public static PlayServices playServices; public MainGame(PlayServices playServices) { this.playServices = playServices; }
My MainGame class has minimal functionality, it only sets the MainMenu screen, and I want to be able to call the PlayServices functions from the MainMenu screen. To do that, pass the object of MainGame when you set the screen.
setScreen(new MainMenu(this));
In the MainMenu class, create an object of MainGame and use a constructor to pass this reference
public static MainGame game; public MainMenuScreen(MainGame game) { this.game = game; }
Now using this object you can call any of the PlayServices interface methods like this.
game.playServices.signIn(); game.playServices.signOut(); game.playServices.rateGame(); game.playServices.unlockAchievement(); game.playServices.submitScore(score); game.playServices.showScore(); game.playServices.showAchievement(); game.playServices.isSignedIn();
If you have any doubts, leave them in the comments section below.
I believe I have set up the google play services correctly but I keep getting this error can someone help me I am not sure how to fix it mean I tried using the attachbasecontent method but it didn’t work. Please please can someone help me.
java.lang.VerifyError: com/google/android/gms/measurement/internal/zzw
at com.google.android.gms.measurement.AppMeasurementContentProvider.onCreate(Unknown Source)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1591)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1562)
at android.app.ActivityThread.installProvider(ActivityThread.java:5292)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4886)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4769)
at android.app.ActivityThread.access$1600(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5692)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
LikeLike
http://stackoverflow.com/questions/668788/android-java-lang-verifyerror
LikeLike
Awesome Tutorial
LikeLike
Thanks man!
LikeLike
cant find where to include the multidex support. My gradle file looks something like this:
project(“:android”) {
apply plugin: “android”
configurations {
natives
}
When I try adding the defaultConfig part, I get a Gradle error
LikeLike
I’m afraid you are editing the project’s build.gradle file. You are supposed to add this to the build.gradle file for the android module as I’ve mentioned in the post. Check if the build.gradle is for (Module: android) .
LikeLike
Thank you! This is a really big help for me.
LikeLike
You’re welcome!
LikeLike
Now using this object you can call any of the PlayServices interface methods like this.
game.playServices.signIn();
game.playServices.signOut();
game.playServices.rateGame();
game.playServices.unlockAchievement();
game.playServices.submitScore(score);
game.playServices.showScore();
game.playServices.showAchievement();
game.playServices.isSignedIn();
i am struggled in lost step
i need to set to button for signin and show list to leaderboard
LikeLike
After you’ve initialized and defined the interfaces, just call the methods of the PlayServices interface (in your case call the signIn() and showScore()) in your buttons’ click listeners.
LikeLike
Hello! This is a great help! However I’m having some issues and I’m not sure where I’ve gone wrong. When I try and sign in I get this message http://imgur.com/IcOZdQ6
Can you point me in the right direction? I’m sure I’ve missed changing a variable somewhere but I don’t know where!
All the best!
LikeLike
Sign the game with the same certificate whose fingerprint you specified for the game service.
LikeLike
Hey thanks for this great tutorial! It was very easy to follow. I also have the same problem as Johnny. I’m rather new at android development so could you please expand on your answer? Thanks
LikeLike
Hey, thanks for this awesome tutorial!
Everything worked out fine for me, but when I try to call the game.playServices.showScore() method, the leaderboards show up and everything works, but after that I cannot go back to my game anymore.
It just opens up the leaderboards over and over again.
Do you have an idea what could be the problem?
Greetings from Austria!
LikeLike
Check if you have mistakenly placed the button onClickListener inside the render loop?
LikeLike
thanks!!!
LikeLiked by 1 person
Great Tutorial. It has helped me a lot!
LikeLiked by 1 person
awesome
LikeLiked by 1 person
Great tutorial! Been looking for libgdx implementation of google play services for a while now.
LikeLiked by 1 person
its always popup “Failed to sign in. Please check your network connection and try again.
But my internet connection is working correctly.
LikeLike
Thank you so much for such a nice tutorial, my issue is solved, I had just forget to include SHA1 key.
LikeLiked by 1 person
great tutorial !!! Thank you so much…
can you make another tutorial for libgdx + facebook integration……….it would be great help
LikeLike
I’ll look into it 🙂
LikeLike
awesome! thanks!
LikeLike
this is perfect!! what I was looking for, Thank you.
Libgdx + facebook please, i can’t find any tutorials about it till now.
LikeLike
Awesome tutorial man! Thank you very much 🙂
LikeLike