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

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

ワンタップ登録 UI

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

ワンタップ アカウント作成の実装は、次の 2 つの部分で構成されます。

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

ワンタップ登録はどこで使用すればよいですか?

ユーザーに One Tap サインアップを提示するうえで最も効果的な場所は、ログインすることで新機能が有効になるコンテキストです。まず、保存済みの認証情報を使用してユーザーのログインを試みます。保存された認証情報が見つからない場合は、ユーザーの新しいアカウントを作成することを提案します。

始める前に

One Tap サインインを使ってみるの説明に沿って、Google Cloud コンソール プロジェクトと Android プロジェクトを設定します。

1. ワンタップ クライアントを構成する

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

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

    • サーバー クライアント ID を Google Cloud コンソールで作成した ID に設定します。これはサーバーのクライアント ID であり、Android のクライアント 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 のキャンセルを追跡する

ユーザーがプロンプトを閉じるか、プロンプトの外側をタップして、ワンタップ登録の使用をすでに拒否しているかどうかを追跡する必要があります。たとえば、Activity のブール値プロパティを使用できます。(下記の One Tap UI の表示を停止するをご覧ください)。

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

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

  • 成功リスナー: ユーザーがデバイスで 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 を閉じるか、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() の呼び出しは CommonStatusCodes.CANCELED ステータス コードを含む ApiException をスローします。このような場合は、One Tap サインイン UI の表示を一時的に停止して、ユーザーに繰り返しプロンプトが表示されないようにする必要があります。次の例では、Activity にプロパティを設定し、そのプロパティを使用してユーザーに One Tap サインインを提供するかどうかを判断しています。ただし、SharedPreferences に値を保存したり、他の方法を使用したりすることもできます。

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 ID トークンが取得されます。このトークンには、ユーザーのメールアドレス、氏名、プロフィール写真の URL などの基本的なプロフィール情報が含まれています。多くのアプリでは、この情報だけでバックエンドでユーザーを認証し、新しいアカウントを作成できます。

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