From The Blog: Update on the new GPGS v2 plugin

Corona Labs would like to update you about our recent plugin for Google Play Games Services. This plugin is known as GPGS v2 and there is a breaking change to be aware of.

We’ve worked hard to make it call compatible with the older GPGS v1 plugin, however Google has changed their initialization and login process significantly. We had to make a change that you will need to adapt to so that you can successfully login and know if your app is connected.

Simply remove any calls to the gpgs.init() API and instead call gpgs.login() directly:

gpgs.login( { userInitiated=true, listener=gpgsLoginListener } )

Where gpgsLoginListener is the name of your function to handle a successful login. If you have questions about the plugin, please joins us in our community forums.

View the full article

I tried using this plugin, but I’m getting a crash when I try to show leaderboards or to submit scores to it.

Here’s the logcat:

D plugin.gpgs.v2: leaderboards.show() I Corona : ERROR: Runtime error I Corona : java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.ContextWrapper.getApplicationContext()' on a null object reference I Corona : Java Stack Trace: I Corona : plugin.gpgs.v2.Connector.getContext(Connector.java:58) I Corona : plugin.gpgs.v2.Connector.isConnected(Connector.java:50) I Corona : plugin.gpgs.v2.Utils.checkConnection(Utils.java:52) I Corona : plugin.gpgs.v2.Leaderboards.show(Leaderboards.java:278) I Corona : plugin.gpgs.v2.Leaderboards$4.invoke(Leaderboards.java:51) I Corona : com.ansca.corona.JavaToNativeShim.nativeTouchEvent(Native Method) I Corona : com.ansca.corona.JavaToNativeShim.touchEvent(JavaToNativeShim.java:430) I Corona : com.ansca.corona.input.RaiseTouchEventTask.executeUsing(RaiseTouchEventTask.java:39) I Corona : com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:170) I Corona : com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91) I Corona : com.ansca.corona.Controller.updateRuntimeState(Controller.java:318) I Corona : com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRen I Corona : ERROR: Runtime error I Corona : java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.ContextWrapper.getApplicationContext()' on a null object reference I Corona : Java Stack Trace: I Corona : plugin.gpgs.v2.Connector.getContext(Connector.java:58) I Corona : plugin.gpgs.v2.Connector.isConnected(Connector.java:50) I Corona : plugin.gpgs.v2.Utils.checkConnection(Utils.java:52) I Corona : plugin.gpgs.v2.Leaderboards.show(Leaderboards.java:278) I Corona : plugin.gpgs.v2.Leaderboards$4.invoke(Leaderboards.java:51) I Corona : com.ansca.corona.JavaToNativeShim.nativeTouchEvent(Native Method) I Corona : com.ansca.corona.JavaToNativeShim.touchEvent(JavaToNativeShim.java:430) I Corona : com.ansca.corona.input.RaiseTouchEventTask.executeUsing(RaiseTouchEventTask.java:39) I Corona : com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:170) I Corona : com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91) I Corona : com.ansca.corona.Controller.updateRuntimeState(Controller.java:318) I Corona : com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRenderer.onDrawFrame(CoronaGLSurfaceView.java:425) I Corona : com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1625) I Corona : com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1380) I Corona : stack traceback: I Corona : [C]: ? I Corona : [C]: in function 'show' I Corona : ?: in function 'showLeaderboards' I Corona : ?: in function '\_onEvent' I Corona : /Users/jenkins/slaveroot/workspace/Templates/label/android/subrepos/widget/widgetLibrary/widget\_button.lua:120: in function 'manageButtonTouch' I Corona : /Users/jenkins/slaveroot/workspace/Templates/label/android/subrepos/widget/widgetLibrary/widget\_button.lua:658: in function 'method' I Corona : /Users/jenkins/slaveroot/workspace/Templates/label/android/platform/resources/init.lua:221: in function \</Users/jenkins/slaveroot/workspace/Templates/label/android/platform/resources/init.lua:190\>

Any idea what could be causing this? It’s driving me crazy!

This is blocking my project from finishing.  :frowning:

Any help would be appreciated. 

I’ll see if I can get an engineer to look into this.

In the meantime can you share your code?

What version of Corona as you using?

Are you doing native builds or simulator builds?

What device and version of Android are you testing on?

Is the test device rooted?

Are you building with a release keystore or a debug keystore?

Are you sure you have everything set up correctly in your Google Play developer console?

Rob

Thank you for your response Rob.

Here’s the code leaderboard handler I created:

local isAndroid = false local isiOS = false local targetAppStore = system.getInfo( "targetAppStore" ) local leaderboardIDs = { "leaderboardid1", -- those are placeholder IDs for the purpose of this post. "leaderboardid2" -- In my code I have the real values from Play Store Console. } if ( "apple" == targetAppStore ) then -- iOS isiOS = true elseif ( "google" == targetAppStore ) then -- Android isAndroid = true local licensing = require( "licensing" ) local function licensingListener( event ) if not ( event.isVerified ) then native.showAlert( "Event!", "You're a pirate!", { "OK" } ) else native.showAlert( "Event!", "You're not a pirate!", { "OK" } ) end end local licensingInit = licensing.init( "google" ) if ( licensingInit == true ) then licensing.verify( licensingListener ) else end end local gameNetwork = nil local gpgs = nil if isiOS then gameNetwork = require( "gameNetwork" ) end if isAndroid then gpgs = require( "plugin.gpgs.v2" ) gpgs.enableDebug() end local m = {} local function initCallback( event ) if isAndroid then if not event.isError then if ( event.name == "init" ) then native.showAlert( "Submit Event!", "Init call back", { "OK" } ) gpgs.login( { userInitiated=true, listener=initCallback } ) elseif ( event.name == "login" ) then native.showAlert( "Submit Event!", "Login call back", { "OK" } ) end else native.showAlert( "Submit Event!", "Error in initcallback: "..event.name, { "OK" } ) end else native.showAlert( "Submit Event!", "Now android: "..event.name, { "OK" } ) end end function m.init() if m.didInit then return end m.didInit = true if isiOS then gameNetwork.init( "gamecenter", initCallback ) elseif isAndroid then gpgs.init(initCallback) end end function m.setTopScore( score, leaderboardIndex ) if isiOS then local categories = { "com.frikado.leaderboard.park", "com.frikado.leaderboard.room" } gameNetwork.request( "setHighScore", { localPlayerScore = { category=categories[leaderboardIndex], value=score }}) elseif isAndroid then local function submitCallback(event) native.showAlert( "Submit Event!", "Set Top Score", { "OK" } ) end gpgs.leaderboards.submit({ leaderboardId = leaderboardIDs[leaderboardIndex], score = score, listener = submitCallback }) end end function m.showLeaderboards() if isiOS then gameNetwork.show( "leaderboards" ) elseif isAndroid then local function showCallback(event) native.showAlert( "Show Event!", "Show Leaderboard", { "OK" } ) end gpgs.leaderboards.show({listener = showCallback}) end end return m

I tried with Corona versions 3326 and 3441. It’s happening with both.

I’m testing on a Galaxy S6 with Android 7.0; I also made sure to update Google Play Store Game Services form the play store before posting this. The device is not rooted.

I was initially signing with the app store key. After signing with the debug key I get the error saying:

attempt to call field ‘init’ (a nil value) // On the line where it says “gpgs.init(initCallback)” in the code above.

I went over the Google Play developer console requirements multiple times. Could anything related to that be causing the issue?

It’s worth mentioning that in the build.settings file I have

       [“plugin.gpgs.v2”] =

        {

            publisherId = “com.coronalabs”,

            supportedPlatforms = { android=true }

        },

Thank you for your help!

You should not call .init() with GPGS v2. Please see:

https://coronalabs.com/blog/2018/10/31/update-on-the-new-gpgs-v2-plugin/

I’d make that change and see if the issue goes away.

Rob

Oh right, I removed that, and I get:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.ContextWrapper.getApplicationContext()' on a null object reference

On both lines that call:

gpgs.leaderboards.submit({

and

gpgs.leaderboards.show({listener = showCallback})

Hi! First of all, before calling any methods from the plugin check the connection state because the result of isConnected() method can be false and you probably will get this error. Second, if you didn’t update your app at the https://play.google.com/apps/publish or at the https://console.developers.google.com/, or you didn’t set up the project completely, the plugin will not allow you to call the methods.

Probably this would help you with debugging your application

function m.setTopScore( score, leaderboardIndex ) if isiOS then local categories = { "com.frikado.leaderboard.park", "com.frikado.leaderboard.room" } gameNetwork.request( "setHighScore", { localPlayerScore = { category=categories[leaderboardIndex], value=score }}) elseif isAndroid then local function submitCallback(event) native.showAlert( "Submit Event!", "Set Top Score", { "OK" } ) end if gpgs.isConnected() then gpgs.leaderboards.submit({ leaderboardId = leaderboardIDs[leaderboardIndex], score = score, listener = submitCallback }) else native.showAlert('Is connected?', gpgs.isConnected() and 'Yes' or 'No', {'OK'}) end end end function m.showLeaderboards() if isiOS then gameNetwork.show( "leaderboards" ) elseif isAndroid then local function showCallback(event) native.showAlert( "Show Event!", "Show Leaderboard", { "OK" } ) end if gpgs.isConnected() then gpgs.leaderboards.show({listener = showCallback}) else native.showAlert('Is connected?', gpgs.isConnected() and 'Yes' or 'No', {'OK'}) end end end

Thanks for your reply Kirill, after trying your suggestion, I get the crash now on the line that calls this:

if gpgs.isConnected() then

I will go over the console stuff again.  :rolleyes:

Any updates?  :frowning:

Hello guys!

I know you are super busy but there are some issues with gpgs v2.

I use gpgs for saving / loading players progress.

Everything is fine with the old plugin.

With the new plugin:

  1. I don’t see the welcome and chose account boxes the first time (or ever) the app starts. Is it normal?

  2. If I delete / reinstall the game, I have to start the game twice until I get my progress back.

The first time fails to move to gpgsSnapshotOpenForReadListener function I guess.

Something wrong with my code?

I’m sorry, I don’t have time right now for logs but maybe someone ( Mr. Rob Miracle :slight_smile: ) could check my code.

  

-- build.settings ["plugin.gpgs.v2"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true } }, -- main.lua gpgs = require( "plugin.gpgs.v2" ) -- menu.lua local function gpgsSnapshotOpenForReadListener( event ) if not event.isError then local readlevels = gpgs.snapshots.getSnapshot (event.snapshotId) local prevlevels = json.decode( readlevels.contents.read() ) if prevlevels == nil then readlevels.contents.write( json.encode( makeallzero ) ) gpgs.snapshots.save({ snapshotId = event.snapshotId, listener = gpgsSnapshotAfter }) else if prevlevels \> nowlevels then saveFile("nowlevels.txt", prevlevels) end end end end local function gpgsLoginListener( event ) gpgs.snapshots.open({ filename = "save1", create = true, listener = gpgsSnapshotOpenForReadListener }) gpgs.snapshots.open({ filename = "save2", create = true, listener = gpgsSnapshotOpenForReadListener2 }) end gpgs.login( { userInitiated = true, listener = gpgsLoginListener } )

I believe there were multiple ways to deal with snapshots in the V1 plugin, but for V2, those seem to be a bit more limited. Consider this code:

local myTable = { play = 1 } local snapshotFilename = "snapshot1" local data = json.encode( myTable ) local function gpgsSnapshotOpenForReadListener( event ) print( "snapshot open event:", json.prettify(event) ) if not event.isError then local data = event.snapshot.contents.read() native.showAlert('Snapshots', 'Reading was ' .. (event.isError and 'unsuccessful' or 'successful') .. ',', { 'OK'}) end end local function gpgsSnapshotAfterSaveListener( event ) native.showAlert('Snapshots', 'Saving was ' .. (event.isError and 'unsuccessful' or 'successful') .. '.', {'OK'}) end function myData.openSnapshot() print("Opening snapshot") gpgs.snapshots.open({ filename = snapshotFilename, listener = gpgsSnapshotOpenForReadListener }) end local function gpgsSnapshotOpenForSaveListener( event ) print("open for save listener", json.prettify( event )) if not event.isError then event.snapshot.contents.write(data) -- Write new data as a JSON string into the snapshot gpgs.snapshots.save({ snapshot = event.snapshot, description = 'Save slot ' .. snapshotFilename, listener = gpgsSnapshotAfterSaveListener }) end end function myData.saveSnapshot() print("saving snapshhot") gpgs.snapshots.open({ -- Open the save slot filename = snapshotFilename, create = true, -- Create the snapshot if it's not found listener = gpgsSnapshotOpenForSaveListener }) end

Try this method of reading/writing snapshots.

Rob

Hi Rob,

There is a gpgs.multiplayer.realtime.show() function which _“Shows a view that will display a “waiting room” screen that shows the progress of participants joining a real-time multiplayer room”. _I’m using it and a waiting room is showed. Problem is how to close it programmatically before room is fully connected. Android documentation says: 

When a player clicks the  Start Playing  option, the waiting room UI is not automatically dismissed for the other players in the game. To dismiss the waiting room for the other players, your game should send a reliable real-time message to the other players to indicate that the game is starting early. When your game receives the message, it should dismiss the waiting room UI.

How should I dismiss the waiting room UI?

Thank you for your support

No replies?? :frowning:

This is the document for gpgs.multiplayer.realtime.show( params )

minPlayersRequired (optional)

Number. If desired, the waiting room can allow the user to start playing the game even before the room is fully connected, and this is controlled by the minPlayersRequiredparameter. If at least this many participants including the current player are connected to the room, a “start” menu item will be enabled in the waiting room UI. Setting minPlayersRequired to 0 means that the item will always be available, while omitting this parameter will disable the item entirely. Note that if you allow any user to start early, you’ll need to handle the situation by explicitly telling the other connected peers that the game is now starting.

 

Is there any example of how to tell the other connected peers that game is starting and dismiss the waiting UI?

 

Thank you

I tried using this plugin, but I’m getting a crash when I try to show leaderboards or to submit scores to it.

Here’s the logcat:

D plugin.gpgs.v2: leaderboards.show() I Corona : ERROR: Runtime error I Corona : java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.ContextWrapper.getApplicationContext()' on a null object reference I Corona : Java Stack Trace: I Corona : plugin.gpgs.v2.Connector.getContext(Connector.java:58) I Corona : plugin.gpgs.v2.Connector.isConnected(Connector.java:50) I Corona : plugin.gpgs.v2.Utils.checkConnection(Utils.java:52) I Corona : plugin.gpgs.v2.Leaderboards.show(Leaderboards.java:278) I Corona : plugin.gpgs.v2.Leaderboards$4.invoke(Leaderboards.java:51) I Corona : com.ansca.corona.JavaToNativeShim.nativeTouchEvent(Native Method) I Corona : com.ansca.corona.JavaToNativeShim.touchEvent(JavaToNativeShim.java:430) I Corona : com.ansca.corona.input.RaiseTouchEventTask.executeUsing(RaiseTouchEventTask.java:39) I Corona : com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:170) I Corona : com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91) I Corona : com.ansca.corona.Controller.updateRuntimeState(Controller.java:318) I Corona : com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRen I Corona : ERROR: Runtime error I Corona : java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.ContextWrapper.getApplicationContext()' on a null object reference I Corona : Java Stack Trace: I Corona : plugin.gpgs.v2.Connector.getContext(Connector.java:58) I Corona : plugin.gpgs.v2.Connector.isConnected(Connector.java:50) I Corona : plugin.gpgs.v2.Utils.checkConnection(Utils.java:52) I Corona : plugin.gpgs.v2.Leaderboards.show(Leaderboards.java:278) I Corona : plugin.gpgs.v2.Leaderboards$4.invoke(Leaderboards.java:51) I Corona : com.ansca.corona.JavaToNativeShim.nativeTouchEvent(Native Method) I Corona : com.ansca.corona.JavaToNativeShim.touchEvent(JavaToNativeShim.java:430) I Corona : com.ansca.corona.input.RaiseTouchEventTask.executeUsing(RaiseTouchEventTask.java:39) I Corona : com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:170) I Corona : com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91) I Corona : com.ansca.corona.Controller.updateRuntimeState(Controller.java:318) I Corona : com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRenderer.onDrawFrame(CoronaGLSurfaceView.java:425) I Corona : com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1625) I Corona : com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1380) I Corona : stack traceback: I Corona : [C]: ? I Corona : [C]: in function 'show' I Corona : ?: in function 'showLeaderboards' I Corona : ?: in function '\_onEvent' I Corona : /Users/jenkins/slaveroot/workspace/Templates/label/android/subrepos/widget/widgetLibrary/widget\_button.lua:120: in function 'manageButtonTouch' I Corona : /Users/jenkins/slaveroot/workspace/Templates/label/android/subrepos/widget/widgetLibrary/widget\_button.lua:658: in function 'method' I Corona : /Users/jenkins/slaveroot/workspace/Templates/label/android/platform/resources/init.lua:221: in function \</Users/jenkins/slaveroot/workspace/Templates/label/android/platform/resources/init.lua:190\>

Any idea what could be causing this? It’s driving me crazy!

This is blocking my project from finishing.  :frowning:

Any help would be appreciated. 

I’ll see if I can get an engineer to look into this.

In the meantime can you share your code?

What version of Corona as you using?

Are you doing native builds or simulator builds?

What device and version of Android are you testing on?

Is the test device rooted?

Are you building with a release keystore or a debug keystore?

Are you sure you have everything set up correctly in your Google Play developer console?

Rob

Thank you for your response Rob.

Here’s the code leaderboard handler I created:

local isAndroid = false local isiOS = false local targetAppStore = system.getInfo( "targetAppStore" ) local leaderboardIDs = { "leaderboardid1", -- those are placeholder IDs for the purpose of this post. "leaderboardid2" -- In my code I have the real values from Play Store Console. } if ( "apple" == targetAppStore ) then -- iOS isiOS = true elseif ( "google" == targetAppStore ) then -- Android isAndroid = true local licensing = require( "licensing" ) local function licensingListener( event ) if not ( event.isVerified ) then native.showAlert( "Event!", "You're a pirate!", { "OK" } ) else native.showAlert( "Event!", "You're not a pirate!", { "OK" } ) end end local licensingInit = licensing.init( "google" ) if ( licensingInit == true ) then licensing.verify( licensingListener ) else end end local gameNetwork = nil local gpgs = nil if isiOS then gameNetwork = require( "gameNetwork" ) end if isAndroid then gpgs = require( "plugin.gpgs.v2" ) gpgs.enableDebug() end local m = {} local function initCallback( event ) if isAndroid then if not event.isError then if ( event.name == "init" ) then native.showAlert( "Submit Event!", "Init call back", { "OK" } ) gpgs.login( { userInitiated=true, listener=initCallback } ) elseif ( event.name == "login" ) then native.showAlert( "Submit Event!", "Login call back", { "OK" } ) end else native.showAlert( "Submit Event!", "Error in initcallback: "..event.name, { "OK" } ) end else native.showAlert( "Submit Event!", "Now android: "..event.name, { "OK" } ) end end function m.init() if m.didInit then return end m.didInit = true if isiOS then gameNetwork.init( "gamecenter", initCallback ) elseif isAndroid then gpgs.init(initCallback) end end function m.setTopScore( score, leaderboardIndex ) if isiOS then local categories = { "com.frikado.leaderboard.park", "com.frikado.leaderboard.room" } gameNetwork.request( "setHighScore", { localPlayerScore = { category=categories[leaderboardIndex], value=score }}) elseif isAndroid then local function submitCallback(event) native.showAlert( "Submit Event!", "Set Top Score", { "OK" } ) end gpgs.leaderboards.submit({ leaderboardId = leaderboardIDs[leaderboardIndex], score = score, listener = submitCallback }) end end function m.showLeaderboards() if isiOS then gameNetwork.show( "leaderboards" ) elseif isAndroid then local function showCallback(event) native.showAlert( "Show Event!", "Show Leaderboard", { "OK" } ) end gpgs.leaderboards.show({listener = showCallback}) end end return m

I tried with Corona versions 3326 and 3441. It’s happening with both.

I’m testing on a Galaxy S6 with Android 7.0; I also made sure to update Google Play Store Game Services form the play store before posting this. The device is not rooted.

I was initially signing with the app store key. After signing with the debug key I get the error saying:

attempt to call field ‘init’ (a nil value) // On the line where it says “gpgs.init(initCallback)” in the code above.

I went over the Google Play developer console requirements multiple times. Could anything related to that be causing the issue?

It’s worth mentioning that in the build.settings file I have

       [“plugin.gpgs.v2”] =

        {

            publisherId = “com.coronalabs”,

            supportedPlatforms = { android=true }

        },

Thank you for your help!

You should not call .init() with GPGS v2. Please see:

https://coronalabs.com/blog/2018/10/31/update-on-the-new-gpgs-v2-plugin/

I’d make that change and see if the issue goes away.

Rob

Oh right, I removed that, and I get:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.ContextWrapper.getApplicationContext()' on a null object reference

On both lines that call:

gpgs.leaderboards.submit({

and

gpgs.leaderboards.show({listener = showCallback})