Вход в игры для Android

В связи с прекращением поддержки API входа Google мы удалим SDK для игр v1 в 2026 году. После февраля 2025 года вы не сможете публиковать в Google Play игры, недавно интегрированные с SDK для игр v1. Вместо этого мы рекомендуем использовать SDK для игр v2.
Хотя существующие игры с интеграцией предыдущих игр v1 продолжат функционировать еще пару лет, вам рекомендуется перейти на v2, начиная с июня 2025 года.
Это руководство посвящено использованию SDK Play Games Services v1. Информацию о последней версии SDK см. в документации v2 .

Для доступа к функциям игровых сервисов Google Play вашей игре необходимо предоставить учётную запись вошедшего в систему игрока. Если игрок не аутентифицирован, игра может столкнуться с ошибками при вызовах API игровых сервисов Google Play. В этой документации описывается, как реализовать бесперебойный вход в игру.

Реализовать вход игрока

Класс GoogleSignInClient является основной точкой входа для получения учетной записи текущего вошедшего в систему игрока, а также для входа игрока в систему, если он ранее не сделал этого в вашем приложении на устройстве.

Чтобы создать клиент входа, выполните следующие действия:

  1. Создайте клиент входа через объект GoogleSignInOptions , как показано в следующем фрагменте кода. В GoogleSignInOptions.Builder для настройки входа необходимо указать GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN .

    GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  2. Если вы хотите использовать SnapshotsClient , добавьте .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS) в GoogleSignInOptions.Builder , как показано в следующем фрагменте кода:

    GoogleSignInOptions  signInOptions =
        new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
            .build();
  3. Вызовите метод GoogleSignIn.getClient() и передайте ему параметры, настроенные на предыдущих шагах. Если вызов успешен, API входа Google возвращает экземпляр GoogleSignInClient .

Проверьте, вошел ли игрок уже в систему

Вы можете проверить, выполнен ли вход в учётную запись на текущем устройстве, с помощью GoogleSignIn.getLastSignedInAccount() и предоставлены ли этой учётной записи необходимые разрешения, с помощью GoogleSignIn.hasPermissions() . Если оба условия истинны, то есть getLastSignedInAccount() возвращает ненулевое значение, а hasPermissions() возвращает true , вы можете безопасно использовать учётную запись, возвращённую методом getLastSignedInAccount() , даже если устройство находится в автономном режиме.

Выполните тихий вход в систему

Вы можете вызвать silentSignIn() , чтобы получить учетную запись текущего вошедшего в систему игрока, и попытаться авторизовать игроков без отображения пользовательского интерфейса, если они успешно вошли в ваше приложение на другом устройстве.

Метод silentSignIn() возвращает Task<GoogleSignInAccount> . После завершения задачи вы устанавливаете в поле GoogleSignInAccount , объявленном ранее, учётную запись входа, которую задача возвращает в качестве результата, или значение null , что указывает на отсутствие вошедшего пользователя.

Если попытка тихого входа не удалась, вы можете при желании отправить намерение входа для отображения пользовательского интерфейса входа, как описано в разделе Выполнение интерактивного входа .

Поскольку состояние вошедшего в систему игрока может измениться, когда активность не находится на переднем плане, мы рекомендуем вызывать silentSignIn() из метода onResume() активности.

Чтобы выполнить вход в скрытом режиме, выполните следующие действия:

  1. Вызовите метод silentSignIn() объекта GoogleSignInClient , чтобы начать процесс скрытого входа. Этот вызов возвращает объект Task<GoogleSignInAccount> , содержащий GoogleSignInAccount , если вход выполнен успешно.
  2. Обрабатывайте успешный или неудачный вход игрока, переопределяя OnCompleteListener .
    • Если задача входа выполнена успешно, получите объект GoogleSignInAccount , вызвав getResult() .
    • Если вход не удался, вы можете отправить намерение входа для запуска интерактивного процесса входа. Список дополнительных прослушивателей обратных вызовов, которые можно использовать, см. в руководстве разработчика Tasks API и справочнике Task API.

В следующем фрагменте кода показано, как ваше приложение может выполнять тихий вход:

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();
}

Если попытка скрытого входа не удалась, вы можете вызвать метод getException() , чтобы получить исключение ApiException с подробным кодом статуса. Код статуса CommonStatusCodes.SIGN_IN_REQUIRED означает, что игроку необходимо выполнить явное действие для входа. В этом случае ваше приложение должно запустить интерактивный процесс входа, как описано в следующем разделе.

Выполните интерактивный вход

Для входа с участием игрока вашему приложению необходимо запустить намерение входа. В случае успеха API входа Google отображает пользовательский интерфейс, предлагающий игроку ввести свои учётные данные. Такой подход упрощает разработку приложения, поскольку действие входа обрабатывает такие сценарии, как необходимость обновления сервисов Google Play или отображение запросов на согласие, от имени вашего приложения. Результат возвращается через обратный вызов onActivityResult .

Чтобы выполнить интерактивный вход, выполните следующие действия:

  1. Вызовите getSigninIntent() в GoogleSignInClient , чтобы получить намерение входа, затем вызовите startActivity() и передайте это намерение. Следующий фрагмент кода показывает, как ваше приложение может запустить интерактивный процесс входа:

    private void startSignInIntent() {
      GoogleSignInClient signInClient = GoogleSignIn.getClient(this,
          GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
      Intent intent = signInClient.getSignInIntent();
      startActivityForResult(intent, RC_SIGN_IN);
    }
  2. В обратном вызове onActivityResult() обработайте результат возвращенного намерения.

    • Если вход прошел успешно, получите объект GoogleSignInAccount из GoogleSignInResult .
    • Если вход не удался, необходимо обработать ошибку входа (например, отобразив сообщение об ошибке в оповещении). Следующий фрагмент кода показывает, как ваше приложение может обрабатывать результаты входа игрока:
    @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();
        }
      }
    }

Получить информацию об игроке

GoogleSignInAccount , возвращаемый API входа Google, не содержит никакой информации об игроке. Если ваша игра использует информацию об игроке, например отображаемое имя и идентификатор игрока, вы можете получить эту информацию, выполнив следующие действия.

  1. Получите объект PlayersClient , вызвав метод getPlayersClient() и передав GoogleSignInAccount в качестве параметра.
  2. Используйте методы PlayersClient для асинхронной загрузки объекта Player , содержащего информацию об игроке. Например, можно вызвать метод getCurrentPlayer() для загрузки текущего вошедшего в систему игрока. Если задача возвращает исключение ApiException с кодом состояния SIGN_IN_REQUIRED , это означает, что игроку требуется повторная аутентификация. Для этого вызовите GoogleSignInClient.getSignInIntent() для интерактивной авторизации игрока.
  3. Если задача успешно возвращает объект Player , вы можете вызвать методы объекта Player для получения конкретных данных об игроке (например, getDisplayName() или getPlayerId() .

Предоставить кнопку входа

Чтобы добавить в свою игру стандартную кнопку входа Google, можно использовать один из следующих подходов:

Когда пользователи нажимают кнопку входа, ваша игра должна инициировать процесс входа, отправив намерение входа, как описано в разделе Выполнение интерактивного входа .

В этом фрагменте кода показано, как можно добавить кнопку входа в метод onCreate() для вашей активности.

@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);
}

В следующем фрагменте кода показано, как можно отправить намерение входа, когда пользователь нажимает кнопку входа.

@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);
  }
}

Отображать всплывающие окна игр

Вы можете отображать всплывающие окна в своей игре с помощью класса GamesClient . Например, в игре может отображаться всплывающее окно с сообщением «С возвращением» или «Достижения разблокированы». Чтобы разрешить сервисам Google Play Games Services запускать всплывающие окна в играх, вызовите метод setViewForPopups() . Вы также можете настроить место появления всплывающего окна на экране, вызвав метод setGravityForPopups() .

Вывести игрока из аккаунта

Выход из системы осуществляется с помощью вызова метода signOut() в 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.
        }
      });
}