B. initializing and sign in - myflashlab/GameServices-ANE GitHub Wiki

Authentication

As stated before, user authentication happens in the GoogleSignIn ANE. So before initializing the GameServices ANE, you need to make sure the user is signed in. Sign in users to your app like below:

// depending on your app design, you must customize the Signin Options
// If you want GoogleGames signin only, do like below:
var options:GSignInOptions = new GSignInOptions();
options.gamesSignIn = true; // set to true if you are working with Google Games Services ANE.

// you don't want to bother users with a permission page, right? so set these to false 
// and don't ask for extra access scopes.
options.requestId = false;
options.requestProfile = false;
options.requestEmail = false;

// IMPORTANT: if you are not using Game Save Snapshots, you would not need GScopes.DRIVE_APPFOLDER
options.requestScopes = [
	"https://www.googleapis.com/auth/games", // must be set for games
	GScopes.DRIVE_APPFOLDER // optional and only needed if you are using Game Save Snapshots
];

// then pass the options to the initialization method of the GSignIn ANE
GSignIn.init(options);

// Finally, add listeners
GSignIn.listener.addEventListener(GSignInEvents.SILENT_SIGNIN_SUCCESS, onSilentSigninSuccess);
GSignIn.listener.addEventListener(GSignInEvents.SILENT_SIGNIN_FAILURE, onSilentSigninFailure);
GSignIn.listener.addEventListener(GSignInEvents.SIGNIN_SUCCESS, onSigninSuccess);
GSignIn.listener.addEventListener(GSignInEvents.SIGNIN_FAILURE, onSigninFailure);
GSignIn.listener.addEventListener(GSignInEvents.SIGNOUT_SUCCESS, onSignoutSuccess);
GSignIn.listener.addEventListener(GSignInEvents.SIGNOUT_FAILURE, onSignoutFailure);

// check if user is already loggedin or not
var account:GAccount = GSignIn.signedInAccount;
if(account)
{
	initGames(); // here, you will initialize the GameServices ANE
}
else
{
	// You should first check if user can signin silently, if she can't, use the signin() method
	GSignIn.silentSignIn();
}

function onSigninSuccess(e:GSignInEvents):void
{
	trace("e.account.scopes: "+ e.account.scopes);
	initGames();
}

function onSilentSigninSuccess(e:GSignInEvents):void
{
	initGames();
}

When the user is logged in successfully, you can initialize the GameServices ANE. Just remember that if you are signing out a user, for example by calling GSignIn.signOut(); you must call Games.dismiss(); when the signout happens:

GSignIn.listener.addEventListener(GSignInEvents.SIGNOUT_SUCCESS, onSignoutSuccess);

function onSignoutSuccess(e:GSignInEvents):void
{
	Games.dismiss();
}

Initialization

Initializing and using Game services couldn't be easier than this, all you have to do is to initialize it and then listen to the events. user must be already logged in of course.

Games.init();

if(!Games.listener.hasEventListener(GamesEvents.CONNECT_SUCCESS))
{
	Games.listener.addEventListener(GamesEvents.CONNECT_SUCCESS, onConnectSuccess);
	Games.listener.addEventListener(GamesEvents.CONNECT_FAILURE, onConnectFailure);

	// There's no need to add this listener, it just shows you some more information about
	// how activities inside the ANE are doing.
	Games.listener.addEventListener(GamesEvents.ACTIVITY_RESULT_CODES, onActivityResultCodes);
}

// If you are using Multiplayer RealTime API, you would also need to listen to the following events
if(!Games.realtime.hasEventListener(GamesEvents.REAL_TIME_ROOM_CREATED))
{
	Games.realtime.addEventListener(GamesEvents.REAL_TIME_ROOM_CREATED, onRoomCreated);
	Games.realtime.addEventListener(GamesEvents.REAL_TIME_ROOM_CONNECTED, onRoomConnected);
	Games.realtime.addEventListener(GamesEvents.REAL_TIME_ROOM_JOINED, onRoomJoined);
	Games.realtime.addEventListener(GamesEvents.REAL_TIME_ROOM_LEFT, onRoomLeft);
	
	Games.realtime.addEventListener(GamesEvents.ROOM_STATUS_UPDATED, onRoomStatusUpdated);
	Games.realtime.addEventListener(GamesEvents.WAITING_ROOM_WINDOW_DISMISSED, onWaitingRoomDismissed);
	Games.realtime.addEventListener(GamesEvents.WAITING_ROOM_WINDOW_FAILURE, onWaitingRoomFailure);
	Games.realtime.addEventListener(GamesEvents.WAITING_ROOM_RESULT, onWaitingRoomResult);
	
	Games.realtime.addEventListener(GamesEvents.MESSAGE_SENT, onMessageSent);
	Games.realtime.addEventListener(GamesEvents.MESSAGE_RECEIVED, onMessageReceived);
	
	Games.invitations.addEventListener(GamesEvents.INVITE_PLAYERS_WINDOW_FAILURE, onInvitingPlayersWinFailure);
	Games.invitations.addEventListener(GamesEvents.INVITING_PLAYERS_RESULT, onInvitingPlayersResult);
	Games.invitations.addEventListener(GamesEvents.INVITATION_RECEIVED, onInvitationReceived);
	Games.invitations.addEventListener(GamesEvents.INVITATION_REMOVED, onInvitationRemoved);
}

function onConnectFailure(e:GamesEvents):void
{
	trace("onConnectFailure: " + e.msg);
}

function onActivityResultCodes(e:GamesEvents):void
{
	// https://developers.google.com/android/reference/com/google/android/gms/games/GamesActivityResultCodes
	trace("onActivityResultCodes: " + e.status);
}

function onConnectSuccess(e:GamesEvents):void
{
	trace("displayName: " + e.player.displayName);
	trace("id: " + e.player.id);
	trace("lastPlayedTimestamp: " + e.player.lastPlayedTimestamp);
	trace("title: " + e.player.title);
	trace("retrievedTimestamp: " + e.player.retrievedTimestamp);
	trace("hasHiResImage: " + e.player.hasHiResImage);
	trace("hasIconImage: " + e.player.hasIconImage);

	if(e.player.levelInfo)
	{
		trace("levelInfo.currentXpTotal: " + e.player.levelInfo.currentXpTotal);
		trace("levelInfo.isMaxLevel: " + e.player.levelInfo.isMaxLevel);
		trace("levelInfo.lastLevelUpTimestamp: " + e.player.levelInfo.lastLevelUpTimestamp);
		
		trace("levelInfo.currentLevel.levelNumber: " + e.player.levelInfo.currentLevel.levelNumber);
		trace("levelInfo.currentLevel.maxXp: " + e.player.levelInfo.currentLevel.maxXp);
		trace("levelInfo.currentLevel.minXp: " + e.player.levelInfo.currentLevel.minXp);
		
		trace("levelInfo.nextLevel.levelNumber: " + e.player.levelInfo.nextLevel.levelNumber);
		trace("levelInfo.nextLevel.maxXp: " + e.player.levelInfo.nextLevel.maxXp);
		trace("levelInfo.nextLevel.minXp: " + e.player.levelInfo.nextLevel.minXp);
	}
}

Loading images

There are many different graphics you may like to load when using the GameServices ANE. For example if a player has an icon image and you would like to load it in your app, you will have two options. the first option would be to use Games REST API and find the URL of the image file you need and load it normally with AIR. But there's a second solution and an easier one. You may use the methods of this ANE and it will take care of loading the image files for you.

Take the sample code above as an example. If you want to load the user's HiResImage, here's what you could do:

if(e.player.hasHiResImage)
{
	e.player.loadHiResImg(false, function ($file:File) 
	{
		if($file)
		{
			trace("use FileStream to load the File object: " + $file.nativePath);
		}
		else
		{
			trace("image is not available");
		}
	});
}

Look through the asdoc, and you will see different load methods which lets you load specefic images.

Events & Listeners

GamesServices ANE has many listeners which may or may not be dispatched based on which part of the API is called. One of the best ways to learn about these events is by looking at the GamesEvents class. Checkout the asdoc and you will see that we have listed all the possible events that GameServices ANE may dispatch. Take ACHIEVEMENT_LOAD_RESULT as an example. The documentation says:

 Dispatches on relation to Games.achievements.load.

    event.status
    event.msg
    event.achievements

This means that you may expect this event to be dispatched when you are calling the Games.achievements.load method. And when the event happens, you will have access to the mentioned three parameters.

All the GameSservices events has a similar description which you will find very helpful when developng your game.