From The Blog: Google Play Games Services update, and how to use snapshots

Google Play Games Services (GPGS) have proven to be a crucial part of any Android game. Now, we are proud to announce that this great platform is available on iOS as well, with some slight variations based on the fact that Google’s own SDK for the iOS version does not match the Android version 100% (when Google updates their SDK, we will update our plugin to reflect these changes to bring the APIs into sync).

The beauty of a cross-platform plugin is that your existing code for Android will just work on iOS without needing to have different initialization listeners or different IDs for leaderboards and achievements.

On Android, the plugin communicates with Google’s servers through a special Google app that is pre-installed on devices. On iOS there is no such app, so the plugin uses Safari to perform authentication. In both cases, the user only needs to enter their GPGS password once for all games that use GPGS — once authenticated, the session persists in the browser and the user only has to click “Allow” for any other game that requests an authentication.

1

Google Play setup

To use this plugin, you first need to complete some basic setup on Google’s side:

Enable Google Play Games Services

Inside the Google Play Developer Console , go to Game Services and add a new game.

For snapshots to work, turn on Saved Games in Game Details. Then, add a few achievements and leaderboards for testing.

Link Android and iOS apps

Go to the linked apps page and link both iOS and Android apps.
2

Make sure both iPhone and iPad are enabled in the iOS app details.

If you want to use multiplayer, enable it in the app’s settings, however keep in mind that multiplayer support is not yet implemented for the iOS version of the GPGS plugin.

Sample settings for an Android app

3

Sample settings for an iOS app

4

After you have made all of the changes, save them. Publishing is not necessary for most testing purposes.

Take note of the Application ID on the Android app page and OAuth2 Client ID on the iOS app page. Write them down since you will need these values in the next step. Obviously, your unique values will be different than the values used in this tutorial.

Prepare your project settings

On the Corona side, the first thing you need to add to build.settings is the plugin:

settings = { plugins = { ["plugin.gpgs"] = { publisherId = "com.coronalabs", supportedPlatforms = { iphone=true, android=true } }, }, }

Then you need to insert authorization details for the plugin.

On Android, that is Application ID from the Google portal, specified as googlePlayGamesAppId within the android table of build.settings:

android = { googlePlayGamesAppId = "760035641580" }

For iOS, you need to insert the  OAuth2 Client ID  from the Google portal, specified as GooglePlayGamesOAuth2ClientId within the iphone → plist table of build.settings:

iphone = { plist = { GooglePlayGamesOAuth2ClientId = "760035641580-8eho8p557gtaaa7alouh5a2qlhtruomq.apps.googleusercontent.com", CFBundleURLTypes = { { CFBundleURLSchemes = { "com.googleusercontent.apps.760035641580-8eho8p557gtaaa7alouh5a2qlhtruomq" } }, { CFBundleURLSchemes = { "com.coronalabs.gpgs" } }, } } }

Also, as illustrated, you need to add two CFBundleURLTypes. The first should be set to your  OAuth2 Client ID , but in reverse order. The second is your iOS app bundle ID, gathered from within the Apple developer portal.

Prepare your project configuration

For the Android version for Google Play Games Services to work properly, the license key must be present in config.lua, inside applicationlicense:

application = { license = { google = { key = "2EMHcCmcO70sxhA8K+ll4msnfJPBfANFACWZkFtmiJM/pnZiqf+h14gZktyZ1fR3QY/iSLqmsYCIDQcQVVGhDa3VF39CEWz+X1Z70H4In/5I8Bi+xZ8hJZVS3MEYZrDFCEBS2WOHnGvCu7obId/qEKcfyRw7DAl9AV9b00Qj0D1bTjfjz/7AAXuZoa0QMC3qQPOojpneyb1A9eT/F2NfKTpTggg5/1pU4ZiYkmV+1t85AqL/IwlXOBhZo9AvCI6jqt4yDXfPSvzhpVucmFSg9SKFknNwz2BbwbUBb/LKuAewjiGPP3cKmmIUco27IOqho/bgAU1mOq1hmiuXsmvCRjkymWZY0LwBHbWIKKTbydBIGhpj9d0vndU8BvpQ5TUQbTC/WC7A" } } }

This key can be found in the Android app setup interface on the  Services & APIs page:
5

Coding

The coding begins with requiring the plugin and initializing it:

Initialization

local gpgs = require( "plugin.gpgs" ) local json = require( "json" ) local function gpgsLoginListener( event ) print( "Login event:", json.prettify(event) ) end local function gpgsInitListener( event ) if not event.isError then -- Try to automatically log in the user without displaying the login screen gpgs.login( { listener = gpgsLoginListener } ) end end gpgs.init( gpgsInitListener )

Inside the init() listener you can try to “silently” log in the current user. This means that, if the user has an internally-saved authentication token, the login process will be successful.

To make it “not silent” and present a login dialog, supply the userInitiated parameter into gpgs.login() as true. If the user is already logged in, a login dialog will not be shown.

Snapshots

One of the most exciting new features is the ability to save game data into the cloud and sync your game progress on different devices.

Saving data in a snapshot

To save data, first you need to open a snapshot. The gpgs.snapshots.open() function accepts a filename and a create parameter. The filename can be an arbitrary string name used to distinguish snapshots, even something as unoriginal as "save1" or "snapshot1". The create parameter tells Google to create the snapshot if it has not already been created (on iOS, the create parameter always true).

Inside the listener, you get the snapshot object as event.snapshot. To save new data, write it into the snapshot object’s contents using object.write() (this performs like a local file update). Then, save the snapshot using gpgs.snapshots.save()which effectively performs the snapshot upload.

local function gpgsSnapshotAfterSaveListener( event ) native.showAlert( "Snapshots", "Saving was " .. ( event.isError and "unsuccessful" or "successful" ) .. ".", { "OK" } ) end local function gpgsSnapshotOpenForSaveListener( 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 gpgs.snapshots.open({ -- Open the save slot filename = snapshotFilename, create = true, -- Create the snapshot if it's not found listener = gpgsSnapshotOpenForSaveListener })

Note that the value passed to object.write() must be a string. If you want to save a Lua table of data, first encode it into a string using json.encode().

Once you save the snapshot, it is closed internally and can’t be reused to save new data again. Basically, you have to reopen the snapshot each time before you want to save new data to it.

Loading data from a snapshot

Reading is easier: you just need to open a snapshot and call object.read() on snapshot object’s contents:

local function gpgsSnapshotOpenForReadListener( 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 gpgs.snapshots.open({ filename = snapshotFilename, listener = gpgsSnapshotOpenForReadListener })

Here, the data variable will hold a string representation of the snapshot content. Remember that if you encoded a Lua table into JSON when saving the snapshot contents, you should decode it back to a Lua table using json.decode().

Sample app

To help understand the snapshots concept, we have created a sample app that lets you save and load a simple game state. You can, for instance, save a game on Android and then load it on iOS right away. You can download this sample app from our Github repository.

Additional material

To better understand snapshots, you can watch these two videos made by Google that explain them in depth.

Also, since the plugin closely resembles the official SDK by Google, you can use their documentation when you want to clear up specific usage details:

Conclusion

The GPGS plugin can be a great addition to your Android and iOS apps. Progress toward completion of the full suite of iOS functionality continues and we’ll update you as additions are implemented.

Questions or comments? Join us in the Corona Forums.

View the full article

@Lerg

There is a serious issue when applying this new gpgs plugin…

The new plugin requires to exclude the legacy [“plugin.google.play.services”] from build.settings. However, many other plugins (e.g, Admob, Vungle…) requires the legacy plugin, which cannot be replaced by the new one.

Hi @wilsonwansun, we are aware of the issue. Engineering is working to get the new plugin dependencies system rolled out.

I’ll see if I can get an expectation for this.

Rob

im still having the issue like snapshots.open its not working even the listener is dispatch

Hi Rob;

I’m with wilsonwansun. Although I’m looking forward to implementing snapshots and other gpgs features, my apps require the legacy plugin.google.play.services for Admob and at least a couple of other plugins. I just wanted to confirm the importance of this. Thanks!

Steve

Rene.castillo, make sure snapshots are enabled in both Google Play Games Services console and in API console: https://console.developers.google.com

don’t think vungle requires that plug in. Some corona docs say it’s needed while other corona docs don’t mention it (which is already rather confusing). However, I’m now using vungle without that plug in (plugin.google.play.services) and it works fine.

Lerg. its enabled  in both of them

jaques1 have you test another ad plugin without the google play service in it

another stuff is im a little confused with the chartboost integration its only via corona ads, or may i use it alongside?

Note to Jacques1 – it isn’t simply a matter of Vungle. Several other important plugins require the legacy plugin.google.play.services. For example – adMob, inMobi, Kochava, Flurry all require it. And probably others that we are not presently using.

Steve

@Rene.castillo, From your code side, Chartboost is it’s own plugin. You have to add it to build.settings, init it in your code, etc. From an administrative perspective, you use your Corona Ads dashboard to enable the plugin, select placements, etc.

Rob

@sbullock, I was simply clarifying on wilsonwansun’s post mentioning admob and vungle both require the plugin. Definitely admob doesn’t work with it as mentioned in many places by corona. However, even though the documentation indicates that the plugin is required for vungle it is actually not required for vungle. So people who only use vungle won’t be affected.

@Lerg

There is a serious issue when applying this new gpgs plugin…

The new plugin requires to exclude the legacy [“plugin.google.play.services”] from build.settings. However, many other plugins (e.g, Admob, Vungle…) requires the legacy plugin, which cannot be replaced by the new one.

Hi @wilsonwansun, we are aware of the issue. Engineering is working to get the new plugin dependencies system rolled out.

I’ll see if I can get an expectation for this.

Rob

im still having the issue like snapshots.open its not working even the listener is dispatch

Hi Rob;

I’m with wilsonwansun. Although I’m looking forward to implementing snapshots and other gpgs features, my apps require the legacy plugin.google.play.services for Admob and at least a couple of other plugins. I just wanted to confirm the importance of this. Thanks!

Steve

Rene.castillo, make sure snapshots are enabled in both Google Play Games Services console and in API console: https://console.developers.google.com

don’t think vungle requires that plug in. Some corona docs say it’s needed while other corona docs don’t mention it (which is already rather confusing). However, I’m now using vungle without that plug in (plugin.google.play.services) and it works fine.

Lerg. its enabled  in both of them