[Unity] OneTapログインの実装

# 概要
https://developers.google.com/identity/one-tap/android/overview?hl=ja
未来の自分のために備忘録として残す
# 経緯
Nonceを扱える既存ライブラリを見つけられなかった
# 実装
Unityのバージョンは[2021.3.23f1]

### 1. ExternalDependencyManagerの導入
パッケージのリンクがあるので踏んで落とす
https://github.com/googlesamples/unity-jar-resolver/releases/tag/v1.2.176
※Firebase等を導入していれば必要ないかも

### 2. Javaファイルの作成
いつからかjavaファイルを入れるだけで勝手にビルドしてくれるようになったので活用する
パスは[Assets/Plugins/Android/MyClass.java]
※ファイル名とクラス名は必ず一致させる
<details><summary>MyClass.java</summary><div>

ここのサンプルまんまでいける
https://developers.google.com/identity/one-tap/android/get-saved-credentials?hl=ja

```java
package MyPackage;

import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import com.google.android.gms.auth.api.identity.BeginSignInRequest;
import com.google.android.gms.auth.api.identity.GetSignInIntentRequest;
import com.google.android.gms.auth.api.identity.Identity;
import com.google.android.gms.auth.api.identity.SignInClient;
import com.google.android.gms.auth.api.identity.SignInCredential;
import com.google.android.gms.common.api.ApiException;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

public class MyClass extends UnityPlayerActivity {
    final int SignInCode = 999;
    SignInClient client;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        client = Identity.getSignInClient(this);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == SignInCode) {
            try {
                SignInCredential credential = client.getSignInCredentialFromIntent(data);
                var jwt = credential.getGoogleIdToken();
                UnityPlayer.UnitySendMessage("", "", jwt);
            }
            catch (ApiException e) {
                UnityPlayer.UnitySendMessage("", "", e.toString());
            }
        }
    }

    public void SignInGoogle(String clientId, String nonce) {
        // GetSignInIntentRequest request = GetSignInIntentRequest.builder()
        //     .setServerClientId(clientId)
        //     .setNonce(nonce)
        //     .build();
        BeginSignInRequest request = BeginSignInRequest.builder()
            .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions
                .builder()
                .setSupported(true)
                .build()
            )
            .setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions
                .builder()
                .setSupported(true)
                .setServerClientId(clientId)
                .setNonce(nonce)
                .build()
            )
            .setAutoSelectEnabled(true)
            .build();

        // client.getSignInIntent(request)
        client.beginSignIn(request)
            .addOnSuccessListener(result -> {
                try {
                    startIntentSenderForResult(
                        // result.getIntentSender(),
                        result.getPendingIntent().getIntentSender(),
                        SignInCode,
                        null, 0, 0, 0, null
                    );
                }
                catch (IntentSender.SendIntentException e) {
                    UnityPlayer.UnitySendMessage("", "", e.toString());
                }
            })
            .addOnCanceledListener(() -> {
                UnityPlayer.UnitySendMessage("", "", "canceled");
            })
            .addOnFailureListener(e -> {
                UnityPlayer.UnitySendMessage("", "", e.toString());
            });
    }

    public void SignOutGoogle() {
        client.signOut();
    }
}
```
コメントアウト部分を置き換えると古いUIにできる
細かいところは各プロジェクト毎に変えれば良い
</div></details>

### 3. 依存パッケージの追加
javaで書いたidentityのAPIを使えるようにする
任意のEditorフォルダ(?)にxmlファイルを追加
<details><summary>MyClassDependencies.xml</summary><div>

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<dependencies>
  <androidPackages>
    <androidPackage spec="com.google.android.gms:play-services-auth:20.5.0">
    </androidPackage>
  </androidPackages>
</dependencies>
```
</div></details>

### 4. AndroidManifestの作成
Project Settings > Player > Publish Settings
Custom Main Manifest ☑

Assets/Plugins/Android/AndroidManifest.xml
に作成される

7行目のactivityのnameをさっき作ったjavaファイルに合わせる
MyPackage.MyClass(パッケージ+クラス名)

### 5. ビルドして確認

# 細かい注意点等
・Firebaseの設定と並行でやってたので抜け漏れはあるかも

・javaに渡すClientIdは 'client_type=3（ウェブアプリケーション）'
Firebaseプロジェクトからgoogle-services.json落とすと分かりやすい

・c#側でコールする場合
```
×
ajo = new AndroidJavaObject("MyPackage.MyClass");
○
ajo = new AndroidJavaClass("com.unity3d.player.UnityPlayer")
    .GetStatic<AndroidJavaObject>("currentActivity");
```

~~・UnityPlayerActivity継承するしかないんかな~~