Android Games Sing in - StansAssets/com.stansassets.android-native GitHub Wiki

In order to access Google Play games services functionality, your game needs to provide the signed-in player’s account. If the player is not authenticated, your game may encounter errors when making calls to the Google Play games services APIs. This documentation describes how to implement a seamless sign-in experience in your game.

Checking Availability

Before you begin to use any GMS API, you should consider checking if you can use GMS API on this device at all. The AN_GoogleApiAvailability is a helper class for verifying that the Google Play services APK is available and up-to-date on this device. With its help, you can check if GMS API is available on a current device, and if it's not, you may try to resolve the issue. See the example below:

using SA.Android.GMS.Common;

int result = AN_GoogleApiAvailability.IsGooglePlayServicesAvailable();
if (result != AN_ConnectionResult.SUCCESS) {
    Debug.Log("Play Services does not available on this device. Resolving....");
    AN_GoogleApiAvailability.MakeGooglePlayServicesAvailable(resolution => {
        if (resolution.IsSucceeded) {
            Debug.Log("Resolved! Play Services is available on this device");
        } else {
            Debug.LogError($"Failed to resolve: {resolution.Error.Message}");
        }
    });
} else {
    Debug.Log("Play Services is available on this device");
}

Implementing player sign-in

The AN_GoogleSignInClient ++class is the main entry point to retrieve the account of the currently signed-in player, and to sign-in the player if they have not previously done so on your app in the device.

To create a sign-in client, follow these steps:

To determine if a player has already signed-in, you can call the AN_GoogleSignIn.getLastSignedInAccount() method and check if it returns null.

using SA.Android.GMS.Auth;
...

private boolean isSignedIn() {
  return AN_GoogleSignIn.GetLastSignedInAccount() != null;
}

Performing silent sign-in

You can call SilentSignIn() to retrieve the currently signed-in player’s account, and try to sign players in without displaying a user interface if they have successfully signed in to your app on a different device.

If the silent sign-in attempt fails, you can optionally send the sign-in intent to display a sign-in user interface, as described in Performing interactive sign-in.

Since the state of the signed-in player can change when the activity is not in the foreground, Google recommends calling SilentSignIn() after the game is resumed. For Unity the best place to perform a silent sign in is when your game is unpaused.

The following code snippet shows how your app can perform silent sign-in:

using SA.Android.GMS.Auth;
...

Debug.Log("Play Services Sign In started....");
var builder = new AN_GoogleSignInOptions.Builder(AN_GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
//Google play documentation says that
// you don't need to use this, however, we recommend you still
// add those option to your Sing In builder. Some version of play service lib
// may retirn a signed account with all fileds empty if you will not add this.
// However according to the google documentation this step isn't required
// So the decision is up to you.
builder.RequestId();
builder.RequestEmail();
builder.RequestProfile();
// Add the APPFOLDER scope for Snapshot support.
builder.RequestScope(AN_Drive.SCOPE_APPFOLDER);
var gso = builder.Build();
Debug.Log("Let's try Silent SignIn first");
var client = AN_GoogleSignIn.GetClient(gso);
client.SilentSignIn(result => {
    if (result.IsSucceeded) {
        Debug.Log("SilentSignIn Succeeded");
        UpdateUIWithAccount(result.Account);
    } else {
        // Player will need to sign-in explicitly using via UI
        Debug.Log($"SilentSignIn Failed with code: {result.Error.Code}");
        Debug.Log("Starting the default Sign in flow");
        //Starting the interactive sign-in
        client.SignIn(signInResult => {
            Debug.Log($"Sign In StatusCode: {signInResult.StatusCode}");
            if (signInResult.IsSucceeded) {
                Debug.Log("SignIn Succeeded");
                UpdateUIWithAccount(signInResult.Account);
            } else {
                Debug.LogError($"SignIn failed: {signInResult.Error.FullMessage}");
            }
        });
    }
});

If the silent sign-in attempt fails, you can analyze the signInResult.Error.Message and signInResult.Error.Code fields. From example A status code of AN_CommonStatusCodes.SIGN_IN_REQUIRED indicates that the player needs to take explicit action to sign-in. In this case, your app should launch an interactive sign-in flow as described in the next section.

Performing interactive sign-in

To sign in with player interaction, your app needs to launch the sign-in intent. If successful, the Google Sign-In API displays a user interface that prompts the player to enter their credentials to sign in. This approach simplifies your app development, since the sign-in activity handles scenarios such as needing to update Google Play services or showing consent prompts, on your app’s behalf.

As an example of how to perform the sign-in interactively, see the snippet below:

using SA.Android.GMS.Auth;
...
var builder = new AN_GoogleSignInOptions.Builder(AN_GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
builder.RequestId();
builder.RequestEmail();
builder.RequestProfile();
var gso = builder.Build();
var client = AN_GoogleSignIn.GetClient(gso);
Debug.Log("SignInNoSilent Start");
client.SignIn(signInResult => {
    Debug.Log($"Sign In StatusCode: {signInResult.StatusCode}");
    if (signInResult.IsSucceeded) {
        Debug.Log("SignIn Succeeded");
        UpdateUIWithAccount(signInResult.Account);
    } else {
        Debug.LogError($"SignIn filed: {signInResult.Error.FullMessage}");
    }
});

Retrieving player information

The AN_GoogleSignInAccount that the Google Sign-In API returns does not contain any player information. If your game uses player information, such as the player’s display name and player ID, you can follow these steps to retrieve this information:

using SA.Android.GMS.Games;
...

var client = AN_Games.GetPlayersClient();
client.GetCurrentPlayer(result => {
    if(result.IsSucceeded) {
        var player = result.Data;
        Debug.Log($"player.Id: {player.PlayerId}");
        Debug.Log($"player.DisplayName: {player.DisplayName}");
        Debug.Log($"player.HiResImageUri: {player.HiResImageUri}");
        Debug.Log($"player.IconImageUri: {player.IconImageUri}");
        Debug.Log($"player.HasIconImage: {player.HasIconImage}");
        Debug.Log($"player.HasHiResImage: {player.HasHiResImage}");
        if (!player.HasHiResImage) {
             var url = player.HiResImageUri;
             var manager = new AN_ImageManager();
             manager.LoadImage(url, imaheLoadResult => {
                 m_userAvatar.texture = imaheLoadResult.IsSucceeded ? imaheLoadResult.Image : null;
             });
        }
    } else {
        Debug.LogError($"Failed to load Current Player {result.Error.FullMessage}");
    }
});

As you may notice the AN_Player object contains HiResImageUri and IconImageUri properties. Those URLs will be formatted similar to the example below:

content://com.google.android.gms.games.background/images/b4d1b8fd/2956

This means you can't use UnityWebRequest to download the image using this URL. Since google play stores all the images locally. In order to obtain an image that you can use in your game, you need to use Image Manager.

Displaying game pop-ups

You can display pop-up views in your game using the AN_GamesClient class. For example, your game can display a “Welcome back” or an “Achievements unlocked” pop-up. To allow Google Play games services to launch pop-ups in views in your game, call the SetViewForPopups() method. You can further customize where the pop-up appears in the screen by calling SetGravityForPopups().

using SA.Android.App;
using SA.Android.App.View;
using SA.Android.GMS.Games;
...

//When Sign in is finished with successes
var gamesClient = AN_Games.GetGamesClient();
gamesClient.SetViewForPopups(AN_MainActivity.Instance);

//optionally
gamesClient.SetGravityForPopups(AN_Gravity.TOP | AN_Gravity.CENTER_HORIZONTAL);

Signing the player out

Signing-out is done via call the SignOut() method on the AN_GoogleSignInClient.

using SA.Android.GMS.Auth;
...

AN_GoogleSignInOptions gso = new AN_GoogleSignInOptions.Builder(AN_GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).Build(); 
AN_GoogleSignInClient client = AN_GoogleSignIn.GetClient(gso);

client.SignOut(() => {
    ClearAccountUI();
});

Applications are required to provide users that are signed in with Google the ability to disconnect their Google account from the app. If the user deletes their account, you must delete the information that your app obtained from the Google APIs. You can also use RevokeAccess. Method revokes access given to the current application. Future sign-in attempts will require the user to re-consent to all requested scopes.

using SA.Android.GMS.Auth;
...

AN_GoogleSignInOptions gso = new AN_GoogleSignInOptions.Builder(AN_GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).Build(); 
AN_GoogleSignInClient client = AN_GoogleSignIn.GetClient(gso);

client.RevokeAccess (() => {
    ClearAccountUI();
});