Создавайте аккаунты одним нажатием

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

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

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

Реализация регистрации в одно касание состоит из двух частей:

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

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

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

Подготовка

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

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

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

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

Java

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

        // ...
    }
}

Kotlin

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, закрыв окно или нажав за его пределами. Например, можно использовать логическое свойство Activity. (см. раздел Как отключить показ интерфейса One Tap ниже).

3. Как показать интерфейс регистрации через One Tap

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

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

Java

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

Kotlin

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. Обработка ответа пользователя

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

Как создать аккаунт с помощью токена идентификатора Google

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

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

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

Java

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

Kotlin

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. В этом случае следует временно прекратить показ интерфейса входа через One Tap, чтобы не раздражать пользователей повторяющимися запросами. В примере ниже это делается путем настройки свойства в Activity, которое используется для определения того, предлагать ли пользователю вход через One Tap. Однако вы также можете сохранить значение в SharedPreferences или использовать другой метод.

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

Java

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

Kotlin

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})")
                          }
                      }
                  }
              }
          }
      }
      // ...
  }

Дальнейшие действия

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

Если для создания аккаунта вам нужна дополнительная информация, например дата рождения пользователя, запросите ее на этапе регистрации, а затем отправьте на сервер.