[pyjnius]Google Play Services and ResultCallback

130 views
Skip to first unread message

Damien Moore

unread,
Jul 21, 2016, 3:36:16 PM7/21/16
to Kivy users support
I am trying to get a player's leaderboard score from google play services.

The docs show that the method loadCurrentPlayerLeaderboardScore will do this, but that it does so asynchronously. 

The function returns an abstract class PendingResult object of type LoadPlayerScoreResult.

PendingResult has the method setResultCallback that let's me set the callback.

So the code I need, building off this example, is something like this:

result = Games.Leaderboards.loadCurrentPlayerLeaderboardScore(self.client, settings.GOOGLE_PLAY_LEADERBOARD_IDS[name], Games.LeaderboardVariant.TIME_SPAN_ALL_TIME, Games.LeaderboardVariant.COLLECTION_PUBLIC)
result.setResultCallback(<RESULT_CALLBACK_OBJECT>)

My question is how does one specify the <RESULT_CALLBACK_OBJECT> to call a python function with the result. Does anyone have some sample code of what that might look like?


Antonio Cuni

unread,
Jul 21, 2016, 5:11:13 PM7/21/16
to kivy-...@googlegroups.com

According to the docs, you need to create a class which implements the ResultCallback interface.
Have a look to my xcamera widget to see an example of how to do it:
https://github.com/kivy-garden/garden.xcamera/blob/master/android_api.py


--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Damien Moore

unread,
Jul 21, 2016, 6:06:28 PM7/21/16
to Kivy users support
Thanks!!

Thanks. So to clarify I would do

class LoadPlayerScoreCallback(PythonJavaClass):
__javainterfaces__ = ('com.google.android.gms.common.api.ResultCallback',)

@java_method('(Lcom/Google/.../Leaderboards$LoadPlayerScoreResult;)')
def onResult(self, result):
#do stuff


Is my __javainterfaces__ correct? Is there somewhere other than the java_method that I need to specify the LoadPlayerScoreResult?

Damien Moore

unread,
Jul 22, 2016, 1:30:17 AM7/22/16
to Kivy users support
Small update. Here's my callback:

class GetScoreResultCallback(PythonJavaClass):
    __javainterfaces__ = ['com.google.android.gms.common.api.ResultCallback'
                            ]
    __javacontext__ = 'app'
    def __init__(self):
        super(GetScoreResultCallback, self).__init__()

                            
    # same error if I use this: @java_method('(Landroid/gms/games/leaderboard/Leaderboards$LoadPlayerScoreResult;)V')
    @java_method('(Landroid/gms/common/api/result;)V')
    def onResult(self, result):
        Logger.info('Score retrieved: %i'%result.getScore())


But I get the following error:

I/python  ( 1261): Python class:<googleplayservices.GetScoreResultCallback object at 0x63fe1df0>
I/python  ( 1261): Java method name:onResult
I/python  ( 1261): Signature: (Lcom/google/android/gms/common/api/Result;)V
I/python  ( 1261): =======================================
I/python  ( 1261):  Traceback (most recent call last):
I/python  ( 1261):    File "jnius/jnius_proxy.pxi", line 47, in jnius.jnius.PythonJavaClass.invoke (jnius/jnius.c:29223)
I/python  ( 1261):    File "jnius/jnius_proxy.pxi", line 71, in jnius.jnius.PythonJavaClass._invoke (jnius/jnius.c:29905)
I/python  ( 1261):  NotImplementedError: The method ('onResult', (u'V', (u'Lcom/google/android/gms/common/api/Result;',))) is not implemented

Here's a Java example of what such a ResultCallback looks like:

ResultCallback<TurnBasedMultiplayer.InitiateMatchResult> cb = new ResultCallback<TurnBasedMultiplayer.InitiateMatchResult>() {
        @Override
        public void onResult(TurnBasedMultiplayer.InitiateMatchResult result) {
            processResult(result);
        }
    };
    Games.TurnBasedMultiplayer.createMatch(mGoogleApiClient, tbmc).setResultCallback(cb);


So it looks like I need to somehow specify the template parameters for my callback in the interface definition. Something like com.google.android.gms.common.api.ResultCallback<android/gms/games/leaderboard/Leaderboards$LoadPlayerScoreResult> 

Is such a thing supported in pyjnius? Am I making sense?

Antonio Cuni

unread,
Jul 22, 2016, 4:42:46 AM7/22/16
to kivy-...@googlegroups.com

I am sorry I cannot be of much help,I never had to do something like this. I suggest to decompile the correct java file to smali, so that you can see what is the correct signature


--

Damien Moore

unread,
Jul 22, 2016, 3:05:10 PM7/22/16
to Kivy users support
Thanks. After some more reading, it dawned on me that the ResultCallback is referred to as a "generic class". So my remaining question can be better phrased as does pjynius support generic class instances? If so then it is just a matter of getting the type signature right using say some bytecode as you suggest. But if generics aren't supported then I am wasting my time and will need to find a different way.

Damien Moore

unread,
Jul 23, 2016, 5:23:03 PM7/23/16
to Kivy users support
I have officially hit a dead end on subclassing a generic class/interface in pyjnius. It seems that this is a hard thing to do because of Java's type erasure.

I think the workaround for now will be to use a simple library that defines the classes I need from the generic classes. Is there a sample anywhere (like in the kivy garden) that shows how to include a minimal java library in a kivy project. I realized I could just whip something up using eclipse then copy it across to kivy, but I would prefer to do something more minimalist from the command line.

Damien Moore

unread,
Jul 24, 2016, 3:30:07 AM7/24/16
to Kivy users support
I finally came up with a work around. I hadn't realized how straightforward it is to integrate java files into the build.

It seems the pyjnius is extremely limited when it comes to working with generic and/or abstract classes and interfaces, both of which are used extensively in the play services API. If you implement your own classes in python you are basically limited to implementing interfaces and not extending existing Java classes. It also appears to be impossible to implement interfaces that extend other interfaces. The pyjnius docs needs to be clearer about this!!

Anyway, a couple of simple java files did the trick, which you can see here: https://github.com/spillz/SlideWords/tree/master/libs/play_interface


Next to see if I can get Google's turn-based multiplayer to work.
Reply all
Reply to author
Forward
0 new messages