UnityでGoogle Sign Inを実装する場合、Google公式のライブラリを利用するのが一般的です。
しかし、最終更新日が5年ぐらい前で、最新のFirebaseライブラリーと組み合わせて使うと動きません。
この問題を解消するため、Androidネイティブ連携でGoogle Sign Inを行う方法と、Sign Inした結果をUnity用のFirebaseAuthライブラリーと連携させる方法を詳しく解説します。
何か問題があった時デバッグしやすいように、Android Logcatパッケージを追加しておく事をオススメします。
実機でアプリが立ち上がるとAndroid Logcatも自動的に起動して、ログを表示してくれます。
iOSネイティブ連携でGoogle Sign Inを実装する方法はコチラ
Firebaseの用意
Firebaseにアプリ用のプロジェクトを作成したらUnityアプリとして登録し、Androidの欄に必要項目を記入します。
そして、Unity側で呼ぶFirebaseAuthとAndroidネイティブのGoogle Sign Inを紐付けるための準備をしていきます。
Google Sign Inの有効化
構築欄のAuthenticationを選び、新しいプロバイダを追加からGoogleを選び、Google Sign Inを有効にします。
フィンガープリントの登録
Google Sign Inをするには、Firebaseプロジェクトにフィンガープリントを登録しないといけません。
登録する場所は、該当アプリのFirebaseプロジェクトを開き、左上の設定アイコンを押して「プロジェクトの設定」
下の方にスクロールすると「SHA証明書フィンガープリント」という欄があるので「フィンガープリントを追加」で追加します。
デバッグ環境用のフィンガープリントは、ターミナルを開き次のコマンドを叩くことで取得できます。
キーストアのパスワードは「android」です。
// Mac
keytool -list -v -keystore ~/.android/debug.keystore
// Windows
keytool -list -v -keystore %USERPROFILE%\.android\debug.keystore
本番用のフィンガープリントは、Google Play Consoleで該当アプリを開き
設定 > アプリの署名 > アプリ署名鍵の証明書 > SHA1 証明書のフィンガープリント
に記載があります。
Google PlayにまだAndroidアプリを登録していない場合は、まず登録をしてから上記を確認してみてください。
設定ファイルの配置
全ての準備が完了したら、左上の歯車ボタンを押して、プロジェクトの設定を選び、google-services.jsonをダウンロードしたら、UnityプロジェクトのAssetsフォルダに配置します。
AndroidネイティブでGoogle Sign In
では、AndroidネイティブのGoogle Sign Inを実装していきましょう。
まず、File > Build Settingsで、PlatformをAndroidに切り替えておきます。
AndroidネイティブはActivityというもので画面が構成されているのですが、Unityの場合、Activityを継承してUnityに必要な処理を追加した「UnityPlayerActivity」がアプリの起動と同時に呼び出されます。
このUnityPlayerActivityを、独自Activityに差し替え、そこにGoogle Sign Inを実装することでUnityでのGoogle Sign Inを実現します。
独自Activityの実装
という訳で早速、UnityPlayerActivityを継承した独自Activityを作ってGoogle Sign Inを実装していきます。
コードの詳細は全部コメントに書いたのでそちらを参照してください。
コードはJavaで書いてください。Kotlinだと動きません。
package jp.toconakis.catcrane;
import com.unity3d.player.UnityPlayerActivity;
import android.os.Bundle;
import android.util.Log;
// For Google SignIn
import android.content.Intent;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.Task;
import com.unity3d.player.UnityPlayer;
public class MyActivity extends UnityPlayerActivity {
final int RC_SIGN_IN = 999;
GoogleSignInClient googleSignInClient;
// Unityから呼び出す
public void signInWithGoogle() {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
// google-services.jsonの client > oauth_client > client_id の値をコピペする
.requestIdToken("1234567-nejdtuaef7aq6pb83e3i90g3vc87fnv4.apps.googleusercontent.com")
.requestEmail()
.build();
googleSignInClient = GoogleSignIn.getClient(this, gso);
Intent i = googleSignInClient.getSignInIntent();
startActivityForResult(i, RC_SIGN_IN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
if (data != null) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
GoogleSignInAccount account = task.getResult(ApiException.class);
if (account.getIdToken() != null) {
// Unity側のTestController.GetIDTokenFromAndroidを呼んで、IDTokenを渡す
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数です。
UnityPlayer.UnitySendMessage("TestController" , "GetIDTokenFromAndroid" , account.getIdToken());
} else {
// Unity側のTestController.GetIDTokenFailedFromAndroidを呼んで、失敗を知らせる
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数です。
UnityPlayer.UnitySendMessage("TestController" , "GetIDTokenFailedFromAndroid" , "");
}
} catch (ApiException e) {
// Unity側のTestController.GetIDTokenFailedFromAndroidを呼んで、失敗を知らせる
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数です。
UnityPlayer.UnitySendMessage("TestController" , "GetIDTokenFailedFromAndroid" , "" + e.getStatusCode());
}
} else {
// Unity側のTestController.GetIDTokenFailedFromAndroidを呼んで、失敗を知らせる
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数です。
UnityPlayer.UnitySendMessage("TestController" , "GetIDTokenFailedFromAndroid" , "");
}
}
}
protected void onCreate(Bundle savedInstanceState) {
// UnityPlayerActivity.onCreate() を呼び出す
super.onCreate(savedInstanceState);
}
public void onBackPressed()
{
// UnityPlayerActivity.onBackPressed() を呼び出す代わりに、Back ボタンイベントを無視する
// super.onBackPressed();
}
}
この独自Activityを、以下の場所に保存します。
赤字の部分は自分のpackage名に合わせて変更してください。
Assets/Plugins/Android/jp/toconakis/catcrane/MyActivity.java
各種設定ファイルの修正
次に、独自Activityを起動時に呼び出すよう、起動情報を定義してあるAndroidManifest.xmlの書き換え、と、Google Sign InのライブラリーをAndroid側にインストールするため、Androidのライブラリーを管理しているgradleファイルの書き換えを行います。
(必要に応じて、gradle propertiesの書き換えも)
ただ、上記の設定ファイルはデフォルトでは表示されないのでUnityを開き
File > Build Settings > Player Settings… でProject Settingsウインドウを開き
左のリストからPlayerを選んだら、Publishing Settings欄にある以下3つの項目にチェックを入れて必要な設定ファイルを追加します。
- Custom Main Manifest
- Custom Main Gradle Template
- Custom Gradle Properties Template
AndroidManifest.xmlの修正
Assets/Plugins/Android にAndroidManifest.xmlが追加されるので、独自Activityが起動時に呼び出されるよう、activityタグの部分を修正します。(8行目あたり)
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools">
<application>
<!-- com.unity3d.player.UnityPlayerActivity から jp.toconakis.catcrane.MyActivityに書き換える -->
<activity android:name="jp.toconakis.catcrane.MyActivity"
android:theme="@style/UnityThemeSelector">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
</manifest>
mainTemplate.gradleの修正
同様に、Assets/Plugins/Android にmainTemplate.gradleが追加されているので、Google Sign Inライブラリーが追加されるように、dependenciesの欄に追記します。
apply plugin: 'com.android.library'
**APPLY_PLUGINS**
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Google Sign Inライブラリー
implementation 'com.google.android.gms:play-services-auth:20.6.0'
**DEPS**}
android {
...
gradleTemplate.propertiesの修正
同様に、Assets/Plugins/Android にgradleTemplate.propertiesが追加されているので、2つの設定を追記します。
この設定は、他のプロジェクトでは自動で追加されていたのですが、今回記事のために作業してみたプロジェクトでは自動で追加されていませんでした。
どうしたら自動追加されるのか不明なので、もし既に追加されていた場合は無視してください。
- android.useAndroidX=true
- android.enableJetifier=true
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
org.gradle.parallel=true
android.enableR8=**MINIFY_WITH_R_EIGHT**
unityStreamingAssets=**STREAMING_ASSETS**
**ADDITIONAL_PROPERTIES**
# 2つのプロパティを追加
android.useAndroidX=true
android.enableJetifier=true
以上でAndroidネイティブ側の実装は完了なので、試しに実機でAndroidビルドを試して見てください。
問題なく起動するはずです。
Unity用FirebaseAuthと連携
次に、Unity側にFirebaseAuthパッケージを導入して、Androidネイティブで成功したGoogle Sign Inの結果をFirebase Authに紐付ける処理を実装していきます。
FirebaseAuthパッケージの導入
以下のリンクから最新版のFirebase Unity SDKをダウンロードします。
今回は、2023/7/20時点で最新のバージョン11.2.0を導入します。
既に他のFirebaseパッケージを導入済の場合は同じバージョンのFirebaseAuthパッケージを入れるか、最新のパッケージを全て入れ直してください。
そうしないとエラーで動きません。
ダウンロードしたら解凍して、FirebaseAuth.unitypackage をimportします。
AndroidのMinimum API Levelが低すぎるとこのあとビルドが通らなくなるので、File > Build Settings > Player Settings… でProject Settingsウインドウを開き、左のリストからPlayerを選んだら、Other Settings欄にあるMinimum API Levelを新しめの値に変えておいてください。
デフォルト値のAndroid5.1 Lolipopだとビルドが通りませんでした。
C#の実装
Androidネイティブの独自Activityで、UnityのTestControllerのメソッドを呼び出すよう実装していたので、クラス名はTestControllerとします。
TestControllerに定義したSignInWithGoogleメソッドをButtonなどに当てて呼び出すと、Android側のGoogle Sign Inが実行され、結果がUnity側のメソッドを通して返ってきます。
詳細はコードのコメントを参照してください。
using UnityEngine;
using Firebase.Auth;
using Firebase.Extensions;
public class TestController : MonoBehaviour
{
private FirebaseAuth auth;
Firebase.DependencyStatus dependencyStatus = Firebase.DependencyStatus.UnavailableOther;
private void Start()
{
// FirebaseAuthの初期化
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available)
{
auth = FirebaseAuth.DefaultInstance;
}
else
{
Debug.Log($"error: {dependencyStatus}");
}
});
}
// Androidに定義してあるメソッドを呼ぶ
public void SignInWithGoogle()
{
// AndroidのActivityを取得する
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
// Androidの独自Activityに定義しているメソッドを呼び出す
activity.Call("signInWithGoogle");
}
// Androidから呼び出される。Google Sign Inで取得したIDTokenを受け取る
public void GetIDTokenFromAndroid(string idToken)
{
Credential credencial = GoogleAuthProvider.GetCredential(idToken, null);
// GoogleアカウントをAuthに紐付ける
auth.SignInWithCredentialAsync(credencial).ContinueWith(authTask =>
{
if (authTask.IsCanceled)
{
Debug.Log($"LinkWithCredentialAsync Cancelled");
}
else if (authTask.IsFaulted)
{
Debug.Log($"LinkWithCredentialAsync Faulted");
}
else
{
Debug.Log($"LinkWithCredentialAsync Complete!");
}
});
}
// Androidから呼び出される。AndroidでGoogle Sign Inに失敗した事を教えてもらう
public void GetIDTokenFailedFromAndroid(string errorCode)
{
Debug.Log($"GetIDTokenFromAndroid Failed!! {errorCode}");
}
}
うまく処理が完了すると、FirebaseAuthとの連携が完了し、FirebaseのAuthenticationにGoogle Sign Inしたユーザーの情報が登録されます。