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

Чтобы получить доступ к функциям игровых сервисов 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() и передайте параметры, настроенные на предыдущих шагах. Если вызов выполнен успешно, Google Sign-In API возвращает экземпляр 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 указывает на то, что игроку необходимо выполнить явное действие для входа в систему. В этом случае ваше приложение должно запустить интерактивный процесс входа, как описано в следующем разделе.

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

Чтобы выполнить вход с помощью взаимодействия с игроком, ваше приложение должно запустить намерение входа. В случае успеха Google Sign-In API отображает пользовательский интерфейс, который предлагает игроку ввести свои учетные данные для входа. Такой подход упрощает разработку вашего приложения, поскольку действие входа обрабатывает такие сценарии, как необходимость обновления сервисов 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 , который возвращает Google Sign-In API, не содержит никакой информации об игроке. Если в вашей игре используется информация об игроке, такая как отображаемое имя и идентификатор игрока, вы можете выполнить следующие действия, чтобы получить эту информацию.

  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 могли запускать всплывающие окна в представлениях вашей игры, вызовите метод 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.
        }
      });
}