Google は、黒人コミュニティのための人種的公平の促進に取り組んでいます。詳細をご覧ください。

C ++でGooglePlayゲームサービスを使用して認証する

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Google Playゲームサービスを使用して、Firebase上に構築されC ++で記述されたAndroidゲームにプレーヤーをログインさせることができます。 FirebaseでGooglePlayゲームサービスのログインを使用するには、まずGoogle Playゲームでプレーヤーにログインし、そのときにOAuth2.0認証コードをリクエストします。次に、認証コードをPlayGamesAuthProviderに渡して、Firebaseでの認証に使用できるFirebaseクレデンシャルを生成します。

あなたが始める前に

Firebase認証を使用する前に、次のことを行う必要があります。

  • C ++プロジェクトを登録し、Firebaseを使用するように構成します。

    C ++プロジェクトがすでにFirebaseを使用している場合は、Firebase用に登録および構成されています。

  • Firebase C ++ SDKをC ++プロジェクトに追加します。

FirebaseをC ++プロジェクトに追加するには、 Firebaseコンソールと開いているC ++プロジェクトの両方でタスクが必要になることに注意してください(たとえば、コンソールからFirebase構成ファイルをダウンロードしてからC ++プロジェクトに移動します)。

Firebaseプロジェクトを設定する

  1. まだ設定していない場合は、Firebaseコンソールの[設定]ページでゲームのSHA-1フィンガープリントを設定します。

    signingReportコマンドを使用して署名証明書のSHAハッシュを取得できます:

    ./gradlew signingReport

  2. サインインプロバイダーとしてGooglePlayゲームを有効にします。

    1. プロジェクトのWebサーバークライアントIDとクライアントシークレットを見つけます。ウェブサーバーのクライアントIDは、FirebaseプロジェクトをGooglePlay認証サーバーに対して識別します。

      これらの値を見つけるには:

      1. GoogleAPIコンソールの認証情報ページでFirebaseプロジェクトを開きます。
      2. [ OAuth 2.0クライアントID ]セクションで、 Webクライアント(Googleサービスによって自動作成された)の詳細ページを開きます。このページには、WebサーバーのクライアントIDとシークレットが一覧表示されます。
    2. 次に、 Firebaseコンソールで[認証]セクションを開きます。

    3. [サインイン方法]タブで、 Playゲームのサインインプロバイダーを有効にします。 APIコンソールから取得したプロジェクトのWebサーバークライアントIDとクライアントシークレットを指定する必要があります。

Firebaseアプリ情報を使用してPlayゲームサービスを構成する

  1. Google Play Consoleで、GooglePlayアプリを開くか作成します。

  2. [成長]セクションで、[ゲームサービスのプレイ]> [セットアップと管理]> [構成]をクリックします。

  3. [はい、私のゲームはすでにGoogle APIを使用しています]をクリックし、リストからFirebaseプロジェクトを選択して、[使用]をクリックします。

  4. Play Gamesサービスの構成ページで、[資格情報の追加]をクリックします。

    1. ゲームサーバーの種類を選択します。
    2. [ OAuthクライアント]フィールドで、プロジェクトのWebクライアントIDを選択します。これは、Playゲームのログインを有効にしたときに指定したクライアントIDと同じであることを確認してください。
    3. 変更を保存します。
  5. 引き続きPlayGamesサービスの構成ページで、[資格情報の追加]をもう一度クリックします。

    1. Androidの種類を選択します。
    2. [ OAuthクライアント]フィールドで、プロジェクトのAndroidクライアントIDを選択します。 (AndroidクライアントIDが表示されない場合は、FirebaseコンソールでゲームのSHA-1フィンガープリントを設定してください。)
    3. 変更を保存します。
  6. [テスター]ページで、Playストアでゲームをリリースする前に、ゲームにサインインできるようにする必要があるユーザーのメールアドレスを追加します。

Playゲームのサインインをゲームに統合する

プレーヤーをゲームにサインインする前に、GooglePlayゲームのサインインを統合する必要があります。

PlayゲームのサインインのサポートをC ++ Androidプロジェクトに追加する最も簡単で推奨される方法は、 GoogleサインインC ++ SDKを使用することです。

GoogleサインインC ++ SDKを使用してPlayゲームのサインインをゲームに追加するには、次の手順を実行します。

  1. GoogleサインインUnityプラグインリポジトリを複製またはダウンロードします。このリポジトリにはC ++ SDKも含まれています。

  2. AndroidStudioまたはgradlew buildを使用して、 staging/native/ディレクトリに含まれるプロジェクトをビルドします。

    ビルドは、その出力をgoogle-signin-cppという名前のディレクトリにコピーします。

  3. ゲームのネイティブコードmakeファイルにGoogleサインイン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)
    

  4. 次に、C ++ SDKに必要なJavaヘルパーコンポーネントを含めます。

    これを行うには、プロジェクトレベルのbuild.gradleファイルで、SDKビルド出力ディレクトリをローカルリポジトリとして追加します。

    allprojects {
        repositories {
            // ...
            flatDir {
                dirs 'path/to/google-signin-cpp'
            }
        }
    }
    

    また、モジュールレベルのbuild.gradleファイルで、ヘルパーコンポーネントを依存関係として宣言します。

    dependencies {
        implementation 'com.google.android.gms:play-services-auth:20.4.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')
    }
    
  5. 次に、ゲームで、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);
    
  6. 最後に、 SignIn()を呼び出して、プレーヤーをPlayGamesにサインインします。

    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で認証する

プレーヤーがPlayGamesでサインインした後、認証コードを使用してFirebaseで認証できます。

  1. プレーヤーがPlayGamesを使用して正常にサインインした後、プレーヤーのアカウントの認証コードを取得します。

  2. 次に、Playゲームサービスの認証コードをFirebaseクレデンシャルと交換し、Firebaseクレデンシャルを使用してプレーヤーを認証します。

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  3. プログラムに定期的に実行される更新ループがある場合(たとえば、1秒間に30回または60回)、 Auth::SignInWithCredentialLastResult

    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredentialLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        firebase::auth::User* user = *result.result();
        printf("Sign in succeeded for `%s`\n", user->display_name().c_str());
      } else {
        printf("Sign in failed with error '%s'\n", result.error_message());
      }
    }
    を使用して、更新ごとに1回結果を確認できます。

    または、プログラムがイベント駆動型の場合は、Futureにコールバックを登録することをお勧めします。

Futureにコールバックを登録する

一部のプログラムには、1秒間に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::User*> 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::User*> 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オブジェクトからユーザーのFirebaseUIDを取得できます。

firebase::auth::User* user = auth->current_user();
if (user != nullptr) {
  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();
}

FirebaseRealtimeデータベースとCloudStorageのセキュリティルールでは、ログインしたユーザーの一意のユーザーIDをauth変数から取得し、それを使用してユーザーがアクセスできるデータを制御できます。

ユーザーのPlayゲームプレーヤー情報を取得したり、Playゲームサービスにアクセスしたりするには、 GooglePlayゲームサービスC ++ SDKが提供するAPIを使用します。

ユーザーをサインアウトするには、 SignOut()を呼び出します。

auth->SignOut();