Git Product home page Git Product logo

gdx-gamesvcs's Introduction

gdx-gamesvcs

Framework and implementations for using Game Services (BaaS) with libGDX.

Build Status Maven Central

Demo app

With this extension, you can integrate one or more Game Services in your libGDX games with ease. You can choose the wanted Game Service client in your Launcher classes dynamically.

Supported game services

Basic concept

The library provides an interface IGameServiceClient that you reference in your core code. Your platform-dependant launchers instantiate an actual implementation of the interface.

Every implemented game service client has its own project you can decide to include or not. So your game won't get blown up with code you don't need.

There is a no-op implementation NoGameServiceClient provided that does absolutely nothing besides logging your calls. Use it to test platform-independant or to avoid null checks or NPEs. For testing your UI's behaviour on slow callback responses, you can use MockGameServiceClient.

See the corresponding demo app for an example and this project's wiki for further documentation.

Working demos

Ready to play:

Source examples:

Installation

This project is published to the Sonatype Maven repository. You can integrate the lib into your project by just adding the dependencies to your build.gradle file.

Define the version of this API right after the gdxVersion:

gdxVersion = '1.9.8'
gamesvcsVersion = '1.1.0'

Core:

api "de.golfgl.gdxgamesvcs:gdx-gamesvcs-core:$gamesvcsVersion"

For the HTML5 project, you also have to include the sources

implementation "de.golfgl.gdxgamesvcs:gdx-gamesvcs-core:$gamesvcsVersion:sources"

and add a line to GdxDefinition.gwt.xml and GdxDefinitionSuperdev.gwt.xml:

<inherits name="de.golfgl.gdxgamesvcs.gdx_gamesvcs_gwt" />

After including the dependencies and refreshing, you can use the NoGameServiceClient in your project. For using another Gameservice, add its dependencies according to its wiki page or implement your own client against IGameServiceClient.

Building from source

To build from source, clone or download this repository, then open it in Android Studio. Perform the following command to compile and upload the library in your local repository:

gradlew clean publishToMavenLocal

See build.gradle file for current version to use in your dependencies.

Usage

Initializing the game service client

You should be fine by adding the following lines to your game in order to connect to the service:

Main game class:

public IGameServiceClient gsClient;

@Override
public void create() {
    // ...awesome initialization code...
    
    if (gsClient == null)
        gsClient = new NoGameServiceClient();

    // for getting callbacks from the client
    gsClient.setListener(this);

    // establish a connection to the game service without error messages or login screens
    gsClient.resumeSession();
    
}

@Override
public void pause() {
    super.pause();

    gsClient.pauseSession();
}

@Override
public void resume() {
    super.resume();

    gsClient.resumeSession();
}

In the launcher class you instantiate and initialize the GameServiceClient for the service you want to use:

    DesiredGameserviceClient gsClient = new DesiredGameserviceClient();

    gsClient.initialize( game service dependant initialization parameters );

    myGdxGame.gsClient = gsClient;

Initialization depends on the game service; see the wiki pages on how to instantiate the included Game Service clients.

As you see, you assign the game service client dynamically here - so it is no problem to support different game services with only a single build of your game.

If you want to know if you established a connection to a user session, you can use gsClient.isSessionActive(), or set a listener and wait for the call to gsOnSessionActive(). You don't need to check if a user session is active for submitting scores, events and unlocking achievements, as some game services allow anonymous or guest submits. The API client implementations do all needed checks.

Submitting events and scores, unlocking achievements

You can feed your players by unlocking achievements and posting scores to leaderboards really easy:

gsClient.submitToLeaderboard(leaderboardId, score, tag);

gsClient.unlockAchievement(achievementId);

Events are interesting for you as a developer.

gsClient.submitEvent(eventId, 1);

Please note: It depends of the game services which calls can be processed without a user session. The API client implementations deal with that so you don't have to.

Cloud save

Not every game service and client implementation supports cloud save, check the overview table in the wiki. In your game, you can and must check the availability by calling

if (gsClient.isFeatureSupported(GameServiceFeature.GameStateStorage))

If you ensured that cloud save feature is available, use these methods to invoke it:

gsClient.loadGameState(fileId, new ILoadGameStateResponseListener() {...});

gsClient.saveGameState(fileId, gameState, progressValue, 
                       new ISaveGameStateResponseListener() {...});

The methods perform an ansynchronous operation and call your listener afterwards.

Fetching scores and achievement status

The interface provides a method for open up an API's default leaderboard or achievment UI:

gsClient.providesAchievementsUI();
gsClient.showAchievements();
// same for leaderboards

Default UI is provided by all game services, so you need to check with gsClient.isFeatureSupported() before calling.

Fetching scores and achievement status to show in your own UI can be done by calling

 gsClient.fetchLeaderboardEntries(...)
 gsClient.fetchAchievements(...)

after checking

 gsClient.isFeatureSupported(GameServiceFeature.FetchLeaderBoardEntries)
 gsClient.isFeatureSupported(GameServiceFeature.FetchAchievements))

You give a listener as a parameter which will be called with a list of achievement or leader board entries in response. See to the JavaDocs or the demo application for more information.

Explicit log in and out

Some game services support user sign in and out, some need the user to log in manually for the first time. Use the game service interface's logIn() and logOut() methods for doing so. These methods should only be called when the user manually requested an explicit log in/out.

Note: For Google Play Games your game even must provide a sign in/out button to be considered Google Play Games Services-compatible.

News & Community

You can get help on the libgdx discord.

License

The project is licensed under the Apache 2 License, meaning you can use it free of charge, without strings attached in commercial and non-commercial projects. We love to get (non-mandatory) credit in case you release a game or app using this project!

gdx-gamesvcs's People

Contributors

fstranieri avatar karivatj avatar mgsx-dev avatar mrstahlfelge avatar simonit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gdx-gamesvcs's Issues

GPGS HTML: provide implementation

Possibility to fetch leader board entries and achievements status

At the moment, it is only possible to show achievements status and leader board entries via showLeaderboard or showAchievements if the game service provides an own interface.

Methods for fetching this data are needed in the core interface and implementations in the game service clients.

Runtime error java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap;

When using gdx-gamesvcs in junction with "com.google.firebase:firebase-analytics:17.4.4" or posterior
then code compile but generate a runtime error at the line

game.gsClient = new GpgsClient().initialize(this,false);

with firebase analytics version 17.4.3 or prior the code works

Error log..............

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mygdx.game, PID: 22977
java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap;
at com.google.android.gms.common.api.GoogleApiClient$Builder.(Unknown Source)
at de.golfgl.gdxgamesvcs.GpgsClient.initialize(GpgsClient.java:117)
at com.mygdx.game.AndroidLauncher.onCreate(AndroidLauncher.java:17)
at android.app.Activity.performCreate(Activity.java:6285)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.util.ArrayMap" on path: DexPathList[[zip file "/data/app/com.mygdx.game-2/base.apk"],nativeLibraryDirectories=[/data/app/com.mygdx.game-2/lib/arm, /data/app/com.mygdx.game-2/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at com.google.android.gms.common.api.GoogleApiClient$Builder.(Unknown Source) 
at de.golfgl.gdxgamesvcs.GpgsClient.initialize(GpgsClient.java:117) 
at com.mygdx.game.AndroidLauncher.onCreate(AndroidLauncher.java:17) 
at android.app.Activity.performCreate(Activity.java:6285) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524) 
at android.app.ActivityThread.access$900(ActivityThread.java:154) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:234) 
at android.app.ActivityThread.main(ActivityThread.java:5526) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Suppressed: java.lang.ClassNotFoundException: android.support.v4.util.ArrayMap
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 16 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
D/FBAudienceNetwork: SDK dex loading time: 1514

GameCenter: UnsupportedOperationException on loadGameState()

Calling loadGameState() when more snapshots are available results in UnsupportedOperationException

java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:404)
at java.util.AbstractList.add(AbstractList.java:425)
at org.robovm.apple.foundation.NSArray.add(NSArray.java:267)
at de.golfgl.gdxgamesvcs.GameCenterClient$7.invoke(GameCenterClient.java:287)
at de.golfgl.gdxgamesvcs.GameCenterClient$7.invoke(GameCenterClient.java:261)

NSArray does not support adding elements.

GPGS Android: crash when no listener set

GPGS Android implementation does not check if a game service listener is set on all method calls. Therefore it crashes when login() or resumeConnection() is called and no listener is set.

Project doesn't build with gpg on android with build tools 28 / gradle 4.6

Recently I upgraded my Gradle version to 4.6 from 3.5.1.
But this annoying error appears:

Android resource linking failed
Output:  D:\Software\Entwicklung\TurbanGuy\android\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml:423: error: resource android:attr/preserveIconSpacing is private.
error: failed linking references.

Command: C:\Users\simon\.gradle\caches\transforms-1\files-1.1\aapt2-3.2.1-4818971-windows.jar\51876d9a334f74c9c5f25b354472a28b\aapt2-3.2.1-4818971-windows\aapt2.exe link -I\
        D:\Android-SDK\platforms\android-28\android.jar\
        --manifest\
        D:\Software\Entwicklung\TurbanGuy\android\build\intermediates\merged_manifests\debug\processDebugManifest\merged\AndroidManifest.xml\
        -o\
        D:\Software\Entwicklung\TurbanGuy\android\build\intermediates\processed_res\debug\processDebugResources\out\resources-debug.ap_\
        -R\
        @D:\Software\Entwicklung\TurbanGuy\android\build\intermediates\incremental\processDebugResources\resources-list-for-resources-debug.ap_.txt\
        --auto-add-overlay\
        --java\
        D:\Software\Entwicklung\TurbanGuy\android\build\generated\not_namespaced_r_class_sources\debug\processDebugResources\r\
        --custom-package\
        de.nta15.turbanguy.android\
        -0\
        apk\
        --output-text-symbols\
        D:\Software\Entwicklung\TurbanGuy\android\build\intermediates\symbols\debug\R.txt\
        --no-version-vectors
Daemon:  AAPT2 aapt2-3.2.1-4818971-windows Daemon #0

I found the source in gamesvcs-android-gpgs.
Because if I comment the line compile "de.golfgl.gdxgamesvcs:gdx-gamesvcs-android-gpgs:$gamesvcsVersion" in my project, I can build it.

I use libgdx 1.9.8 and gdx-gamesvcs 0.2.3.

App Missing Runtime Dependencies

I seem to be running into runtime errors when attempting to integrate this library. The below exception is thrown when I startup my app on my Galaxy S6, and I receive no other information.

05-04 17:20:26.101 6291-6291/com.niftysoft.tweeter E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.niftysoft.tweeter, PID: 6291
    java.lang.IllegalStateException: A fatal developer error has occurred. Check the logs for further information.
        at com.google.android.gms.common.internal.zzj$zza.zzc(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zza.zzw(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zzc.zzqN(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zzb.handleMessage(Unknown Source)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

People on the interwebs say this is an issue with missing dependencies... I know you haven't updated past Google Play 8.4.0... could this be the root cause? How would I include the missing libs along with my apk?

But I've checked and the example app doesn't seem to require that any additional dependencies
are configured in gradle.build. I've tried adding some of the Google Play Services dependencies as described here anyway, but they do not resolve the issue.

Also ,this only happens on actual devices, everything seems to work fine on the emulator.

EDIT: Below are full logs:

05-04 17:33:31.172 3677-7895/? V/InputMethodManagerService: windowGainedFocus: reason=WINDOW_FOCUS_GAIN client=android.os.BinderProxy@e9a171c inputContext=com.android.internal.view.IInputContext$Stub$Proxy@c80a823 missingMethods= attribute=android.view.inputmethod.EditorInfo@4147120 nm = com.niftysoft.tweeter controlFlags=#105 softInputMode=#120 windowFlags=#1810500
    Unspecified window will hide input
05-04 17:33:31.208 4145-4145/? D/SwipeDoorsillDetector: reset()com.android.systemui.statusbar.phone.NotificationPanelView.resetViews:864 com.android.systemui.statusbar.phone.PanelBar.collapsePanel:173 com.android.systemui.statusbar.phone.PhoneStatusBar.setWindowState:4347 com.android.systemui.statusbar.CommandQueue$H.handleMessage:678 
05-04 17:33:31.254 11186-11186/com.niftysoft.tweeter E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.niftysoft.tweeter, PID: 11186
    java.lang.IllegalStateException: A fatal developer error has occurred. Check the logs for further information.
        at com.google.android.gms.common.internal.zzj$zza.zzc(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zza.zzw(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zzc.zzqN(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zzb.handleMessage(Unknown Source)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
05-04 17:33:31.265 3677-4855/? D/ActivityManager: setFocusStackUnchecked: reason=finishActivity adjustFocus setFocusedActivity focusCandidate=ActivityStack{8ad9423d0 stackId=0, 1 tasks} caller=com.android.server.am.ActivityStack.moveToFront:877 com.android.server.am.ActivityStackSupervisor.moveActivityStackToFront:2006 
05-04 17:33:31.358 3677-3702/? I/WindowManager_SurfaceController: Destroying surface Surface(name=Starting com.niftysoft.tweeter) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.removeLocked:1867 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:2934 com.android.server.wm.AppWindowToken.destroySurfaces:427 com.android.server.wm.AppWindowToken.destroySurfaces:388 com.android.server.wm.WindowStateAnimator.finishExit:686 com.android.server.wm.WindowStateAnimator.stepAnimationLocked:570 
05-04 17:33:35.126 3677-4985/? D/ApplicationPolicy: isStatusBarNotificationAllowedAsUser: packageName = com.android.systemui,userId = -1
05-04 17:33:42.307 3677-3694/? I/WindowManager_SurfaceController: Destroying surface Surface(name=SurfaceView - com.niftysoft.tweeter/com.niftysoft.tweeter.AndroidLauncher) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.removeLocked:1867 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:2934 com.android.server.wm.WindowManagerService.removeWindowLocked:2879 com.android.server.wm.WindowManagerService.removeWindowLocked:2689 com.android.server.wm.AppWindowToken.removeAllWindows:608 com.android.server.wm.AppWindowToken.removeAppFromTaskLocked:370 
05-04 17:33:42.330 3677-3694/? I/WindowManager_SurfaceController: Destroying surface Surface(name=com.niftysoft.tweeter/com.niftysoft.tweeter.AndroidLauncher) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.removeLocked:1867 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:2934 com.android.server.wm.WindowManagerService.removeWindowLocked:2879 com.android.server.wm.WindowManagerService.removeWindowLocked:2689 com.android.server.wm.AppWindowToken.removeAllWindows:608 com.android.server.wm.AppWindowToken.removeAppFromTaskLocked:370 
05-04 17:33:45.628 3677-3702/? I/WindowManager_SurfaceController: Destroying surface Surface(name=Application Error: com.niftysoft.tweeter) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.destroyOrSaveSurface:2705 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementInner:503 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:278 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:226 com.android.server.wm.WindowManagerService$H.handleMessage:9324 android.os.Handler.dispatchMessage:102 
05-04 17:33:50.318 3677-3985/? E/WifiWatchdogStateMachine: Unhandled message { when=-1ms what=135229 target=com.android.internal.util.StateMachine$SmHandler } in state ValidNonSwitchableState
05-04 17:33:54.969 11358-11358/? D/AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
05-04 17:33:55.296 11358-11358/? D/AndroidRuntime: Calling main entry com.android.commands.pm.Pm
05-04 17:33:55.318 3677-3985/? E/WifiWatchdogStateMachine: Unhandled message { when=-1ms what=135238 target=com.android.internal.util.StateMachine$SmHandler } in state ValidNonSwitchableState
05-04 17:33:56.274 11402-11402/? D/AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
05-04 17:33:56.507 11402-11402/? D/AndroidRuntime: Calling main entry com.android.commands.pm.Pm
05-04 17:33:56.512 11402-11410/? W/MessageQueue: Handler (android.os.Handler) {e2546a6} sending message to a Handler on a dead thread
    java.lang.IllegalStateException: Handler (android.os.Handler) {e2546a6} sending message to a Handler on a dead thread
        at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543)
        at android.os.Handler.enqueueMessage(Handler.java:643)
        at android.os.Handler.sendMessageAtTime(Handler.java:612)
        at android.os.Handler.sendMessageDelayed(Handler.java:582)
        at android.os.Handler.post(Handler.java:338)
        at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:57)
        at com.android.internal.os.IResultReceiver$Stub.onTransact(IResultReceiver.java:58)
        at android.os.Binder.execTransact(Binder.java:573)
05-04 17:33:59.492 11414-11414/? D/AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
05-04 17:33:59.495 11416-11416/? D/AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
05-04 17:33:59.779 11416-11416/? D/AndroidRuntime: Calling main entry com.android.commands.am.Am
05-04 17:33:59.780 11414-11414/? D/AndroidRuntime: Calling main entry com.android.commands.wm.Wm
05-04 17:34:00.551 11437-11437/? D/AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
05-04 17:34:00.820 11437-11437/? D/AndroidRuntime: Calling main entry com.android.commands.am.Am
05-04 17:34:00.848 3677-3745/? D/ActivityManager: moveToFront() : reason=startedActivity setFocusedActivity isAttached=true TaskRecord{2bdf141d0 #15791 A=com.niftysoft.tweeter U=0 StackId=1 sz=1}
    setFocusStackUnchecked: reason=startedActivity setFocusedActivity focusCandidate=ActivityStack{8a6ba6ed0 stackId=1, 4 tasks} caller=com.android.server.am.ActivityStack.moveToFront:877 com.android.server.am.ActivityStackSupervisor.moveActivityStackToFront:2006 
05-04 17:34:00.975 3677-29269/? I/WindowManager_SurfaceController: Destroying surface Surface(name=com.teslacoilsw.launcher/com.teslacoilsw.launcher.NovaLauncher) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.destroyOrSaveSurface:2705 com.android.server.wm.WindowManagerService.tryStartExitingAnimation:3577 com.android.server.wm.WindowManagerService.relayoutWindow:3433 com.android.server.wm.Session.relayout:240 android.view.IWindowSession$Stub.onTransact:288 com.android.server.wm.Session.onTransact:161 
05-04 17:34:01.844 3677-4031/? V/InputMethodManagerService: windowGainedFocus: reason=WINDOW_FOCUS_GAIN client=android.os.BinderProxy@c44acb1 inputContext=com.android.internal.view.IInputContext$Stub$Proxy@1ab967a missingMethods= attribute=android.view.inputmethod.EditorInfo@a446e2b nm = com.niftysoft.tweeter controlFlags=#105 softInputMode=#120 windowFlags=#1810500
    Unspecified window will hide input
05-04 17:34:01.858 4145-4145/? D/SwipeDoorsillDetector: reset()com.android.systemui.statusbar.phone.NotificationPanelView.resetViews:864 com.android.systemui.statusbar.phone.PanelBar.collapsePanel:173 com.android.systemui.statusbar.phone.PhoneStatusBar.setWindowState:4347 com.android.systemui.statusbar.CommandQueue$H.handleMessage:678 
05-04 17:34:01.970 11450-11450/com.niftysoft.tweeter E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.niftysoft.tweeter, PID: 11450
    java.lang.IllegalStateException: A fatal developer error has occurred. Check the logs for further information.
        at com.google.android.gms.common.internal.zzj$zza.zzc(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zza.zzw(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zzc.zzqN(Unknown Source)
        at com.google.android.gms.common.internal.zzj$zzb.handleMessage(Unknown Source)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
05-04 17:34:01.980 3677-3900/? D/ActivityManager: setFocusStackUnchecked: reason=finishActivity adjustFocus setFocusedActivity focusCandidate=ActivityStack{8ad9423d0 stackId=0, 1 tasks} caller=com.android.server.am.ActivityStack.moveToFront:877 com.android.server.am.ActivityStackSupervisor.moveActivityStackToFront:2006 
05-04 17:34:02.025 3677-3702/? I/WindowManager_SurfaceController: Destroying surface Surface(name=Starting com.niftysoft.tweeter) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.removeLocked:1867 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:2934 com.android.server.wm.AppWindowToken.destroySurfaces:427 com.android.server.wm.AppWindowToken.destroySurfaces:388 com.android.server.wm.WindowStateAnimator.finishExit:686 com.android.server.wm.WindowStateAnimator.stepAnimationLocked:570 
05-04 17:34:04.213 3677-3842/? V/SamsungAlarmManager: Sending to uid : 1001 action=com.android.internal.telephony.data-stall alarm=Alarm{3b7b31d type 3 when 4916074 com.android.phone}
05-04 17:34:12.990 3677-3694/? I/WindowManager_SurfaceController: Destroying surface Surface(name=SurfaceView - com.niftysoft.tweeter/com.niftysoft.tweeter.AndroidLauncher) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.removeLocked:1867 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:2934 com.android.server.wm.WindowManagerService.removeWindowLocked:2879 com.android.server.wm.WindowManagerService.removeWindowLocked:2689 com.android.server.wm.AppWindowToken.removeAllWindows:608 com.android.server.wm.AppWindowToken.removeAppFromTaskLocked:370 
05-04 17:34:13.011 3677-3694/? I/WindowManager_SurfaceController: Destroying surface Surface(name=com.niftysoft.tweeter/com.niftysoft.tweeter.AndroidLauncher) called by com.android.server.wm.WindowStateAnimator.destroySurface:2907 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:1120 com.android.server.wm.WindowState.removeLocked:1867 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:2934 com.android.server.wm.WindowManagerService.removeWindowLocked:2879 com.android.server.wm.WindowManagerService.removeWindowLocked:2689 com.android.server.wm.AppWindowToken.removeAllWindows:608 com.android.server.wm.AppWindowToken.removeAppFromTaskLocked:370 
05-04 17:34:16.641 3677-3985/? E/WifiWatchdogStateMachine: Unhandled message { when=0 what=135229 target=com.android.internal.util.StateMachine$SmHandler } in state ValidNonSwitchableState
05-04 17:34:21.642 3677-3985/? E/WifiWatchdogStateMachine: Unhandled message { when=-1ms what=135238 target=com.android.internal.util.StateMachine$SmHandler } in state ValidNonSwitchableState

Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'fewZBzlAIBvWOuukVqyWKzOi'

I have a problem with this branch: https://github.com/MrStahlfelge/gdx-gamesvcs-app/tree/feature/gpgs

I bring it up, because it is based off this repository. I can not seem to feed the "Client ID" to the "gpgs" version of a Desktop build. It only feeds the "secret". Here is my shortened version: https://github.com/shatterblast/gdx-gamesvcs-app/tree/feature/gpgs

Thank you for your efforts!

GPGS Desktop implementation

As discussed here : http://www.badlogicgames.com/forum/viewtopic.php?f=17&t=26608&p=104851&hilit=gamesvcs#p104851 I'm working on GPGS Desktop implementation and I have something working pretty well. I'll PR you when all will be clean.

You can have a look at my dev branch https://github.com/mgsx-dev/gdx-gamesvcs/tree/desktop-gpgs
there is a test GUI (GpgsClientTest) if you want.

If you don't mind, I will use this issue to ask some questions about how to implements it correctly and make some suggestions about current API and other implementations.

Threading

I understand your concept of "fire and forget" : user code call a methods and get result in listener but ...

Questions :

  • Is IGameServiceClient implementations have to be thread safe ? my opinion is it don't have to be.
  • Is IGameServiceClient implementations have to be called in GLThread ? my opinion is it don't have to be.
  • Is IGameServiceClient implementations have to be non blocking ? that is process things in background. My opinion is it shouldn't (see below).

While underlying library may do things in background (activity intent in android...), I think GameServiceClient should never spawn threads itself, it is the user code responsibility to do it, to not doing it, to parallelize some tasks or chaining multiple calls in a single background thread and synchronize things if needed.

It is not really clear what implementation is supposed to do. I looked your android-gpgs implementation and most of methods are blocking except the load/save game state. I don't understand why mixing up blocking and non blocking parts.

I need more information on this before continue my implementation.

Packaging

I saw all implementation in the same package (de.golfgl.gdxgamesvcs) which may conflicts if you use multiple implementations in the same app (I may want to use both GPGS android and GPGS REST in my application).

I suggest to use the convention : de.golfgl.gdxgamesvcs.[service].[platform]

Versionning

I saw that android-gpgs-0.0.1 depends on android-0.0.1-SNAPSHOT ... have to wait the next release to be solved :-/

I see also that next release is 0.1.1 and not 0.1.0 ... maybe a mistake ?

and another quick question : what VCS stand for ? :-)

Features

In my original implementation, I have features that i can't implements with your API like :

  • listing all achievements
  • fetching leaderboards
  • list game states
  • delete game state

I understand that android implementation delegates a lot to google play activity but it won't be the case for other implementations. Maybe API is too tight to GPGS concepts and workflow ... It could be a little more abstract in my opinion, what do you think ?

I hope you dont't take all my remarks too badly because even if there is some things to fix up, current API is globally usable.

android-gpgs: GpgsClient using deprecated Google APIs

Hello,

I've been using your library for integrating Google Play Services to my game project, and it has been working fine when I'm running it on desktop (using desktop-gpgs module implementation). Leaderboards work as they should etc. However I noticed that on Android the leaderboards seem to respond with an empty payload even though the leaderboard id is correct, it is published and there are scores in it. I'm not sure if I'm using the library incorrectly or not, but here are my two cents that came to mind.

I downloaded the source code and checked that what's happening when I trigger fetchLeaderboardEntries method. The library is using deprecated Google APIs. For example, Games.Leaderboards.loadTopScores on line 477 of android-gpgs / GpgsClient.java has been deprecated since 2020-11-09. One should migrate to LeaderboardsClient instead.

There were other deprecated method calls within the client also that should be checked. Maybe using these deprecated APIs is causing some issues on android?

Also on another note I noticed that when fetching the leaderboards the timespan of the scores is hardcoded to be ALL_TIME. It would be great if you could specify the timespan yourself (DAILY, WEEKLY, ALL_TIME) so it would be possible to implement daily, weekly and all time leaderboards easily. It would be easy to implement by adding a new argument timespan of type integer in to the mix.

Thanks again for the good library. I'm not sure tho if this project is active anymore but if you could consider refactoring the android gpgs client code to use the up-to-date APIs it would be greatly appreciated.

image

GPGS Android: Disconnect from service while saving leads to crash

In very rare cases, app crashes with the following cause:

java.lang.IllegalStateException:
com.google.android.gms.games.internal.api.SnapshotsImpl.commitAndClose (SnapshotsImpl.java)
or .open$70b7f367 (SnapshotsImpl.java)
at de.golfgl.gdxgamesvcs.GpgsClient..saveGameStateSync (GpgsClient.java)
at de.golfgl.gdxgamesvcs.GpgsClient$4.doInBackground (GpgsClient.java)

This is probably caused by disconnecting from GPGS while cloud save is still running.

There are two possible approaches to prevent this crash:

  1. do not disconnect while cloud save is running
  2. catch the exception and return failed cloud save

Documentation has incorrect version label

In the Apple Game Center the documentation states:

implementation "de.golfgl.gdxgamesvcs:gdx-gamesvcs-ios-gamecenter:$gamsvcsVersion"

and in the main doc it states:

gamesvcsVersion = '1.1.0'

It took me a bit too long time to realize that there is a missing 'e' in the first line. Anyone following in my footsteps will probably save some time of those strings match.

GPGS Desktop: SEVERE: unable to refresh token, Help?

Hi I am using you wonderful library and had everything working for a long time until recently I was working on cloud saves.

I got a message in console along the lines of 'two files with the same name found' when calling saveGameState(). I checked using fetchSaveStates() and sure enough there were two files with the same name (which should not happen if I am correct?) Then the desktop version stopped connecting to google play services(mobile version still is working), with the following error messages. Any help if you can understand the reason behind this problem would be very appreciated?

p.s. I tried deleting the save states but this did not help and I tried deleting the old id and creating a new OAuth 2.0 client ID for the desktop version using developer console website and re-downloaded the json file secret key, but this did not seem to help at all....

---This error only appeared once
May 09, 2018 6:26:55 PM com.google.api.client.auth.oauth2.Credential handleResponse SEVERE: unable to refresh token com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request { "error" : "invalid_grant", "error_description" : "Token has been expired or revoked." } at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105) at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287) at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307) at com.google.api.client.auth.oauth2.Credential.executeRefreshToken(Credential.java:570) at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489) at com.google.api.client.auth.oauth2.Credential.handleResponse(Credential.java:272) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1015) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469) at de.golfgl.gdxgamesvcs.GpgsClient.waitForUserAuthorization(GpgsClient.java:265) at de.golfgl.gdxgamesvcs.GpgsClient.access$100(GpgsClient.java:67) at de.golfgl.gdxgamesvcs.GpgsClient$2.run(GpgsClient.java:305) at java.lang.Thread.run(Thread.java:748)

---This error occurs every time now when trying to connect the desktop version
gsShowErrorToUser: : errorLoginFailed: Request to Google API failed.

ERROR while show leaderboards

Hi

First, thanks for the your work

I'm using your library in my game and getting an error when I call the gsClient.showLeaderboards() method

image

The code i am using in AndroidLauncher:

public class AndroidLauncher extends AndroidApplication {

	private GpgsClient gpgsClient;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		AsteroidBustersXGame game = new AsteroidBustersXGame();

		this.gpgsClient = new GpgsClient()
				.setGpgsLeaderboardIdMapper(new IGameServiceIdMapper<String>() {

					@Override
					public String mapToGsId(String independantId) {
						return GpgsMappers.mapToGpgsLeaderboard(independantId);
					}
				})
				.initialize(this, false);
		game.gsClient = gpgsClient;

		AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
		config.useAccelerometer = false;
		config.useCompass = false;
		config.useImmersiveMode = true;
		initialize(game, config);
	}
}

Main Game Class create() method:

if (gsClient == null) {
	Gdx.app.log("GS_CLIENT", "GsClient is null");
	gsClient = new MockGameServiceClient(1) {
		@Override
		protected Array<ILeaderBoardEntry> getLeaderboardEntries() {
			return null;
		}

		@Override
		protected Array<String> getGameStates() {
			return null;
		}

		@Override
		protected byte[] getGameState() {
			return new byte[0];
		}

		@Override
		protected Array<IAchievement> getAchievements() {
			return null;
		}

		@Override
		protected String getPlayerName() {
			return null;
		}
	};
}

Gdx.app.log("GS_CLIENT", "GsClient set listener");
gsClient.setListener(this);

//My game initialization

Gdx.app.log("GS_CLIENT", "GsClient resume session");
gsClient.resumeSession();

Where I call showLeaderboards() method:

highscoresButton = new ImageButton(highscoresStyle);
highscoresButton.addListener(new ClickListener() {

    @Override
    public void clicked(InputEvent event, float x, float y) {
        try {
            game.gsClient.showLeaderboards(LEADERBOARD1);
        }
        catch (GameServiceException e) {
            Gdx.app.error("GS_CLIENT", "Failed to show leaderboards", e);
        }
    }
});

GpgsMappers class:

public class GpgsMappers {

    public static String mapToGpgsLeaderboard(String leaderboardId) {
        String gpgsId = null;

        if (leaderboardId != null) {
            if (leaderboardId.equals(AsteroidBustersXGame.LEADERBOARD1))
                gpgsId = "CgkIjOjVy8gdEAIQAQ";
        }

        return gpgsId;
    }
}

I also have a version of gdx 1.10.0, in the example its - 1.9.8. Most likely the problem is somewhere else.

Authorization passes - a welcome gpgs popup window appears with my username, but when click 'Highscores' it's load gpgs highscores page, but loading is freezing

Thanks in advance

GameJolt: Cloud save

Cloud save is supported by GameJolt, but not yet implemented in the API client.

GPGS Android: UserRecoverableAuthException: NeedPermission

I configured my app by Wiki and Google Play Services sdocumentation, but I cannot to sign in
I get the following message in logcat:

W/GamesAuthenticator: Failed to sign in silently
    com.google.android.gms.auth.UserRecoverableAuthException: NeedPermission

How to fix this error?

Rename core interface methods to clarify their purposes

The core's interface main methods root on a connection/session model based on GPGS Android which was this libraries first implementation.

However, GPGS is special in the case that the service is only available when the GoogleApiClient is "connected", which is no technical connection to the service cloud backend but just an active user session on a users device. Therefore, the methods resuming, pausing and checking the user session are named connect(), disconnect(), isConnected() in v0.1 of the interface, following the names from GoogleApiClient.

Other services do not need a user session for certain functionalities like fetching leader board entries, but of course they need a technical connection to the service's servers. This technical connection is not opened with connect() and closed with disconnect() - it is just an user session that is opened or closed when calling this methods. It is up to the service API implementation how the technical connection is made and when it is opened and closed (in most cases, the REST API implementations do not hold a connection, but just open a connection for querying or submitting data).

The JavaDocs on the methods state this correctly, however, the names of the methods lead to confusion, so they should be renamed. Suggestions are:

IGameServiceClient:
connect(true) to resumeSession()
connect(false) to logIn()
disconnect() to pauseSession()
isConnected() to isSessionActive()

IGameServliceListener:
gsConnected() to gsOnSessionActive()
gsDisconnected() to gsOnSessionInactive()
gsError() to gsShowErrorToUser()

NotConnectedExceptionto NoSessionException

Cannot log in Google Play Services when cloud save enabled

Since couple of days ago, I'm not able to log my app into the Google Play Services. I'm getting this trace in the logs:
E/Auth: [GoogleAccountDataServiceImpl] getToken() -> NETWORK_ERROR. Account: <ELLIDED:-827796636>, App: com.teenagemutantninjacoders.robotwarehouse.android.dev, Service: oauth2:https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/games_lite
It looks like it's really a Google problem, but as I'm not seeing any recent complaint on that, I was wondering if the library is simply using some deprecated API?

GameCenter Cloud save error 27

When activitating cloud save for Apple Game Center, it does not work and the following error is printed to console output:

Error Domain=GKErrorDomain Code=27 "The requested operation could not be completed because you are not signed in to iCloud" UserInfo=0x1889f160 {NSLocalizedDescription=The requested operation could not be completed because you are not signed in to iCloud}

The player is signed in. All other parts of Game Center are working fine in the game.

Same issue as in https://forums.developer.apple.com/thread/112716

GPGS Android: Cloud Save - Gamestate Not Null?

I am having another issue which you may have a better understanding of, even when all snapshots are deleted from google play services I keep getting an object back of length 0 when calling gsClient.loadGameState().....

Steps:
-call gsClient.deleteGameState() on desktop, exit app
-call gsClient.loadGameState() multiple times on desktop always returning null which is ok, exit app
-call gsClient.loadGameState() on android first call returns null all following calls return an array with length 0, exit app
-call gsClient.loadGameState() on desktop again and return is an array with length 0

very strange as I am not saving anything at all, maybe I am missing something?

public void loadSnapshot(){

      if(gsClient.isFeatureSupported(GameServiceFeature.GameStateStorage)) {

         gsClient.loadGameState("test", this);
      }
      else{
         Gdx.app.error("loadSnapshot: ", "GameStateStorage not supported by client");
      }
   }
   @Override
   public void gsGameStateLoaded(byte[] gameState) {

      if(gameState != null){

         Gdx.app.error("onGameStateLoaded", "gamestate size is =" + gameState.length);
      }
      else{

         Gdx.app.error("onGameStateLoaded", "gamestate is null" );
      }

   }

UPDATED:
From lidgdx forum pm discussion with MrStahlfelge:

" It is probably because Android's GPGS gamestate creates a subdirectory causing the desktop implementation to return a 0-sized array (because there is something but no file)."

I guess the issue still remains that on android platform the returned value is not consistent with what is expected and the data can be null or invalid/reference to some empty object....?

loadGameState and saveGameState need designated callback interfaces

If loadGameState is performed, the loaded game state response comes back on the main game service listener's gsGameStateLoaded(byte[] gameState) method.

This does not fit in any case: If several game states are used, and if the cloud sync feature is not used at all the method declaration is not necessary.

The method should be moved to an own interface and the response listener should be paramatrized on the loadGameState call.

Also, saveGameState should get a callback interface for returning if operation was performed and if it was successful.

Use of deprecated androidx.fragment:fragment:1.0.0

The following might be related to #45.

When publishing an Android app that uses your (great! ❤️ ) library for using GPGS, it shows the following waring:

Your latest production release [...] contains SDK issues

  • androidx.fragment:fragment:1.0.0
  • This SDK version has been reported as outdated. Consider upgrading to a newer version (1.1.0+).

Learn more

And after brief investigation of my projects dependencies (e.g. via ./gradlew :android:dependencies), it looks like the use of androidx.fragment:fragment:1.0.0 is coming indirectly from this library:

...
+--- de.golfgl.gdxgamesvcs:gdx-gamesvcs-android-gpgs:1.1.0
|    +--- com.google.android.gms:play-services-games:16.0.0
|    |    +--- com.google.android.gms:play-services-base:16.0.1 -> 18.0.0
|    |    |    +--- androidx.collection:collection:1.0.0
|    |    |    |    \--- androidx.annotation:annotation:1.0.0 -> 1.6.0
|    |    |    |         \--- androidx.annotation:annotation-jvm:1.6.0
|    |    |    |              \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.0 -> 1.8.21
|    |    |    |                   +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21
|    |    |    |                   \--- org.jetbrains:annotations:13.0 -> 23.0.0
|    |    |    +--- androidx.core:core:1.2.0
|    |    |    |    +--- androidx.annotation:annotation:1.1.0 -> 1.6.0 (*)
|    |    |    |    +--- androidx.lifecycle:lifecycle-runtime:2.0.0
|    |    |    |    |    +--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.1.0
|    |    |    |    |    |    \--- androidx.annotation:annotation:1.1.0 -> 1.6.0 (*)
|    |    |    |    |    +--- androidx.arch.core:core-common:2.0.0 -> 2.1.0
|    |    |    |    |    |    \--- androidx.annotation:annotation:1.1.0 -> 1.6.0 (*)
|    |    |    |    |    \--- androidx.annotation:annotation:1.0.0 -> 1.6.0 (*)
|    |    |    |    \--- androidx.versionedparcelable:versionedparcelable:1.1.0
|    |    |    |         +--- androidx.annotation:annotation:1.1.0 -> 1.6.0 (*)
|    |    |    |         \--- androidx.collection:collection:1.0.0 (*)
|    |    |    +--- androidx.fragment:fragment:1.0.0
...

Not sure how critical this is. And whether Google Play Store will at some point start rejecting apps that uses deprecated/obsolete/outdated libraries.

But maybe 🤞 this is just about bumping the com.google.android.gms:play-services-games a little?

GPGS end of support for some features

As stated here : https://android-developers.googleblog.com/2017/04/focusing-our-google-play-games-services.html GPGS will end support for Gift, Quests and Requests.

Current API define a submitEvent feature which is if I'm right related to quests for GPGS implementation.

Since other services provide events, you could add a feature query like "idEventSupported" ?

For this reason, I won't implement the submitEvent method in the desktop implementation.

What do you think ?

wiki update

not an issue, really, but a minor edit as I went through the configuration of this awesome library:

in this wiki page: https://github.com/MrStahlfelge/gdx-gamesvcs

For core in the build.gradle, instead of :
compile "de.golfgl.gdxgamesvcs:gdx-gamesvcs-core:$gamesvcsVersion"
I used
api "de.golfgl.gdxgamesvcs:gdx-gamesvcs-core:$gamesvcsVersion"
(compile was showing "obsolete")

same thing for for iOS, in this page: https://github.com/MrStahlfelge/gdx-gamesvcs/wiki/Apple-Game-Center

but for Android, I used "implementation" instead of API.

I used LibGDX 1.10.0

Getting a unique User ID

It seems not possible to identify an user with his login, for example to store game data in an external database?

There is the function "getPlayerDisplayName()" but the display name is not unique.

A function like "getPlayerID()" would be useful and should be easily to implement, for example for google:
String getPlayerID() { return Games.Players.getCurrentPlayerId(mGoogleApiClient); }

for Apple Gamecenter:
public String getPlayerID() { return isSessionActive() ? GKLocalPlayer.getLocalPlayer().gamePlayerID() : null; }

GPGS Android: fetchLeaderboardEntries returns same values

On my android phone, the leaderboard entries are always the same. If there are new values in the Google Play Games App, the old are given by fetchLeaderboardEntries, even if I clear the storage of my App. On the desktop are the entries up-to-date.

Google Play Services has stopped

Hi,
First thanks for your very good jobs about gdx-gamesvcs!
I need to implement Google Play Services in my libgdx project but, i have an error. When the user click on the button, the Google UI appear with animation and when the loading show up i have a popup with this error "Google Play Services has stopped" and after "the application is having problems ...". After this, the app return always isConnectionPending() equal true.

I saw your code example here https://github.com/MrStahlfelge/gdx-gamesvcs-app/blob/feature/gpgs/core/src/de/golfgl/gdxgamesvcsapp/GdxGameSvcsApp.java, and my code it almost the same (just, in AndroidLauncher i don't have mapToGsId and @OverRide things because GpgsMappers doesn't exist in the last version of gdx-gamesvcs).

So, of course, i watched on the Google Play Console my configuration. But, i don't know where I could have a configuration problem. My app is in Beta only and i ticked in the game service configuration "allow Alpha & Beta users". I tested with release signed apk and link (associated application) my service with my app in Play Console and app_id is defined. I don't understand ...

The problem is present on all devices that have the game.
You have an idea?

Thank you for your answer, have a nice day.

Crash on first start after deleting data

10-16 20:52:17.750 19029 19053 E Volley  : [5773] bmi.a: Unexpected response code 401 for https://www.googleapis.com/games/v1/applications/************?language=hu-HU&platformType=ANDROID
10-16 20:52:18.491 19029 19500 E SignInPerformer-6: Failed to load game for package [****************] [CONTEXT service_id=1 ]
10-16 20:52:18.507 18146 18146 E AndroidRuntime: FATAL EXCEPTION: main
10-16 20:52:18.507 18146 18146 E AndroidRuntime: Process: ******, PID: 18146
10-16 20:52:18.507 18146 18146 E AndroidRuntime: java.lang.IllegalStateException: A fatal developer error has occurred. Class name: zzf. Start service action: com.google.android.gms.games.service.START. Service Descriptor: com.google.android.gms.games.internal.IGamesService. 
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at com.google.android.gms.common.internal.BaseGmsClient$zza.zza(Unknown Source)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at com.google.android.gms.common.internal.BaseGmsClient$zzc.zzo(Unknown Source)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at com.google.android.gms.common.internal.BaseGmsClient$zzb.handleMessage(Unknown Source)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:102)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:154)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:6682)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
10-16 20:52:18.507 18146 18146 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

Steps to reproduce:

  1. Connect the app to Play Games
  2. Save data to the cloud
  3. Open Play Games and delete app data there
  4. Open the game
  5. Crash

Not really a big deal though because everything works after restarting the game, just an edge case.
I don't know if even fixable

Google Play Games Dektop

Hello,

I've integrated gdx-gamesvcs with Google Play Games in my project and it works on android. But on desktop, I'm getting this messages on start:

Feb 09, 2018 12:52:05 PM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNUNG: unable to change permissions for everybody: C:\Users\simon\.store\Turban Guy
Feb 09, 2018 12:52:05 PM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNUNG: unable to change permissions for owner: C:\Users\simon\.store\Turban Guy

And this messages when I try to log in:
gsShowErrorToUser errorLoginFailed Request to Google API failed.

I'm using gamesvcsVersion 0.2.2 and gdxVersion 1.9.8.
Thanks for your help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.