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: 583
  • GooglePlayGameServices_372.zip
    241.3 KB · Views: 578
Last edited:
D

Deleted member 30048

Guest
Hi, There any way to get the profile picture of the person who are login?

I want to do that when a user login, display his name and images on MSMaterialDrawer like in the app of gmail for example

The only thing that I could get is the email using "GPUtils.CurrentAccountName" but I had no luck with the images.

Thanks!
 

Informatix

Expert
Licensed User
Longtime User
Hi, There any way to get the profile picture of the person who are login?

I want to do that when a user login, display his name and images on MSMaterialDrawer like in the app of gmail for example

The only thing that I could get is the email using "GPUtils.CurrentAccountName" but I had no luck with the images.

Thanks!
How do you try to get the picture?
DisplayName and GetHiResImage/GetIconImage of GPlayPlayer should give you these data.
 
D

Deleted member 30048

Guest
How do you try to get the picture?
DisplayName and GetHiResImage/GetIconImage of GPlayPlayer should give you these data.

Thanks for your reply. I don't know how to use it, I use:

Dim player As GPlayPlayer
player.GetIconImage(imageview1)
or
log(player.DisplayName)

but I have "an error has occurred in the sub: java.lang.NullPointerException Continue?"

I know that I'm doing something wrong, but I don't know what.

Thanks
 

Informatix

Expert
Licensed User
Longtime User
Thanks for your reply. I don't know how to use it, I use:

Dim player As GPlayPlayer
player.GetIconImage(imageview1)
or
log(player.DisplayName)

but I have "an error has occurred in the sub: java.lang.NullPointerException Continue?"

I know that I'm doing something wrong, but I don't know what.

Thanks
You get a NullPointerException because "player" is not initialized nor set. If you want to retrieve data for the current player, you should set it to CodTurnBasedMatch.Players.CurrentPlayer.
 
D

Deleted member 30048

Guest
You get a NullPointerException because "player" is not initialized nor set. If you want to retrieve data for the current player, you should set it to CodTurnBasedMatch.Players.CurrentPlayer.

Thanks a lot, now it works fine :):).
 

designer2k2

Member
Licensed User
Longtime User
Hello,

im using your library with the API19 and everything is working (login/highscore/achievements) but i have the following error with Logcat:

B4X:
09-10 07:49:20.748 E/ActivityThread(24656): Activity xxx.xxx.xxx.main has leaked IntentReceiver flm.b4a.googleplay.Network_Info$ConnectivityChangeReceiver@25ff28b4 that was originally registered here. Are you missing a call to unregisterReceiver()?
09-10 07:49:20.748 E/ActivityThread(24656): android.app.IntentReceiverLeaked: Activity xxx.xxx.xxx.main has leaked IntentReceiver flm.b4a.googleplay.Network_Info$ConnectivityChangeReceiver@25ff28b4 that was originally registered here. Are you missing a call to unregisterReceiver()?
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.clsconnection._initialize(clsconnection.java:279)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main._activity_create(main.java:338)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main.afterFirstLayout(main.java:98)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main.access$100(main.java:16)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main$WaitForLayout.run(main.java:76)


im having this in the pause/resume:

B4X:
Sub Activity_Resume
    Connection.AutoConnect
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    If UserClosed Then
        Connection.SignOutAndDisconnect
    End If
End Sub

is there something im missing to remove the IntentReceiver?
 

Informatix

Expert
Licensed User
Longtime User
Hello,

im using your library with the API19 and everything is working (login/highscore/achievements) but i have the following error with Logcat:

B4X:
09-10 07:49:20.748 E/ActivityThread(24656): Activity xxx.xxx.xxx.main has leaked IntentReceiver flm.b4a.googleplay.Network_Info$ConnectivityChangeReceiver@25ff28b4 that was originally registered here. Are you missing a call to unregisterReceiver()?
09-10 07:49:20.748 E/ActivityThread(24656): android.app.IntentReceiverLeaked: Activity xxx.xxx.xxx.main has leaked IntentReceiver flm.b4a.googleplay.Network_Info$ConnectivityChangeReceiver@25ff28b4 that was originally registered here. Are you missing a call to unregisterReceiver()?
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.clsconnection._initialize(clsconnection.java:279)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main._activity_create(main.java:338)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main.afterFirstLayout(main.java:98)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main.access$100(main.java:16)
09-10 07:49:20.748 E/ActivityThread(24656):     at xxx.xxx.xxx.main$WaitForLayout.run(main.java:76)


im having this in the pause/resume:

B4X:
Sub Activity_Resume
    Connection.AutoConnect
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    If UserClosed Then
        Connection.SignOutAndDisconnect
    End If
End Sub

is there something im missing to remove the IntentReceiver?
The intent receiver is created by RegisterConnectivityChangeListener when you call Initialize of ClsConnection.bas. UnregisterConnectivityChangeListener should be called when the connection is no longer used but it's not done. So here's a modified version of the class that fix this issue.
 

Attachments

  • ClsConnection.bas
    4.9 KB · Views: 235

Isac

Active Member
Licensed User
Longtime User
Hi Informatix, with your library, I can connect to 2 devices

do you have any example

Thank you for your attention
 

peter93

Member
Licensed User
Longtime User
I am trying to integrate my game app in Google game play.
For this I used Bookstore GooglePlayServices29 de Informatix and the program Achievements Leaderboards of Demo_GPGS29.
Access to Google game play works and I can do all actions in the demo program.
But there are several things I don't understand:
-How the game itself app is launched. By Google? by my program?
-Why the list of complétions is not in the same order as the console developer.
Thanks for your help.
 

Informatix

Expert
Licensed User
Longtime User
But there are several things I don't understand:
-How the game itself app is launched. By Google? by my program?
I'm not sure to understand your question. Your game has to contain the code to unlock/list the achievements, like in the demo. You don't have to run something aside.

-Why the list of complétions is not in the same order as the console developer.
Thanks for your help.
The order is due to the data container (a map). It is unpredictable.
 

peter93

Member
Licensed User
Longtime User
I'm not sure to understand your question. Your game has to contain the code to unlock/list the achievements, like in the demo. You don't have to run something aside.


The order is due to the data container (a map). It is unpredictable.

Thank you Informatix.

In my program I wrote this code:
B4X:
If Connection.IsSignedIn Then
'Maj du score
   Leaderboards.SubmitScoreImmediate(Leaderboard_Id, ((s.SubString2(0, s.IndexOf(":")) * 60) + s.SubString(s.IndexOf(":")+1)) * 1000).SetResultEvent("GP_onScoreSubmitted")
' Unlock la réussite
  Achievements.UnlockImmediate(AchievementToUnlock_Id).SetResultEvent ("GP_onAchievementUnlocked")
'Opens the dialog to see achievements
  Dim i As Intent = Achievements.GetAchievementsIntent
  GPUtils.StartActivityForResult(i, ACHIEVEMENTS_DLG)
End If
But this causes an error:

Leaderboards.SubmitScoreImmediate: id=CgkI1-rS6JkREAIQDA score=113000
Achievements.UnlockImmediate: CgkI1-rS6JkREAIQBw
Achievements.GetAchievementsIntent
** Activity (main) Pause, UserClosed = false **
UpdateAchievementResult -> gp_onachievementunlocked
Error occurred on line: 1130 (Main)
java.lang.NullPointerException: Attempt to read from field 'anywheresoftware.b4a.BA com.Mastermind_Legend.main.activityBA' on a null object reference
at com.Mastermind_Legend.main._gp_onachievementunlocked(main.java:3313)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:702)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at flm.b4a.googleplay.PendingResultWrapper.RaiseEvent(PendingResultWrapper.java:230)
at flm.b4a.googleplay.PendingResultWrapper.access$0(PendingResultWrapper.java:226)
at flm.b4a.googleplay.PendingResultWrapper$UpdateAchievementEvent.onResult(PendingResultWrapper.java:553)
at flm.b4a.googleplay.PendingResultWrapper$UpdateAchievementEvent.onResult(PendingResultWrapper.java:1)
at com.google.android.gms.common.api.internal.zzb$zza.zzb(Unknown Source)
at com.google.android.gms.common.api.internal.zzb$zza.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

It would seem that the functions runs without waiting for the reply of the previous.
is I made a mistake ?
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
It would seem that the functions runs without waiting for the reply of the previous.
Nothing strange here. A network or disk operation should never be blocking, so SubmitScoreImmediate and UnlockImmediate send immediately a query to the server and return. They do not block the main thread to wait for the response. The waiting is done in the background. As soon as the response arrives, an event is raised (the one you specified with SetResultEvent).
The error that you get comes from your code in GP_onAchievementUnlocked. As the code is not posted, I cannot help.
 
Top