ワンタップで新しいアカウントを作成できます

Google アカウントによるログインをサポートしている場合は、ワンタップ ログイン クライアントを使用して、アプリのコンテキストから外れることのないスムーズなアカウント作成をユーザーに提供することもできます。

ワンタップ登録の UI

ワンタップ UI を表示すると、ユーザーはデバイス上の Google アカウントのいずれかを使用して、アプリで新しいアカウントを作成するように求められます。ユーザーが続行を選択すると、基本的なプロフィール情報(名前、プロフィール写真、確認済みのメールアドレス)を含む ID トークンを受け取ります。この ID トークンを使用して新しいアカウントを作成できます。

ワンタップによるアカウント作成の実装は、次の 2 つの部分に分かれます。

  • ワンタップ クライアントをアプリに統合する。これについては、このページで説明します。これはワンタップ ログインを使用する場合とほぼ同じですが、構成にいくつかの違いがあります。
  • Google ID トークンからユーザー アカウントを作成する機能をバックエンドに追加する。詳しくは、バックエンドでの ID トークンの使用をご覧ください。

ワンタップ登録はどこで利用できますか?

ユーザーにワンタップの登録を促すうえで最も効果が高いのは、ログインすることで新機能を利用できる状況です。まず、保存済みの認証情報でユーザーのログインを試します。保存された認証情報が見つからない場合は、ユーザーの新しいアカウントを作成することを提案します。

始める前に

ワンタップ ログインのスタートガイドの説明に沿って、Google API コンソール プロジェクトと Android プロジェクトを設定します。

1. ワンタップ クライアントを設定する

アカウント作成用にワンタップ クライアントを設定する手順は次のとおりです。

  • パスワード認証情報のリクエストを有効にしない。(ワンタップ登録はトークンベースの認証でのみ可能です)。
  • setGoogleIdTokenRequestOptions() と次の設定を使用して、Google ID トークン リクエストを有効にします。

    • サーバーのクライアント ID を Google API コンソールで作成した ID に設定します。これは、Android クライアント ID ではなく、サーバーのクライアント ID です。
    • デバイス上のすべての Google アカウントを表示するようにクライアントを構成します(承認済みアカウントでフィルタしないでください)。
    • 必要に応じて、アカウントの確認済みの電話番号をリクエストすることもできます。

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. ワンタップ UI のキャンセルを追跡する

プロンプトを閉じるか、プロンプトの外側をタップして、ユーザーがワンタップ登録の使用をすでに拒否しているかどうかを追跡する必要があります。これは、アクティビティのブール値プロパティと同じくらい簡単です。(下記のワンタップ UI の表示を停止するをご覧ください)。

3. ワンタップ登録の UI を表示する

ユーザーがワンタップを使用した新しいアカウントを作成することを拒否していない場合は、クライアント オブジェクトの beginSignIn() メソッドを呼び出し、返される Task にリスナーをアタッチします。アプリでこの手順は通常、ワンタップ ログイン リクエストで保存済みの認証情報が見つからない場合(つまり、ログイン リクエストの失敗リスナー内にあります)に行います。

ユーザーがデバイスに 1 つ以上の Google アカウントを設定している場合、ワンタップ クライアントは成功リスナーを呼び出します。成功リスナーで、Task の結果からペンディング インテントを取得し、それを startIntentSenderForResult() に渡してワンタップ UI を開始します。

ユーザーがデバイスに Google アカウントを持っていない場合、ワンタップ クライアントは失敗リスナーを呼び出します。この場合、何もする必要はありません。そのままログアウトした状態でアプリの表示を続け、ユーザーは通常のアカウント作成フローで登録できます。

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. ユーザーの応答を処理する

ワンタップの登録プロンプトに対するユーザーの応答は、アクティビティの onActivityResult() メソッドを使用してアプリに報告されます。ユーザーがアカウントの作成を選択した場合、結果は Google ID トークンになります。ユーザーがワンタップ UI を閉じるか、アウトラインをタップすることで登録を拒否した場合は、コード RESULT_CANCELED が返されます。アプリは両方の可能性に対応する必要があります。

Google ID トークンを使用してアカウントを作成する

ユーザーが Google アカウントでの登録を選択した場合は、onActivityResult() からワンタップ クライアントの getSignInCredentialFromIntent() メソッドにインテント データを渡すことで、ユーザーの ID トークンを取得できます。認証情報には null 以外の googleIdToken プロパティがあります。

ID トークンを使用してバックエンドにアカウントを作成し(ID トークンを使用してバックエンドで認証するを参照)、ユーザーのログインを行います。

認証情報には、アカウントの確認済みの電話番号など、リクエストした追加情報も含まれます。

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

ワンタップ UI の表示を停止する

ユーザーがログインを拒否した場合、getSignInCredentialFromIntent() の呼び出しは ApiExceptionCommonStatusCodes.CANCELED ステータス コードをスローします。このような場合は、ワンタップ ログイン UI の表示を一時的に停止して、繰り返し表示されるプロンプトでユーザーに迷惑をかけることがないようにします。次の例では、アクティビティにプロパティを設定して、ユーザーにワンタップ ログインを提供するかどうかを決定しています。ただし、SharedPreferences に値を保存するなど、別のメソッドを使用することもできます。

独自のワンタップ ログイン プロンプトのレート制限を実装することが重要です。キャンセルしない場合、ユーザーが複数のプロンプトを続けてキャンセルすると、ワンタップ クライアントから 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})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

次のステップ

ユーザーがワンタップの登録フローを完了すると、Google ID トークンを受け取ります。この ID トークンには、基本的なプロフィール情報(ユーザーのメールアドレス、氏名、プロフィール写真の URL)が含まれています。多くのアプリでは、バックエンドでユーザーを認証して新しいアカウントを作成する場合は、この情報で十分です。

アカウントの作成に追加情報(ユーザーの生年月日など)が必要な場合は、登録情報フローをユーザーに提示して、この追加情報をリクエストします。その後、バックエンドに送信してアカウントの作成を完了します。