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

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

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