Sign-in in Android Games

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.

Implementing player sign-in

The 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:

  1. Create a sign-in client via the GoogleSignInOptions object, as shown in the following code snippet. In the GoogleSignInOptions.Builder to configure your sign-in, you must specify GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN.

    GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  2. If you want to use a SnapshotsClient, then add .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS) to your GoogleSignInOptions.Builder as shown in the following code snippet:

    GoogleSignInOptions  signInOptions =
        new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
            .build();
  3. Call the GoogleSignIn.getClient() method and pass in the options that you configured in the previous steps. If the call is successful, the Google Sign-In API returns an instance of GoogleSignInClient.

Check whether player is already signed in

You can check whether an account is already signed in on the current device using GoogleSignIn.getLastSignedInAccount() and whether this account already has the required permissions granted using GoogleSignIn.hasPermissions(). If both conditions are true—that is, getLastSignedInAccount() returns a non-null value and hasPermissions() returns true—you can safely use the account returned from getLastSignedInAccount(), even if the device is offline.

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.

The silentSignIn() method returns a Task<GoogleSignInAccount>. When the task completes, you set the GoogleSignInAccount field you declared earlier to the sign-in account that the task returns as the result, or to null, indicating there is not a signed-in user.

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, we recommended calling silentSignIn() from the activity's onResume() method.

To perform the sign-in silently, follow these steps:

  1. Call the silentSignIn() method on the GoogleSignInClient to start the silent sign-in flow. This call returns an Task<GoogleSignInAccount> object which contains a GoogleSignInAccount if silent sign-in is successful.
  2. Handle the success or failure of the player sign-in by overriding OnCompleteListener.
    • If the sign-in task was successful, get the GoogleSignInAccount object by calling getResult().
    • If sign-in was not successful, you can send a sign-in intent to launch an interactive sign-in flow. For a list of additional callback listeners you can use, see the Tasks API developer guide and Task API reference.

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

private void signInSilently() {
  GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
  if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) {
    // Already signed in.
    // The signed in account is stored in the 'account' variable.
    GoogleSignInAccount signedInAccount = account;
  } else {
    // Haven't been signed-in before. Try the silent sign-in first.
    GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOptions);
    signInClient
        .silentSignIn()
        .addOnCompleteListener(
            this,
            new OnCompleteListener<GoogleSignInAccount>() {
              @Override
              public void onComplete(@NonNull Task<GoogleSignInAccount> task) {
                if (task.isSuccessful()) {
                  // The signed in account is stored in the task's result.
                  GoogleSignInAccount signedInAccount = task.getResult();
                } else {
                  // Player will need to sign-in explicitly using via UI.
                  // See [sign-in best practices](http://developers.google.com/games/services/checklist) for guidance on how and when to implement Interactive Sign-in,
                  // and [Performing Interactive Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in) for details on how to implement
                  // Interactive Sign-in.
                }
              }
            });
  }
}

@Override
protected void onResume() {
  super.onResume();
  signInSilently();
}

If the silent sign-in attempt fails, you can call getException() to obtain an ApiException with the detailed status code. A status code of 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. The result is returned via the onActivityResult callback.

To perform the sign-in interactively, follow these steps:

  1. Call getSigninIntent() on the GoogleSignInClient to obtain a sign-in intent, then call startActivity() and pass in that intent. The following code snippet shows how your app can launch an interactive sign-in flow:

    private void startSignInIntent() {
      GoogleSignInClient signInClient = GoogleSignIn.getClient(this,
          GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
      Intent intent = signInClient.getSignInIntent();
      startActivityForResult(intent, RC_SIGN_IN);
    }
  2. In the onActivityResult() callback, handle the result from the returned intent.

    • If the sign-in result was successful, get the GoogleSignInAccount object from the GoogleSignInResult.
    • If sign-in result was not successful, you should handle the sign-in error (for example, by displaying an error message in an alert). The following code snippet shows how your app can handle the results of player sign-in:
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (result.isSuccess()) {
          // The signed in account is stored in the result.
          GoogleSignInAccount signedInAccount = result.getSignInAccount();
        } else {
          String message = result.getStatus().getStatusMessage();
          if (message == null || message.isEmpty()) {
            message = getString(R.string.signin_other_error);
          }
          new AlertDialog.Builder(this).setMessage(message)
              .setNeutralButton(android.R.string.ok, null).show();
        }
      }
    }

Retrieving player information

The 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.

  1. Obtain a PlayersClient object by calling the getPlayersClient() method, and passing in the GoogleSignInAccount as a parameter.
  2. Use the PlayersClient methods to asynchronously load the Player object that contains a player’s information. For example, you can call getCurrentPlayer() to load the currently signed-in player. If the task returns an ApiException with status code of SIGN_IN_REQUIRED, this indicates that the player needs to be re-authenticated. To do this, call GoogleSignInClient.getSignInIntent() to sign in the player interactively.
  3. If the task successfully returns the Player object, you can then call the methods of the Player object to retrieve specific player details (for example, getDisplayName() or getPlayerId().

Providing a sign-in button

To provide a standard Google sign-in button in your game, you can use one of these approaches:

When users click the sign-in button, your game should initiate the sign-in flow by sending a sign-in intent, as described in Performing interactive sign-in.

This code snippet shows how you can add a sign-in button in the onCreate() method for your activity.

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_sign_in);
  findViewById(R.id.sign_in_button).setOnClickListener(this);
  findViewById(R.id.sign_out_button).setOnClickListener(this);
}

The following code snippet shows how you can send the sign-in intent when the user clicks on the sign-in button.

@Override
public void onClick(View view) {
  if (view.getId() == R.id.sign_in_button) {
    // start the asynchronous sign in flow
    startSignInIntent();
  } else if (view.getId() == R.id.sign_out_button) {
    // sign out.
    signOut();
    // show sign-in button, hide the sign-out button
    findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
    findViewById(R.id.sign_out_button).setVisibility(View.GONE);
  }
}

Displaying game pop-ups

You can display pop-up views in your game using the 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().

Signing the player out

Signing-out is done via call the signOut() method on the GoogleSignInClient.

private void signOut() {
  GoogleSignInClient signInClient = GoogleSignIn.getClient(this,
      GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
  signInClient.signOut().addOnCompleteListener(this,
      new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
          // at this point, the user is signed out.
        }
      });
}