Google Play Games Services v2 (plugin beta)

Can you compare your snapshot code to this?
 

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

Apparently, there were multiple ways to do snapshots. 

Rob

@Rob

Yes my snapshot code is very similar to your one. The only difference is that I don’t have myData.savesnapshot() as a separate function. I have used the code of this how to implement gpgs post. 

During pre-launch test on developer console, one instance of an error was found, here is the message:
 

FATAL EXCEPTION: main Process: com.sheekore.games.sentioTapEmoji, PID: 12290 java.lang.NullPointerException: value == null     at java.util.Hashtable.put(Hashtable.java:362)     at plugin.gpgs.Utils.gameToHashtable(Utils.java:380)     at plugin.gpgs.Utils.snapshotMetadataToHashtable(Utils.java:444)     at plugin.gpgs.Snapshots$LoadSnapshotsResultCallback.onResult(Snapshots.java:412)     at plugin.gpgs.Snapshots$LoadSnapshotsResultCallback.onResult(Snapshots.java:389)     at com.google.android.gms.common.api.internal.BasePendingResult$CallbackHandler.handleMessage(Unknown Source)     at android.os.Handler.dispatchMessage(Handler.java:102)     at android.os.Looper.loop(Looper.java:148)     at android.app.ActivityThread.main(ActivityThread.java:5459)     at java.lang.reflect.Method.invoke(Native Method)     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

I don’t know where the snapshot code in that forum post originated, it almost looks like it’s your original code. The code I used to have wasn’t working either. The engineer who built the plugin provided me with the updated code which I tested with both V1 and V2 of the plugin. 

I’ll share this with Engineering.

Rob

@Rob

Thank you for having a look into this issue.

@Rob

I have updated the snapshot code. I am trying gpgs.v2 plugin, but it seems I can’t login. gpgs.isConnected() is giving false always but event.phase in gpgsLoginListener function is saying ‘logged in’. The pop up that normally used to show in gpgs V1 is not showing here. 

here is how I implemented the login functionality. With gpgs V1 it works but when I add v2, the login doesn’t work anymore. Are there any changes to be made?

local gpgs = require( "plugin.gpgs.v2" ) local function toggleGPGSToLogin( self, event ) &nbsp; if ( gpgs.isConnected() ) then &nbsp; &nbsp; gpgsLoggedOutButton.isVisible = false &nbsp; &nbsp; gpgsLoggedInButton.isVisible = true &nbsp; &nbsp; local tempGameData = loadsave.loadTable( "gameData.json" ) &nbsp; &nbsp; -- download snapshot &nbsp; &nbsp; local function gpgsSnapshotOpenForReadListener( event ) &nbsp; &nbsp; &nbsp; if not event.isError then &nbsp; &nbsp; &nbsp; &nbsp; -- local retrievedData = event.snapshot.contents.read()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local retrievedData = gpgs.snapshots.getSnapshot (event.snapshotId) &nbsp; &nbsp; &nbsp; &nbsp; local gameData, pos, msg = json.decode( retrievedData ) &nbsp; &nbsp; &nbsp; &nbsp; if not gameData then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; toast.show('Decoding failed.' ..tostring(pos)..": "..tostring(msg) )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( tempGameData.inGameAnalyticsTotalGamePlayed \< gameData.inGameAnalyticsTotalGamePlayed&nbsp; ) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- save table from the gpgs server &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loadsave.saveTable( gameData, "gameData.json" )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- upload the offline gameplayed to GPGS server &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local gameData = loadsave.loadTable( "gameData.json" ) -- loading gameData from phone &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- save snapshots &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local function gpgsSnapshotOpenForSaveListener( event ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if not event.isError then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local snapContent = gpgs.snapshots.getSnapshot(event.snapshotId).contents &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; snapContent.write( json.encode(gameData) ) -- Write new gameData as a JSON string into the snapshot &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gpgs.snapshots.save({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; snapshotId = event.snapshotId, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description = "Game scores", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; image = { filename = "EmojiCrushShare.png", baseDir = system.ResourceDirectory }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- gpgsSnapshotOpenForSaveListener func END &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gpgs.snapshots.open({&nbsp; -- Open the save slot &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename = snapshotFileName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; create = true,&nbsp; -- Create the snapshot if it's not found &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conflictPolicy = "most recently modified", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listener = gpgsSnapshotOpenForSaveListener &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- (tempInGameAnalytics.totalGamePlayed \< inGameAnalytics.totalGamePlayed)&nbsp; conditional END &nbsp; &nbsp; &nbsp; &nbsp; end -- not inGameAnalytics conditional END &nbsp; &nbsp; &nbsp; end -- event.iserror conditional END &nbsp; &nbsp; end --gpgsSnapshotOpenForReadListener func END &nbsp; &nbsp; gpgs.snapshots.open({ &nbsp; &nbsp; &nbsp; &nbsp; filename = snapshotFileName, &nbsp; &nbsp; &nbsp; &nbsp; conflictPolicy = "most recently modified", &nbsp; &nbsp; &nbsp; &nbsp; listener = gpgsSnapshotOpenForReadListener &nbsp; &nbsp; &nbsp; }) &nbsp; end -- gpgs.isConnected() conditional END end -- toggleGPGSToLogin func END local function gpgsLoginListener( event ) &nbsp; gameData.gpgsDataUserPref = event.phase &nbsp; print ("gpgsLoginListener") &nbsp; print (event.phase) &nbsp; loadsave.saveTable( gameData, "gameData.json" ) &nbsp; toggleGPGSToLogin() &nbsp; if event.isError then &nbsp; &nbsp; toast.show("Sign in problem: Check network connection.") &nbsp; end -- event.isError conditional END end local function onGpgsLoginButtonTap( self, event ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print ("onGpgsLoginButtonTap") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print (gpgs.isConnected()) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (gpgs.isConnected()) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --logout &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gpgs.logout() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gameData.gpgsDataUserPref = "logged out" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loadsave.saveTable( gameData, "gameData.json" ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gpgsLoggedOutButton.isVisible = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gpgsLoggedInButton.isVisible = false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --login &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gpgs.login( { userInitiated = true, listener = gpgsLoginListener } ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- login or logout conditional END &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true &nbsp; &nbsp; &nbsp; &nbsp; end -- onGpgsLoginButtonTap func END &nbsp; &nbsp; &nbsp; &nbsp; gpgsLoggedInButton:addEventListener( "tap", onGpgsLoginButtonTap ) &nbsp; &nbsp; &nbsp; &nbsp; gpgsLoggedOutButton:addEventListener( "tap", onGpgsLoginButtonTap )

Our engineer is investigating. It’s really weird because when I use a game I’m working on, it works as expected. When I change the credentials to something new, .isConnected() fails reliably. This leads me to believe that the new library from Google is dependent on a setting in the Google Play Console which wasn’t required with the v1 plugin.

Rob

Can everyone here give it another try? We pushed a possible fix for the .isConnected() API today.

Thanks

Rob

@Rob

I have built with 2018.3407

The login functionality is working,but now the achievements, leaderboards and snapshots are not working. even after log in. The default windows are not showing up for them.

 Code for achievements and leaderboards funcitonality:

local function handleButton(event) &nbsp; if (event.target.id == "inGameLeaderboards" and event.phase == "ended") then &nbsp; &nbsp; if (gpgs.isConnected()) then &nbsp; &nbsp; &nbsp; gpgs.leaderboards.show() &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; gpgs.login( { userInitiated = true, listener = gpgsLoginListener } ) &nbsp; &nbsp; &nbsp; gpgs.leaderboards.show() &nbsp; &nbsp; end -- gpgs is connected check outer END &nbsp; elseif (event.target.id == "inGameAchievements" and event.phase == "ended") then &nbsp; &nbsp; if (gpgs.isConnected()) then &nbsp; &nbsp; &nbsp; gpgs.achievements.show() &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; gpgs.login( { userInitiated = true, listener = gpgsLoginListener } ) &nbsp; &nbsp; &nbsp; gpgs.achievements.show() &nbsp; &nbsp; end -- gpgs is connected check outer END &nbsp; end -- button conditional END end

Code for snapshots upload and download funcitonality:

local function handleButton (event) &nbsp; if (event.target.id == "cloudUpload" and event.phase == "ended") then &nbsp; &nbsp; -- save snapshots &nbsp; &nbsp; local function gpgsSnapshotOpenForSaveListener( event ) &nbsp; &nbsp; &nbsp; if not event.isError then &nbsp; &nbsp; &nbsp; &nbsp; local snapContent = gpgs.snapshots.getSnapshot(event.snapshotId).contents &nbsp; &nbsp; &nbsp; &nbsp; snapContent.write( json.encode(gameData) ) -- Write new gameData as a JSON string into the snapshot &nbsp; &nbsp; &nbsp; &nbsp; gpgs.snapshots.save({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; snapshotId = event.snapshotId, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description = "Game scores", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; image = { filename = "EmojiCrushShare.png", baseDir = system.ResourceDirectory }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; end -- gpgsSnapshotOpenForSaveListener func END &nbsp; &nbsp; if (gpgs.isConnected()) then &nbsp; &nbsp; &nbsp; gpgs.snapshots.open({&nbsp; -- Open the save slot &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename = snapshotFileName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; create = true,&nbsp; -- Create the snapshot if it's not found &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conflictPolicy = "most recently modified", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listener = gpgsSnapshotOpenForSaveListener &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.load( {reload = true, }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.show( {title = "Emoji Crush", disableAdd = false, disableDelete = false}) &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; gpgs.login( { userInitiated = true, listener = gpgsLoginListener } ) &nbsp; &nbsp; &nbsp; gpgs.snapshots.open({&nbsp; -- Open the save slot &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename = snapshotFileName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; create = true,&nbsp; -- Create the snapshot if it's not found &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conflictPolicy = "most recently modified", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listener = gpgsSnapshotOpenForSaveListener &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.load( {reload = true, }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.show( {title = "Emoji Crush", disableAdd = false, disableDelete = false}) &nbsp; &nbsp; end -- gpgs is connected check outer END &nbsp; elseif (event.target.id == "cloudDownload" and event.phase == "ended") then &nbsp; &nbsp; -- download snapshot &nbsp; &nbsp; local function gpgsSnapshotOpenForReadListener( event ) &nbsp; &nbsp; &nbsp; if not event.isError then &nbsp; &nbsp; &nbsp; &nbsp; local retrievedData = gpgs.snapshots.getSnapshot (event.snapshotId) &nbsp; &nbsp; &nbsp; &nbsp; local gameData, pos, msg = json.decode( retrievedData ) &nbsp; &nbsp; &nbsp; &nbsp; if not gameData then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; toast.show('Decoding failed.' ..tostring(pos)..": "..tostring(msg))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loadsave.saveTable( gameData, "gameData.json" ) &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; -- DO NOTHING &nbsp; &nbsp; &nbsp; end -- event.iserror conditional END &nbsp; &nbsp; end --gpgsSnapshotOpenForReadListener func END &nbsp; &nbsp; if (gpgs.isConnected()) then &nbsp; &nbsp; &nbsp; gpgs.snapshots.open({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename = snapshotFileName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conflictPolicy = "most recently modified", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listener = gpgsSnapshotOpenForReadListener &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.load( {reload = true, }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.show( {title = "Emoji Crush", disableAdd = false, disableDelete = false}) &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; gpgs.login( { userInitiated = true, listener = gpgsLoginListener } ) &nbsp; &nbsp; &nbsp; gpgs.snapshots.open({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename = snapshotFileName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conflictPolicy = "most recently modified", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listener = gpgsSnapshotOpenForReadListener &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.load( {reload = true, }) &nbsp; &nbsp; &nbsp; gpgs.snapshots.show( {title = "Emoji Crush", disableAdd = false, disableDelete = false}) &nbsp; &nbsp; end -- gpgs.isconnected END &nbsp; end-- conditional END

Hi Rob,

I’ve just rebuilt the game and tested it here. I got the same results. Nothing happens when calling gpgs.leaderboards.show() or gpgs.achievements.show().

Br,

Cleverson

Please see my post here. https://forums.coronalabs.com/topic/73999-from-the-blog-new-google-play-games-services-plugin/page-2#entry390218

Let’s keep the conversation there!

Thanks

Rob

Can everyone give it another try. We think we’ve addressed this issue.

Rob

Hi @genelixis

This isn’t all that helpful to us. Can you share what errors your getting and the code you’re using that’s failing? It’s really hard for me to go to the engineers with “It’s not working. Fix it” with no specifics.

Copies of the errors from the device’s console log would be really great.

Rob

You are right Rob!

As I said, I will test it again and post logs next week.

I’m waiting, at least, Google Play Services login window to start appearing :slight_smile:

Also sample link is not working.

That would help everybody, a lot!!

@rob, I’m about to go live with a new app - should I be using this beta plugin?

The GPGS v2 plugin was in a **closed** test. We had invited a few specific people to work on it. Somehow it was made public. It is not ready to be used in production apps.

We were trying to fix a particular issue that Google was flagging with logins during some feature review. Very few people have reported this problem and the GPGS v1 plugin is working just fine for almost everyone. However to address this problem (which we suspect will impact more people in the future) we had to completely re-write the entire plugin. That means we have to exercise every node.

The only people who should be using the v2 plugin now are those who are willing to test it and share code and report errors and not have it impact their production.

@genelixis I don’t know that not seeing a login popup is a bug that prevents you from testing this. It does appear to successfully log you in.  

Rob

GPGS v1 plugin is not working if you do a build now.

Login popup appears but save / retrieve data using snapshots is not working.

Am I wrong?

We haven’t touched the V1 plugin.

EDIT: we did update the plugin on 8/8 to work with Android API level 27.

Rob

I haven’t touched my code either but save / retrieve data using snapshots is not working if I make a new build.

Other people can make a build now with gpgs v1 and save / retrieve data using snapshots is working for them?

A few days ago I emailed code and logs @coronalabs because gpgs save / retrieve data using snapshots stopped working.

The answer came from the engineers: 

The problem occurs because I use an old version of gpgs.

I should wait for the new version, gpgs-v2, which wil be released soon.

Then you should wait for us to formally release the plugin. Hopefully, it will be soon.

Rob