B4A Library Google Play Game Services

This is a wrapper for the Google Play Services related to games. This library was tested successfully with the API 37 of Google Play Services.

List of features:
  • Sign-in: supported;
  • Achievements: supported;
  • Leaderboards: supported;
  • Real-time multiplayer: supported (NEW!);
  • Turn-based multiplayer: supported;
  • Level and XP: supported;
  • Gifts and requests: supported;
  • Events and quests: not supported;
  • Saved games: supported;
  • Notifications: supported;
  • Player stats: supported;
  • Nearby connections: supported.
To compile, you need B4A v6+, JDK v7+ and android.jar v21+ (cf. Tools/Configure paths).

The library is provided with its Java source code and a few B4A modules:
  • ClsConnection: manages the sign-in, sign-out and connection events;
  • CodConverter: converts your data map to and from the byte array needed for the Saved Games service (this module requires three extra libraries: JSON, ByteConverter and RandomAccessFile) in case you don't own the DataCollection library;
  • CodTurnBasedMatch: helper module for turn-based matches.
Before using this library, you need to:
  • download the Google Play services SDK and Android Support Repository with the Android SDK manager;
  • copy the GooglePlayGameServices library (Jar+Xml) to your additional B4A libraries folder.
When you create a project requiring this library, you need to:
  • add this line in the project attributes of your Main module:
    B4X:
    #AdditionalJar: com.google.android.gms:play-services-games
  • add also this line if you want to access the Nearby Connections API:
    B4X:
    #AdditionalJar: com.google.android.gms:play-services-nearby
  • add these lines to your manifest:
    B4X:
    AddApplicationText(
    <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" />)
  • add also these lines to the manifest if you want to access the Nearby Connections API:
    B4X:
    AddApplicationText(
    <meta-data android:name="com.google.android.gms.nearby.connection.SERVICE_ID"
        android:value="$PACKAGE$" />)
  • copy the games-ids.xml file generated by your Google Play developer console in the Objects\res\values folder.
To generate the games-ids.xml file, click on the link at the bottom of some screens (e.g. achievements) in your developer console (you need of course a game project properly configured to see it):
ressources.png


This file should look like this:
B4X:
<?xml version="1.0" encoding="utf-8"?>
<!--
Google Play game services IDs.
Save this file as res/values/games-ids.xml in your project.
-->
<resources>
  <string name="app_id">01234567890</string>
  <string name="achievement_win_on_a_very_large_map">CgkIuqeG8-kOEAIQAQ</string>
  <string name="achievement_win_on_a_large_map">CgkIuqeG8-kOEAIQAg</string>
  <string name="achievement_win_on_a_medium_map">CgkIuqeG8-kOEAIQAw</string>
  <string name="achievement_win_on_a_small_map">CgkIuqeG8-kOEAIQBA</string>
  <string name="achievement_win_on_a_very_small_map">CgkIuqeG8-kOEAIQBQ</string>
  <string name="leaderboard_main_score">CgkIuqeG8-kOEAIQBw</string>
</resources>

To set up a game in the Google Play developer console, please read this, then this.

To get details about a returned status code, please read this.
 

Attachments

  • Demos_37.zip
    71 KB · Views: 270
  • GooglePlayGameServices_372.zip
    241.3 KB · Views: 267
Last edited:

Schakalaka

Active Member
Licensed User
i have add the file, but when i compile the app, the file wil deleted.
thi is my code..
B4X:
<resources>
  <!-- app_id -->
  <string name="app_id" translatable="false">655981348077</string>
  <!-- package_name -->
  <string name="package_name" translatable="false">eu.beraldogiuliano.tsdgbscvsd</string>
  <!-- leaderboard Relax Mode -->
  <string name="leaderboard_relax_mode" translatable="false">CgkI7Yird3IsTAIQAQ</string>
  <!-- leaderboard Hard Mode -->
  <string name="leaderboard_hard_mode" translatable="false">CgkI7Yird3IsTAIQAQ</string>
  <!-- leaderboard Survival Mode -->
  <string name="leaderboard_survival_mode" translatable="false">CgkI7Yird3IsTAIQAQ</string>
</resources>

maybe on file manifest?
 

Computersmith64

Well-Known Member
Licensed User
no.. i have the same result..
see you tomorrow
As I said in my first post, you need to re-read the instructions at the start of this thread. I have several games that use GPGS leaderboards & achievements using this library & they all work perfectly. If it's not working for you then you have either missed a step, or have a bad configuration somewhere.

I notice your ids.xml file is missing the <integer name="google_play_services_version"> tag - so that's a problem (unless you have hard coded it in your manifest).

If you copy & paste the error message you are getting we might be able to help.

- Colin.
 

Schakalaka

Active Member
Licensed User
i have add this line in the main activity
#AdditionalJar: com.google.android.gms:play-services-games

the library activated are. (see photo)

i have create an activiry after button click "Googleconn"
Addiional module: clsConnections
i have only leaderboards

the error is:
B4X:
Logger connesso a: 0c81fc49
--------- beginning of /dev/log/main--------- beginning of /dev/log/system~i:*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
JAVA [Initialize] eventname = objWFI
[isConnectedToInternet]true
** Activity (main) Resume **
Network WIFI connected
WifiAvailable:true
WifiConnected:true
BroadcastReceiver::onReceive::android.net.conn.CONNECTIVITY_CHANGE
** Activity (main) Pause, UserClosed = false **
** Activity (googleplayconn) Create, isFirst = true **
Initialize: creating a GoogleAPIClient instance
State change: Unconfigured -> Disconnected
Initialize: ready for connection
** Activity (googleplayconn) Resume **
Connect: state = Disconnected
Connect: no auto sign-in, FirstAttempt is false
NetworkInfo.onConnectivityChange: NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), roaming: false, failover: false, isAvailable: true, isConnectedToProvisioningNetwork: false
GPC_onConnectivityChange: NetworkType=1 IsConnectedOrConnecting=true
Connect: state = Disconnected
Connect: first attempt
Connect: isGooglePlayServicesAvailable returned 0
State change: Disconnected -> Connecting
sending message to waiting queue (iad_receivead)
java.lang.IllegalStateException: A fatal developer error has occurred. Check the logs for further information.
    at com.google.android.gms.common.internal.BaseGmsClient$zza.deliverCallback(Unknown Source)
    at com.google.android.gms.common.internal.BaseGmsClient$zza.deliverCallback(Unknown Source)
    at com.google.android.gms.common.internal.BaseGmsClient$CallbackProxy.deliverCallback(Unknown Source)
    at com.google.android.gms.common.internal.BaseGmsClient$zzb.handleMessage(Unknown Source)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:146)
    at android.app.ActivityThread.main(ActivityThread.java:5756)
    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)

you can download it here:
B4X:
https://drive.google.com/file/d/1MqIMN2YaTxpM90GS--hMILTvFLVHL-OX/view?usp=sharing
 

Attachments

  • Api console.png
    Api console.png
    60.1 KB · Views: 73
  • Api detail.png
    Api detail.png
    28.4 KB · Views: 67
  • google play console game.png
    google play console game.png
    63 KB · Views: 71
  • library active.png
    library active.png
    16.1 KB · Views: 66
Last edited:

Computersmith64

Well-Known Member
Licensed User
EDIT: I just ran a test where I removed the google_play_services_version from the manifest & also my ids.xml file & Play Services still ran fine - so I'm guessing that it's no longer required (I was using it as a hangover from way back when I first started using Play Services in my apps).

I also ran a test where I removed the APP_ID from the manifest & this caused the same crash as you were seeing - so this is definitely your problem. You need to add:
AddApplicationText(
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="@string/app_id" />)
to your manifest.

=======================================================

OK - you haven't followed the steps in the first post in this thread. One of the steps is:
add these lines to your manifest:
Code:
AddApplicationText(
<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" />)
I don't see these lines anywhere in your manifest.

You also need to add the following line to your games-ids.xml file (which seems to be missing in the instructions):
<integer name="google_play_services_version">12451000</integer> 'I'm pretty sure this is the current version

I'm not sure why Informatix says you need to add the #AdditionalJar: com.google.android.gms:play-services-games line to your main Activity. I've never added it to any of my projects.

- Colin.
 
Last edited:

Schakalaka

Active Member
Licensed User
ok. thanks you.

AddApplicationText(
<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" />)

i need replace this: "@string/app_id" with what? i have "655981348077-tcsadui6b4eel9uk7rjcacljh0jnvaao.apps.googleusercontent.com" or only "655981348077"?
i ve try all but return same error..

i should insert Sh1 key too? where?

i'm creazying
 

Informatix

Expert
Licensed User
ok. thanks you.

AddApplicationText(
<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" />)

i need replace this: "@string/app_id" with what? i have "655981348077-tcsadui6b4eel9uk7rjcacljh0jnvaao.apps.googleusercontent.com" or only "655981348077"?
i ve try all but return same error..

i should insert Sh1 key too? where?

i'm creazying
You don't need to replace anything or insert anything that is not mentionned in the steps of the first thread.
If you want to try the provided examples, you have to change the default package name to the package name of your app, add the games-id.xml file in Objects\res\values and change the attributes of this file to read-only.
 

Informatix

Expert
Licensed User
I'm not sure why Informatix says you need to add the #AdditionalJar: com.google.android.gms:play-services-games line to your main Activity. I've never added it to any of my projects.
Without this, you have to provide the jar and res files with your application.
 

Computersmith64

Well-Known Member
Licensed User
Without this, you have to provide the jar and res files with your application.
Hmmm - I don't do that either & it works fine.

The only #AdditionalJar statements I use are:
B4X:
#AdditionalJar: com.crashlytics.sdk.android:crashlytics
#AdditionalJar: com.google.firebase:firebase-core

- Colin.
 

Schakalaka

Active Member
Licensed User
Doesn't the:


in the library xml file essentially do the same thing as the #AdditionalJar statement?

- Colin.

Yes, as he told me, it work well. easerly.

now i have another "problem".. too easy end here.
i have create 3 leaaderboards for each game mode:
Normal mode,
Hard mode,
survive mode.
on leaderboards i see only survive mode, and the point are something like 9.2351. it just should be like 40 or 100 as correct answares made on the each game mode.
i save max answare questions too
should i save a number to upload to leaderboard in a file alone?
i can set it somewhere?
thansk for help
 

Computersmith64

Well-Known Member
Licensed User
Yes, as he told me, it work well. easerly.

now i have another "problem".. too easy end here.
i have create 3 leaaderboards for each game mode:
Normal mode,
Hard mode,
survive mode.
on leaderboards i see only survive mode, and the point are something like 9.2351. it just should be like 40 or 100 as correct answares made on the each game mode.
i save max answare questions too
should i save a number to upload to leaderboard in a file alone?
i can set it somewhere?
thansk for help

Can you post the code that shows the leaderboards? You need to create the leaderboard intent with the ID of the leaderboard you want to show (ie: it's not like Game Center where you can just show a list of all your leaderboards & let the user pick the one they want). Here's how I do it:

B4X:
Private Sub showLeaderBoard
    'In my Starter service I have a Public array that holds all my leaderboard IDs
    'eg: Public sLeaderBoards() As String = Array As String("[ID1]", "[ID2]", "[ID3]")
    ' I also have an Int variable that holds the current game mode, which I use as an index into my leaderboard ID array
    'so when I create the leaderboard intent I pass the correct ID for the current game mode

    Private i As Intent
    i = Starter.Leaderboards.GetLeaderboardIntent(Starter.sLeaderBoards(GameMode))
    Starter.GPUtils.StartActivityForResult(i, Starter.LEADERBOARDS_DLG)
               
End Sub

As far as why your scores are not correct, I don't know without seeing the code that posts the scores to the leaderboards.

- Colin.
 

Schakalaka

Active Member
Licensed User
Can you post the code that shows the leaderboards? You need to create the leaderboard intent with the ID of the leaderboard you want to show (ie: it's not like Game Center where you can just show a list of all your leaderboards & let the user pick the one they want). Here's how I do it:

B4X:
Private Sub showLeaderBoard
    'In my Starter service I have a Public array that holds all my leaderboard IDs
    'eg: Public sLeaderBoards() As String = Array As String("[ID1]", "[ID2]", "[ID3]")
    ' I also have an Int variable that holds the current game mode, which I use as an index into my leaderboard ID array
    'so when I create the leaderboard intent I pass the correct ID for the current game mode

    Private i As Intent
    i = Starter.Leaderboards.GetLeaderboardIntent(Starter.sLeaderBoards(GameMode))
    Starter.GPUtils.StartActivityForResult(i, Starter.LEADERBOARDS_DLG)
              
End Sub

As far as why your scores are not correct, I don't know without seeing the code that posts the scores to the leaderboards.

- Colin.

ok, ive do it.
i have use the example and add only this code for read the score to update to leaderboards
under Sub GP_onLeaderboardsLoaded(Result As Map)
B4X:
    Main.listleader = File.ReadList(Main.MySafeFolder, "WorldCapitals/Gplay.txt") 'Read the best score file
    PBSpinner.Visible = True
    Leaderboards.SubmitScoreImmediate("CgkI7Ymk3IsTEAxxxx",Main.listleader.Get(0)).SetResultEvent("GP_onScoreSubmitted")
    Leaderboards.SubmitScoreImmediate("CgkI7Ymk3IsTEAxxxx",Main.listleader.Get(1)).SetResultEvent("GP_onScoreSubmitted")
    Leaderboards.SubmitScoreImmediate("CgkI7Ymk3IsTEAxxxx",Main.listleader.Get(2)).SetResultEvent("GP_onScoreSubmitted")
    'Updates the button states
    Update_UI

Now, how i can do the same for verify achievement?
a Achievements can be:
Answare 10 questions in relax mode
answare 10 questions in Hard mode
answare 10 questions witout errors in normal mode
... and so on.
to get the number to verify use Main.listleader.Get(3,4,5,6 ecc...)

thanks you
 

Computersmith64

Well-Known Member
Licensed User
Actually, I lied about not being able to show all leaderboards. if you want to do this, use:

B4X:
Private Sub showLeaderBoard
    'In my Starter service I have a Public array that holds all my leaderboard IDs
    'eg: Public sLeaderBoards() As String = Array As String("[ID1]", "[ID2]", "[ID3]")
    ' I also have an Int variable that holds the current game mode, which I use as an index into my leaderboard ID array
    'so when I create the leaderboard intent I pass the correct ID for the current game mode

    Private i As Intent
    i = Starter.Leaderboards.GetAllLeaderboardIntent
    Starter.GPUtils.StartActivityForResult(i, Starter.LEADERBOARDS_DLG)
               
End Sub

- Colin.
 

Ivan Aldaz

Member
Licensed User
Hi. I'm trying to configure leaderboards and achievements with this library, and everything seems to go right until I try to submit a score to one of the leaderboards that I have configured in my Google Play Games console. After trying to make it work on my app, without success, I've been trying the Informatix demo as he wrote in post #168, and the result is the same. The app connects, and can retrieve the list of leaderboards and achievements, but when I try to submit a score to one of the leaderboards the Sub GP_onScoreSubmitted shows the error "SubmitScoreImmediate: Error=2" in a MsgBox.

B4X:
If StatusCode <> Leaderboards.STATUS_OK Then
        'The score submission failed
        Msgbox("SubmitScoreImmediate: Error=" & StatusCode, "Error")
        Return
    End If

...and the score is not submitted. I've been looking for the value StatusCode = 2 and seems to correspond to "CLIENT_RECONNECT_REQUIRED", but just before the code in which I try submit a score everything seems to be right (all the next logs are 'True', and the first is "Signed In"):

B4X:
'...
    Log("Connection.GPC.ConnectionStateStr : " & Connection.GPC.ConnectionStateStr)
    Log("Connection.IsSignedIn : " & Connection.IsSignedIn)
    Log("Connection.GPC.IsConnected : " & Connection.GPC.IsConnected)
    Log("Connection.GPC.IsSignedIn : " & Connection.GPC.IsSignedIn)
    Log("Connection.GPC.IsInitialized : " & Connection.GPC.IsInitialized)
    Log("Connection.NI.IsConnected : " & Connection.NI.IsConnected)
    Log("Connection.NI.IsInitialized : " & Connection.NI.IsInitialized)

    Leaderboards.SubmitScoreImmediate("CgkI766JsIEFEAIQHg", Rnd(10, 10000)).SetResultEvent("GP_onScoreSubmitted")


It's curious, but when trying to increment one achievement the Sub GP_onAchievementIncremented throws the same error as when trying to submit a score (StatusCode = 2), but the achievement is registered!

With "GPUtils.AppId" I get the same AppId as the indicated in the Google Play Games console, and the same that appears on the games-ids.xml file, the games-ids.xml file is on its place, the SHA1 key matches, the lines indicated in post #1 of this thread are added to the manifest file, as well as "#AdditionalJar: com.google.android.gms: play-services-games", ...

Don't know if it is important for this issue, but in the Sub Connection.Autoconnect (ClsConnection module) I can't connect using "GPC.Connect(False)". I have to set to "True" the FirstAttempt parameter, or connect using GPC.Reconnect:

B4X:
        If Not(GPC.IsSignedIn) Then
             GPC.Connect(True)
'            GPC.Reconnect
        End If

Any ideas?

Thank you in advance.
 

Computersmith64

Well-Known Member
Licensed User
Hi. I'm trying to configure leaderboards and achievements with this library, and everything seems to go right until I try to submit a score to one of the leaderboards that I have configured in my Google Play Games console. After trying to make it work on my app, without success, I've been trying the Informatix demo as he wrote in post #168, and the result is the same. The app connects, and can retrieve the list of leaderboards and achievements, but when I try to submit a score to one of the leaderboards the Sub GP_onScoreSubmitted shows the error "SubmitScoreImmediate: Error=2" in a MsgBox.

B4X:
If StatusCode <> Leaderboards.STATUS_OK Then
        'The score submission failed
        Msgbox("SubmitScoreImmediate: Error=" & StatusCode, "Error")
        Return
    End If

...and the score is not submitted. I've been looking for the value StatusCode = 2 and seems to correspond to "CLIENT_RECONNECT_REQUIRED", but just before the code in which I try submit a score everything seems to be right (all the next logs are 'True', and the first is "Signed In"):

B4X:
'...
    Log("Connection.GPC.ConnectionStateStr : " & Connection.GPC.ConnectionStateStr)
    Log("Connection.IsSignedIn : " & Connection.IsSignedIn)
    Log("Connection.GPC.IsConnected : " & Connection.GPC.IsConnected)
    Log("Connection.GPC.IsSignedIn : " & Connection.GPC.IsSignedIn)
    Log("Connection.GPC.IsInitialized : " & Connection.GPC.IsInitialized)
    Log("Connection.NI.IsConnected : " & Connection.NI.IsConnected)
    Log("Connection.NI.IsInitialized : " & Connection.NI.IsInitialized)

    Leaderboards.SubmitScoreImmediate("CgkI766JsIEFEAIQHg", Rnd(10, 10000)).SetResultEvent("GP_onScoreSubmitted")


It's curious, but when trying to increment one achievement the Sub GP_onAchievementIncremented throws the same error as when trying to submit a score (StatusCode = 2), but the achievement is registered!

With "GPUtils.AppId" I get the same AppId as the indicated in the Google Play Games console, and the same that appears on the games-ids.xml file, the games-ids.xml file is on its place, the SHA1 key matches, the lines indicated in post #1 of this thread are added to the manifest file, as well as "#AdditionalJar: com.google.android.gms: play-services-games", ...

Don't know if it is important for this issue, but in the Sub Connection.Autoconnect (ClsConnection module) I can't connect using "GPC.Connect(False)". I have to set to "True" the FirstAttempt parameter, or connect using GPC.Reconnect:

B4X:
        If Not(GPC.IsSignedIn) Then
             GPC.Connect(True)
'            GPC.Reconnect
        End If

Any ideas?

Thank you in advance.

I've never used SubmitScoreImmediate - I always just use SubmitScore & it has been 100% reliable (afaik). Can you submit scores successfully using SubmitScore?

- Colin.
 

Ivan Aldaz

Member
Licensed User
Thank you, Colin. It does not work that way either. I've also tried with:

B4X:
    Dim score As Long = Rnd(100,1000)
                                                 'SubmitScore isn't allowed with GPlayPendingResult
    Dim gpScore As GPlayPendingResult = Leaderboards.SubmitScoreImmediate(Leaderboard_Id, score)
        gpScore.SetResultEvent("GP_onScoreSubmitted")

...but no luck, get the same result.

I'm thinking of building a new complete project, starting from zero, including new publishing of the app, and leaderboards and achievements too. Maybe I missed something while setting up the project in the Google Play console, some key, or something else. I think I'm going to lose a lot less time this way...
 

Computersmith64

Well-Known Member
Licensed User
Thank you, Colin. It does not work that way either. I've also tried with:

B4X:
    Dim score As Long = Rnd(100,1000)
                                                 'SubmitScore isn't allowed with GPlayPendingResult
    Dim gpScore As GPlayPendingResult = Leaderboards.SubmitScoreImmediate(Leaderboard_Id, score)
        gpScore.SetResultEvent("GP_onScoreSubmitted")

...but no luck, get the same result.

I'm thinking of building a new complete project, starting from zero, including new publishing of the app, and leaderboards and achievements too. Maybe I missed something while setting up the project in the Google Play console, some key, or something else. I think I'm going to lose a lot less time this way...

Yeah I know that SubmitScore isn't allowed with GPlayPendingResult - however unless you have a specific requirement to know the result, it's better to use it. I'm sure I read somewhere in the Google Play documentation that submitting scores, unlocking achievements, etc... is supposed to be a "send & forget" action - & as I said, afaik it has been 100% reliable for me, in multiple apps that support GPGS using this library.

If you can post the project I can take a look at it (use the File->Export as zip option in the IDE).

- Colin.
 

Ivan Aldaz

Member
Licensed User
Just got home from work and retried to make different things and at last, IT WORKED! :D
Don't know why, but tried (as one of the latest things to do before the 'fatal' solution of post #178) linking the same app to the Game Play Services again (now I have the same app linked two times), and scores and achievements are submitted with no errors. Perhaps has something to do with the OAuth2 client ID, the only thing I see that is different between the two apps.

Thanks again, Colin and, of course, Informatix.
 
Top