Google Play Games サービスを使って、Firebase で構築した C ++ の Android ゲームへログインすることができます。Firebase で Google Play Games サービスのログインを使用するには、最初に Google Play Games でプレーヤーをログインさせ、OAuth 2.0 認証コードをリクエストします。次に、認証コードを PlayGamesAuthProvider
に渡して Firebase 認証情報を生成します。この認証情報を Firebase での認証に使用できます。
始める前に
Firebase Authentication を使用するには、次の作業が必要です。
C++ プロジェクトを登録して Firebase を使用するように構成します。
C++ プロジェクトですでに Firebase を使用している場合、この登録と構成はすでに行われています。
Firebase C++ SDK を C++ プロジェクトに追加します。
Firebase を C++ プロジェクトに追加するには、Firebase コンソールと開いている C++ プロジェクトの両方でこのタスクを行う必要があります(コンソールから Firebase 構成ファイルをダウンロードして C++ プロジェクトに移動するなど)。
Firebase プロジェクトを設定する
まだ設定していない場合は、Firebase コンソールの [設定] ページでゲームの SHA-1 フィンガープリントを設定します。
次のように gradle
signingReport
コマンドを使用して、署名証明書の SHA ハッシュを取得できます。./gradlew signingReport
Google Play Games をログイン プロバイダとして有効にします。
Firebase コンソールで、[Authentication] セクションを開きます。
プロジェクトのウェブサーバーのクライアント ID とクライアント シークレットを生成して取得します。
[Sign-in method] タブで、[Google] ログイン プロバイダを有効にします。
ウェブサーバーのクライアント ID とシークレットを Google ログイン プロバイダからコピーします。
[Sign-in method] タブで [Play Games] ログイン プロバイダを有効にし、前のステップで取得したプロジェクトのウェブサーバーのクライアント ID とクライアント シークレットを指定します。
Firebase アプリの情報を使用して Play Games services を構成する
Google Play Console で、Google Play アプリを開くか、アプリを作成します。
[Grow] セクションで、Play Games services > [設定と管理] > [設定] をクリックします。
[はい、ゲームで Google API をすでに使用しています] をクリックし、リストから Firebase プロジェクトを選択して [使用する] をクリックします。
Play Games services の設定ページで、[認証情報を追加] をクリックします。
- [ゲームサーバー] のタイプを選択します。
- [OAuth クライアント] フィールドで、プロジェクトのウェブ クライアント ID を選択します。Play Games ログインを有効にしたときに指定したクライアント ID と同じ ID を選択してください。
- 変更を保存します。
引き続き Play Games services の設定ページで、もう一度 [認証情報を追加] をクリックします。
- [Android] のタイプを選択します。
- [OAuth クライアント] フィールドで、プロジェクトの Android クライアント ID を選択します(目的の Android クライアント ID が表示されない場合は、Firebase コンソールでゲームの SHA-1 フィンガープリントが設定されていることを確認してください)。
- 変更を保存します。
[テスター] ページで、Play Store にゲームをリリースする前に、ゲームにログインできるようにするユーザーのメールアドレスを追加します。
Play ゲームのログインをゲームに統合する
プレーヤーをゲームにログインさせる前に、Google Play Games のログインを統合する必要があります。
C++ Android プロジェクトに Play ゲームのログインのサポートを追加する最も簡単な方法として、Google Sign-in C++ SDK を使用することが推奨されています。
Google Sign-in C++ SDK を使用して Play ゲームのログインをゲームに追加するには、次の操作を行います。
Google Sign-in Unity plugin リポジトリをダウンロードするか、そのクローンを作成します。このリポジトリには C++ SDK も含まれています。
staging/native/
ディレクトリに含まれるプロジェクトを、Android Studio またはgradlew build
を使用してビルドします。ビルドすると、その出力が
google-signin-cpp
という名前のディレクトリにコピーされます。ゲームのネイティブ コードの make ファイルに Google Sign-in C++ SDK をインクルードします。
CMake
以下は、最上位の
CMakeLists.txt
ファイルです。set(GSI_PACKAGE_DIR "/path/to/google-signin-cpp")
add_library(lib-google-signin-cpp STATIC IMPORTED) set_target_properties(lib-google-signin-cpp PROPERTIES IMPORTED_LOCATION ${GSI_PACKAGE_DIR}/lib/${ANDROID_ABI}/libgoogle-signin-cpp.a )
...
target_link_libraries( ... lib-google-signin-cpp)ndk-build
以下は、
Android.mk
ファイルです。include $(CLEAR_VARS) LOCAL_MODULE := google-signin-cpp GSI_SDK_DIR := /path/to/google-signin-cpp LOCAL_SRC_FILES := $(GSI_SDK_DIR)/lib/$(TARGET_ARCH_ABI)/libgoogle-signin-cpp.a LOCAL_EXPORT_C_INCLUDES := $(GSI_SDK_DIR)/include include $(PREBUILT_STATIC_LIBRARY)
次に、Java ヘルパー コンポーネントをインクルードします。C++ SDK はこのコンポーネントを必要とします。
これを行うには、プロジェクト レベルの
build.gradle
ファイルで、SDK ビルド出力ディレクトリをローカル リポジトリとして追加します。allprojects { repositories { // ... flatDir { dirs 'path/to/google-signin-cpp' } } }
さらに、モジュール レベルの
build.gradle
ファイルで、ヘルパー コンポーネントを依存関係として宣言します。dependencies { implementation 'com.google.android.gms:play-services-auth:21.2.0' // Depend on the AAR built with the Google Sign-in SDK in order to add // the Java helper classes, which are used by the C++ library. compile(name:'google-signin-cpp-release', ext:'aar') }
次に、ゲーム内で Play ゲームログインを使用してサーバー認証コードを取得できるように
GoogleSignIn
オブジェクトを構成します。#include "google_signin.h" #include "future.h" using namespace google::signin; // ... GoogleSignIn::Configuration config = {}; config.web_client_id = "YOUR_WEB_CLIENT_ID_HERE"; config.request_id_token = false; config.use_game_signin = true; config.request_auth_code = true; GoogleSignIn gsi = GoogleSignIn(GetActivity(), GetJavaVM()); gsi.Configure(config);
最後に、
SignIn()
を呼び出して、Play ゲームにプレーヤーをログインさせます。Future<GoogleSignIn::SignInResult> &future = gsi.SignIn();
SignIn()
によって返された Future が解決すると、結果からサーバー認証コードを取得できます。if (!future.Pending()) { const GoogleSignIn::StatusCode status = static_cast<GoogleSignIn::StatusCode>(future.Status()); if (status == GoogleSignIn::kStatusCodeSuccess) { // Player successfully signed in to Google Play! Get auth code to // pass to Firebase const GoogleSignIn::SignInResult result = static_cast<GoogleSignIn::SignInResult>(future.Result()); const char* server_auth_code = result.User.GetServerAuthCode(); } }
Firebase で認証する
プレーヤーが Play ゲームにログインした後、認証コードを使用して Firebase で認証することができます。
プレーヤーが Play ゲームを使用して正常にログインした後、プレーヤーのアカウントの認証コードを取得します。
その後、Play ゲームサービスの認証コードを Firebase 認証情報と交換し、Firebase 認証情報を使用してプレーヤーを認証します。
firebase::auth::Credential credential = firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code); firebase::Future<firebase::auth::AuthResult> result = auth->SignInAndRetrieveDataWithCredential(credential);
定期的に(たとえば、毎秒 30 回または 60 回)実行される更新ループがプログラムに含まれている場合、
Auth::SignInAndRetrieveDataWithCredentialLastResult
を使用して、更新されるたびに 1 回結果を確認できます。firebase::Future<firebase::auth::AuthResult> result = auth->SignInAndRetrieveDataWithCredentialLastResult(); if (result.status() == firebase::kFutureStatusComplete) { if (result.error() == firebase::auth::kAuthErrorNone) { firebase::auth::AuthResult auth_result = *result.result(); printf("Sign in succeeded for `%s`\n", auth_result.user.display_name().c_str()); } else { printf("Sign in failed with error '%s'\n", result.error_message()); } }
プログラムがイベント ドリブンの場合は、Future にコールバックを登録することをおすすめします。
Future にコールバックを登録する
プログラムの中には、毎秒 30 回または 60 回呼び出されるUpdate
関数が含まれるものがあります。たとえば、多くのゲームでこのモデルが使用されています。このようなプログラムでは、LastResult
関数を呼び出して、非同期呼び出しをポーリングできます。ただし、プログラムがイベント ドリブンの場合は、コールバック関数を登録することをおすすめします。コールバック関数は、Future の完了時に呼び出されます。
void OnCreateCallback(const firebase::Future<firebase::auth::User*>& result, void* user_data) { // The callback is called when the Future enters the `complete` state. assert(result.status() == firebase::kFutureStatusComplete); // Use `user_data` to pass-in program context, if you like. MyProgramContext* program_context = static_cast<MyProgramContext*>(user_data); // Important to handle both success and failure situations. if (result.error() == firebase::auth::kAuthErrorNone) { firebase::auth::User* user = *result.result(); printf("Create user succeeded for email %s\n", user->email().c_str()); // Perform other actions on User, if you like. firebase::auth::User::UserProfile profile; profile.display_name = program_context->display_name; user->UpdateUserProfile(profile); } else { printf("Created user failed with error '%s'\n", result.error_message()); } } void CreateUser(firebase::auth::Auth* auth) { // Callbacks work the same for any firebase::Future. firebase::Future<firebase::auth::AuthResult> result = auth->CreateUserWithEmailAndPasswordLastResult(); // `&my_program_context` is passed verbatim to OnCreateCallback(). result.OnCompletion(OnCreateCallback, &my_program_context); }コールバック関数にラムダを使用することもできます。
void CreateUserUsingLambda(firebase::auth::Auth* auth) { // Callbacks work the same for any firebase::Future. firebase::Future<firebase::auth::AuthResult> result = auth->CreateUserWithEmailAndPasswordLastResult(); // The lambda has the same signature as the callback function. result.OnCompletion( [](const firebase::Future<firebase::auth::User*>& result, void* user_data) { // `user_data` is the same as &my_program_context, below. // Note that we can't capture this value in the [] because std::function // is not supported by our minimum compiler spec (which is pre C++11). MyProgramContext* program_context = static_cast<MyProgramContext*>(user_data); // Process create user result... (void)program_context; }, &my_program_context); }
次のステップ
ユーザーが初めてログインすると新しいユーザー アカウントが作成され、ユーザーの Play ゲーム ID にリンクされます。この新しいアカウントは Firebase プロジェクトの一部として保存され、プロジェクト内のすべてのアプリでユーザーを特定するために使用できます。
ゲームでは、firebase::auth::User
オブジェクトからユーザーの Firebase UID を取得できます。
firebase::auth::User user = auth->current_user();
if (user.is_valid()) {
std::string playerName = user.displayName();
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use firebase::auth::User::Token() instead.
std::string uid = user.uid();
}
Firebase Realtime Database と Cloud Storage のセキュリティ ルールでは、ログイン済みユーザーの一意のユーザー ID を auth
変数から取得し、それを使用して、ユーザーがアクセス可能なデータを制御できます。
ユーザーの Play Games のプレーヤー情報を取得したり、Play Games サービスにアクセスしたりするには、Google Play Games サービス C++ SDK で提供されている API を使用します。
ユーザーのログアウトを行うには、SignOut()
を呼び出します。
auth->SignOut();