Following the deprecation of the
[Google Sign-In](https://android-developers.googleblog.com/2024/09/streamlining-android-authentication-credential-manager-replaces-legacy-apis.html)
API, we are removing the games v1 SDK in 2026. After February 2025, you will be unable to publish
titles that are newly integrated with games v1 SDK, on Google Play. We recommend that you use the
games v2 SDK instead.  

While existing titles with the previous games v1 integrations continue to function for a
couple of years, you are encouraged to
[migrate to v2](https://developer.android.com/games/pgs/android/migrate-to-v2)
starting June 2025.  

This guide is for using the Play Games Services v1 SDK. For information
on the latest SDK version, see the
[v2 documentation](https://developer.android.com/games/pgs/android/server-access).

If your game uses a backend server, we recommend that you use
[Google Sign-In](https://developers.google.com/identity/sign-in/android/) to authenticate players and
securely pass the player's identity to the backend server. This also enables
your game to securely retrieve the player's identity and other data without
being exposed to potential tampering while passing through the device.

In this scenario, your game prompts the player to sign in to Google Play Games Services as usual. When the
player signs in successfully, the [`GoogleSignInAccount`](https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount) object contains a special single-use code
(called the *server auth code*) that the client passes to the server. Then, on the server, exchange
the server auth code for an OAuth 2.0 token that the server can use to make calls to the
Google Play Games Services API.

For additional guidance on adding sign-in in your games, see
[Sign-in in Android Games](https://developer.android.com/games/pgs/v1/android/signin).

To see a detailed code sample showing how to use Google Sign-In to authenticate players, see the
[`clientserverskeleton` sample](https://github.com/playgameservices/clientserverskeleton) on GitHub.

The following steps are required for offline access:

1. In the Google Play Console: Create a credential for your game server. The OAuth client type of the credential will be "web".
2. In the Android app: As part of sign-in, request a server auth code for your server's credential, and pass that to your server.
3. On your game server: Exchange the server auth code for an OAuth access token using Google auth services, and then use this to call the Play Games Services [REST APIs](https://developer.android.com/games/services/web/api/rest).

## Before you begin

Before you can integrate Google Sign-In into your game, you'll first need to add your game in the
[Google Play Console](https://play.google.com/apps/publish/), as described in
[Setting Up Google Play Games Services](https://developer.android.com/games/pgs/console/setup).

## Create an associated server-side web application for your game

Google Play Game services does not provide back-end
support for Web games. However, it does provide back-end server support
for your Android game's server.

If you want to use the
[REST APIs for Google Play Games services](https://developer.android.com/games/services/web/api/rest)
in your server-side app, follow these steps:

1. Create an associated web app for your game in the **Linked Apps** section of the [Google Play Console](https://play.google.com/apps/publish/). Note that the `launch_url` is not used for this flow and can be left blank.
2. To get the credential information for your app, follow these steps:
   1. From your game in the Google Play Console, click **Game Details**.
   2. Scroll down to the **API Console Project** section and click on the link to the API console project.
   3. From the **APIs \& Services \> Credentials** screen in the Google API Console, download the `client_secret.json` file for your web app and save it to a location that your server can access. Record the client ID of the credential for later reference.
3. Restart your server-side app so it's ready to accept requests from your game's client app.

## Perform sign-in on the client

The [`GoogleSignInClient`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/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.
| **Note:** The [`GoogleSignInClient`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInClient) class makes use of the Google Play services [`Task`](https://developer.google.com/android/reference/com/google/android/gms/tasks/Task) class to return results asynchronously. To learn more about using tasks to manage threaded work, see the [Tasks API developer guide](https://developer.google.com/android/guides/tasks).

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

1. Create a sign-in client via the [`GoogleSignInOptions`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions) object. In the [`GoogleSignInOptions.Builder`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.Builder) to configure your sign-in, you must specify [`GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.html#DEFAULT_GAMES_SIGN_IN).
2. You must also specify that your game requires an auth code for your backend server by calling the [`GoogleSignInOptions.Builder.requestServerAuthCode()`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.Builder.html#requestServerAuthCode(java.lang.String,%20boolean)) method with server's client ID as the parameter. You will retrieve the auth code later for access tokens on your backend server, as described in [Get the server auth code](https://developer.android.com/games/pgs/v1/android/server-access#get-auth-code).
3. Call the [`GoogleSignIn.getClient()`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignIn.html#getClient(android.app.Activity,%20com.google.android.gms.auth.api.signin.GoogleSignInOptions)) method and pass in options you previously configured. If the call is successful, Google Sign-In API returns an instance of [`GoogleSignInClient`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInClient).
4. Once you have obtained the [`GoogleSignInClient`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInClient) instance, you should proceed to sign the player in silently from the activity's `onResume()`, as described in [Performing silent sign-in](https://developer.android.com/games/pgs/v1/android/signin#silent-signin).

Here's an example:  

```scdoc
private static final int RC_SIGN_IN = 9001;
private GoogleSignInClient mGoogleSignInClient;

private void startSignInForAuthCode() {

  // Client ID for your backend server.
  String webClientId = getString(R.string.webclient_id);

  GoogleSignInOptions signInOption = new
      GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
      .requestServerAuthCode(webClientId)
      .build();

  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  Intent intent = signInClient.getSignInIntent();
  startActivityForResult(intent, RC_SIGN_IN);
}
```

## Get the server auth code

To retrieve a server auth code that your game can use for access tokens on your backend server,
call the [getServerAuthCode()](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount.html#getServerAuthCode())
method on the [GoogleSignInAccount](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount)
object that Google Sign-In returns on successful player sign-in.

Here's an example:  

```scilab
// Auth code to send to backend server.
private String mServerAuthCode;

@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()) {
      mServerAuthCode = result.getSignInAccount().getServerAuthCode();
    } 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();
    }
  }
}
```

## Exchange the server auth code for an access token on the server

Send the server auth code to your backend server to exchange for access and refresh tokens.
Use the access token to call the Google Play Games Services API on behalf of the player and, optionally,
store the refresh token to acquire a new access token when the access token expires.

The following code snippet shows how you might implement the server-side code in the Java
programming language to exchange the server auth code for access tokens. It is
using the
[clientserverskeleton sample app](https://github.com/playgameservices/clientserverskeleton/tree/master/ServerApp/src/main/java/com/google/sample/games):  

    /**
     * Exchanges the authcode for an access token credential.  The credential
     * is the associated with the given player.
     *
     * @param authCode - the non-null authcode passed from the client.
     * @param player   - the player object which the given authcode is
     *                 associated with.
     * @return the HTTP response code indicating the outcome of the exchange.
     */
    private int exchangeAuthCode(String authCode, Player player) {
    try {

        // The client_secret.json file is downloaded from the Google API
        // console.  This is used to identify your web application.  The
        // contents of this file should not be shared.
        //
        File secretFile = new File("client_secret.json");

        // If we don't have the file, we can't access any APIs, so return
        // an error.
        if (!secretFile.exists()) {
            log("Secret file : " + secretFile
                    .getAbsolutePath() + "  does not exist!");
            return HttpServletResponse.SC_FORBIDDEN;
        }

        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
                JacksonFactory.getDefaultInstance(), new
                FileReader(secretFile));

        // Extract the application id of the game from the client id.
        String applicationId = extractApplicationId(clientSecrets
                .getDetails().getClientId());

        GoogleTokenResponse tokenResponse =
                new GoogleAuthorizationCodeTokenRequest(
                HTTPTransport,
                JacksonFactory.getDefaultInstance(),
                "https://oauth2.googleapis.com/token",
                clientSecrets.getDetails().getClientId(),
                clientSecrets.getDetails().getClientSecret(),
                authCode,
                "")
                .execute();

        log("hasRefresh == " + (tokenResponse.getRefreshToken() != null));
        log("Exchanging authCode: " + authCode + " for token");
        Credential credential = new Credential
                .Builder(BearerToken.authorizationHeaderAccessMethod())
                .setJsonFactory(JacksonFactory.getDefaultInstance())
                .setTransport(HTTPTransport)
                .setTokenServerEncodedUrl("https://www.googleapis.com/oauth2/v4/token")
                .setClientAuthentication(new HttpExecuteInterceptor() {
                    @Override
                    public void intercept(HttpRequest request)
                            throws IOException {
                            }
                })
                .build()
                .setFromTokenResponse(tokenResponse);

        player.setCredential(credential);

        // Now that we have a credential, we can access the Games API.
        PlayGamesAPI api = new PlayGamesAPI(player, applicationId,
                HTTPTransport, JacksonFactory.getDefaultInstance());

        // Call the verify method, which checks that the access token has
        // access to the Games API, and that the player id used by the
        // client matches the playerId associated with the accessToken.
        boolean ok = api.verifyPlayer();

        // Call a Games API on the server.
        if (ok) {
            ok = api.updatePlayerInfo();
            if (ok) {
                // persist the player.
                savePlayer(api.getPlayer());
            }
        }

        return ok ? HttpServletResponse.SC_OK :
                HttpServletResponse.SC_INTERNAL_SERVER_ERROR;

      } catch (IOException e) {
        e.printStackTrace();
      }
      return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
    }

To learn more about accessing Google APIs from a backend server on behalf of a signed-in player,
see [Enabling Server-Side Access](https://developer.google.com/identity/sign-in/android/offline-access).

## Handle player sign-out

To sign players out of your game, call the [`signOut()`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInClient.html#signOut()) method on the [`GoogleSignInClient`](https://developer.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInClient). For an
example code snippet, see
[Signing the player out](https://developer.android.com/games/pgs/v1/android/signin#sign-out).

## Call REST APIs from the server

Refer to [REST APIs for Google Play Games services](https://developer.android.com/games/services/web/api/rest) for
a full description of API calls available.

Examples of REST API calls that you may find useful include the following:

### Player

- Want to get the signed-in player's ID and profile data? Call [Players.get](https://developer.android.com/games/services/web/api/rest/v1/players/get) with `'me'` as the ID.

### Friends

Make sure you review the [Friends](https://developer.android.com/games/pgs/friends) guide, which explains Friends in more detail.

- Want to retrieve the player's list of friends? Call [Players.list](https://developer.android.com/games/services/web/api/rest/v1/players/list) with `'friends_all'` as the `collection`.
- Check if you have access to the friends list? Call [Players.get](https://developer.android.com/games/services/web/api/rest/v1/players/get) for `me`, and look at the [`profileSettings.friendsListVisibility`](https://developer.android.com/games/services/web/api/rest/v1/players#profileSettings.friendsListVisibility) field in the response.

### Achievements

Make sure you review the [Achievements](https://developer.android.com/games/pgs/achievements) guide, which explains achievements
in more detail.

- Want to get a list of current achievements? You can make a call to [AchievementDefinitions.list](https://developer.android.com/games/services/web/api/rest/v1/achievementDefinitions/list).
- Combine that with a call to [Achievements.list](https://developer.android.com/games/services/web/api/rest/v1//achievements/list) to find out which ones the player unlocked.
- Did the player earn an achievement? Use [Achievements.unlock](https://developer.android.com/games/services/web/api/rest/v1/achievements/unlock) to unlock it!
- Did the player make progress towards a partial achievement? Use [Achievements.increment](https://developer.android.com/games/services/web/api/rest/v1/achievements/increment) to report progress (and find out if the player unlocked it).
- Are you debugging a game that is not yet in production? Try calling [Achievements.reset](https://developer.android.com/games/services/management/api/achievements/reset) or [Achievements.resetAll](https://developer.android.com/games/services/management/api/achievements/resetAll) from the Management APIs to reset achievements to their original state.

### Leaderboards

Make sure you review the [Leaderboards](https://developer.android.com/games/pgs/leaderboards) guide, which explains leaderboards in more detail.

- Want to get a list of all scoreboards in the game? Make a call to [Leaderboards.list](https://developer.android.com/games/services/web/api/rest/v1/leaderboards/list).
- Is the player done with a game? You can submit their score to [Scores.submit](https://developer.android.com/games/services/web/api/rest/v1/scores/submit) and find out if this is a new high score.
- Want to display a leaderboard? Get the data from [Scores.list](https://developer.android.com/games/services/web/api/rest/v1/scores/list) and show it to the user.
- Use [Scores.listWindow](https://developer.android.com/games/services/web/api/rest/v1/scores/listWindow) to find an assortment of scores close to the user's high score.
- To get more information about the player's score in a particular leaderboard (for example, if the player is in the top 12% of all players), call [Scores.get](https://developer.android.com/games/services/web/api/rest/v1/scores/get).
- Are you debugging a game? Try calling [Scores.reset](https://developer.android.com/games/services/management/api/scores/reset) from the Management APIs to reset all scores for that player from a particular leaderboard