Создавайте новые учетные записи одним нажатием

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

Интерфейс регистрации в одно касание

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

Реализация создания учетной записи One Tap состоит из двух частей:

  • Интеграция клиента One Tap в ваше приложение, описанная на этой странице. По сути, это то же самое, что и вход в систему одним касанием, но с некоторыми отличиями в конфигурации.
  • Добавление в ваш бэкэнд возможности создавать учетные записи пользователей из токенов Google ID, что обсуждается в разделе Использование токенов ID на бэкэнде .

Где мне следует использовать регистрацию One Tap?

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

Прежде чем начать

Настройте проект консоли API Google и проект Android, как описано в разделе Начало работы с входом в одно касание .

1. Настройте клиент One Tap.

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

  • Не включайте запросы учетных данных пароля. (Регистрация в одно касание возможна только при аутентификации на основе токенов.)
  • Включите запросы токенов идентификатора Google, используя setGoogleIdTokenRequestOptions() и следующие настройки:

Ява

public class YourActivity extends AppCompatActivity {

  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signUpRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signUpRequest = BeginSignInRequest.builder()
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.your_web_client_id))
                      // Show all accounts on the device.
                      .setFilterByAuthorizedAccounts(false)
                      .build())
              .build();

      // ...
  }
}

Котлин

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signUpRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signUpRequest = BeginSignInRequest.builder()
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Show all accounts on the device.
                    .setFilterByAuthorizedAccounts(false)
                    .build())
            .build()
        // ...
    }
    // ...
}

2. Отслеживайте отмену пользовательского интерфейса One Tap.

Вам следует отслеживать, отказался ли пользователь уже от использования регистрации в одно касание, закрыв подсказку или нажав за ее пределами. Это может быть просто логическое свойство вашей активности. (См. раздел «Отключение отображения пользовательского интерфейса One Tap» ниже.)

3. Отображение пользовательского интерфейса регистрации в одно касание.

Если пользователь не отказался использовать One Tap для создания новой учетной записи, вызовите метод beginSignIn() клиентского объекта и прикрепите прослушиватели к возвращаемой Task . Приложения обычно выполняют этот шаг, когда запрос на вход в One Tap не находит сохраненных учетных данных, то есть в прослушивателе ошибок запроса на вход.

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

Если у пользователя нет учетных записей Google на устройстве, клиент One Tap вызовет прослушиватель ошибок. В этом случае никаких действий не требуется: вы можете просто продолжать демонстрировать опыт выхода из приложения, а пользователь может зарегистрироваться, используя обычный процесс создания учетной записи.

Ява

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No Google Accounts found. Just continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Котлин

oneTapClient.beginSignIn(signUpRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No Google Accounts found. Just continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. Обработка ответа пользователя

Ответ пользователя на приглашение на регистрацию в одно касание будет передан в ваше приложение с помощью метода onActivityResult() вашего действия. Если пользователь решил создать учетную запись, результатом будет токен Google ID. Если пользователь отказался зарегистрироваться, закрыв пользовательский интерфейс One Tap или нажав за его пределами, результат вернется с кодом RESULT_CANCELED . Ваше приложение должно обрабатывать обе возможности.

Создайте учетную запись с помощью токена Google ID.

Если пользователь решил зарегистрироваться с помощью учетной записи Google, вы можете получить токен идентификатора для пользователя, передав данные о намерении из onActivityResult() в метод getSignInCredentialFromIntent() клиента One Tap. Учетные данные будут иметь свойство googleIdToken , отличное от NULL.

Используйте токен идентификатора, чтобы создать учетную запись на своем сервере (см. Аутентификация с помощью сервера с использованием токенов идентификатора ) и войдите в систему пользователя.

Учетные данные также содержат любую запрошенную вами дополнительную информацию, например подтвержденный номер телефона учетной записи, если он доступен.

Ява

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Котлин

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
            }
        }
    }
    // ...
}

Прекратить отображение пользовательского интерфейса One Tap

Если пользователь отказался войти в систему, вызов getSignInCredentialFromIntent() вызовет исключение ApiException с кодом состояния CommonStatusCodes.CANCELED . В этом случае вам следует временно прекратить отображение пользовательского интерфейса входа в систему одним касанием, чтобы не раздражать пользователей повторяющимися запросами. В следующем примере это достигается путем установки свойства действия, которое используется для определения того, предлагать ли пользователю вход в систему одним касанием; однако вы также можете сохранить значение в SharedPreferences или использовать какой-либо другой метод.

Важно реализовать собственное ограничение скорости запросов на вход в систему одним касанием. Если вы этого не сделаете и пользователь отменит несколько запросов подряд, клиент One Tap не будет отправлять пользователю запросы в течение следующих 24 часов.

Ява

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              break;
      }
  }
}

Котлин

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

Следующие шаги

Когда пользователь завершает процесс регистрации в одно касание, вы получаете токен Google ID, который включает в себя некоторую базовую информацию профиля: адрес электронной почты пользователя, полное имя и URL-адрес изображения профиля. Для многих приложений этой информации достаточно, чтобы аутентифицировать пользователя на серверной стороне и создать новую учетную запись.

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