[Android] Androidにおける2パターンのGoogleSignInについて

# 概要
AndroidでのGoogleサインインには、2種類の方法があることを知りました。
また、少し各実装に手間取ったので備忘録として記事を書きます。

# 2種類のサインイン画面
| パターン1 | パターン2 |
| ---- | ---- |
| ![Screenshot_20231103_010916.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351982/44d9f885-421d-4d45-234b-cdf55293480a.png) | ![Screenshot_20231103_010954.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351982/054dd3d6-56b7-1a2a-1542-c8348a31f98e.png)|

# 実装
まずは公式ドキュメントを一読する。
[公式ドキュメント](https://developers.google.com/identity/sign-in/android/sign-in?hl=ja)

### 注意点
上記ドキュメントではonActivityResultを使っている。
しかし、これは現在において非推奨の方法です。
なのでここでは推奨されているregisterForActivityResultを使用した方法に変更します。

### パターン1
1. サインイン画面を呼び出す処理を記載します。
```kotlin
 private fun googleSignInPattern1() {
        val googleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(idToken) // ここは各自の環境のidを記載してください。
            .requestEmail()
            .build()

        GoogleSignIn.getClient(this, googleSignInOptions).signInIntent.also {
            patter1Launcher.launch(it)
        }
    }
```
2. 次にアカウントが選択された後の処理を記載する。
```kotlin
private val patter1Launcher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            pattern1SignInGoogleResult(result)
        }

private fun pattern1SignInGoogleResult(result: ActivityResult) {
        if (result.resultCode == RESULT_OK) {
            if (result.data != null) {
                val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
                handleSignInResult(task)
            }
        } else {
            Toast.makeText(this, "result code is not RESULT_OK", Toast.LENGTH_SHORT).show()
        }
    }

    private fun pattern2SignInGoogleResult(result: ActivityResult) {
        if (result.resultCode == RESULT_OK) {
            if (result.data != null) {
                val credential = try {
                    Identity.getSignInClient(this).getSignInCredentialFromIntent(result.data)
                } catch (e: Exception) {
                    // ログインキャンセル時等にExceptionが発生する
                    Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()
                    null
                }
                val idToken = credential?.googleIdToken
                if (idToken != null) {
                    Toast.makeText(this, "success", Toast.LENGTH_LONG).show()
                }
            }
        } else {
            Toast.makeText(this, "result code is not RESULT_OK", Toast.LENGTH_SHORT).show()
        }
    }
```
**注意するポイント**
1. 一度サインインすると以後サインアウトをしないとアカウント選択画面が出なくなります。

### パターン2
1. こちら同様にサインイン画面を呼び出す処理を記載します。
```kotlin
private fun googleSignInPattern2() {
        val oneTapClient = Identity.getSignInClient(this)
        val signInRequest = try {
            BeginSignInRequest.Builder()
                .setPasswordRequestOptions(
                    BeginSignInRequest.PasswordRequestOptions.Builder()
                        .setSupported(true)
                        .build()
                )
                .setGoogleIdTokenRequestOptions(
                    BeginSignInRequest.GoogleIdTokenRequestOptions.Builder()
                        .setSupported(true)
                        .setServerClientId(idToken) // ここは各自の環境のidを記載してください。
                        .setFilterByAuthorizedAccounts(false)
                        .build()
                )
                .build()
        } catch (e: Exception) {
            Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()
            null
        }
        signInRequest?.let {
            oneTapClient.beginSignIn(signInRequest)
                .addOnSuccessListener {
                    patter2launcher.launch(
                        IntentSenderRequest.Builder(it.pendingIntent.intentSender).build()
                    )
                }
                .addOnFailureListener { e ->
                    Toast.makeText(
                        this,
                        e.message,
                        Toast.LENGTH_SHORT
                    ).show()
                }
        } ?: run {
            Toast.makeText(this, "signInRequest is null", Toast.LENGTH_SHORT).show()
        }
    }
```
**注意するポイント**
1. こちらはアカウント選択時にキャンセルを複数回繰り返すと24時間サインイン画面が出なくなります。こちら公式サイトに記載もあります。
[公式サイト](https://developers.google.com/identity/one-tap/android/get-saved-credentials?hl=ja#disable-one-tap)

以上です！

# 最後に
こちらに実装したアプリをリポジトリを置いておきます。
https://github.com/NaokiNishizawa/SampleGoogleSignIn

本記事が誰かの助けになれれば幸いです!
※ いいね頂けると死ぬほど喜びます！！:laughing: