با استفاده از خدمات بازی های Google Play با C++ احراز هویت

می‌توانید از سرویس‌های «بازی‌های Google Play» برای ورود بازیکنان به یک بازی Android که بر روی Firebase ساخته شده و به زبان C++ نوشته شده است، استفاده کنید. برای استفاده از ورود به سیستم سرویس‌های بازی‌های Google Play با Firebase، ابتدا با بازی‌های Google Play وارد بازیکن شوید و در صورت انجام این کار، کد تأیید OAuth 2.0 را درخواست کنید. سپس، کد احراز هویت را به PlayGamesAuthProvider ارسال کنید تا یک اعتبار Firebase ایجاد کند، که می توانید از آن برای احراز هویت با Firebase استفاده کنید.

قبل از اینکه شروع کنی

قبل از اینکه بتوانید از Firebase Authentication استفاده کنید، باید:

  • پروژه ++C خود را ثبت کرده و آن را برای استفاده از Firebase پیکربندی کنید.

    اگر پروژه ++C شما قبلاً از Firebase استفاده می‌کند، پس قبلاً برای Firebase ثبت و پیکربندی شده است.

  • Firebase C++ SDK را به پروژه C++ خود اضافه کنید.

توجه داشته باشید که افزودن Firebase به پروژه C++ شما شامل وظایفی هم در کنسول Firebase و هم در پروژه C++ باز شما می شود (به عنوان مثال، فایل های پیکربندی Firebase را از کنسول دانلود می کنید، سپس آنها را به پروژه C++ خود منتقل می کنید).

پروژه Firebase خود را راه اندازی کنید

  1. اگر قبلاً این کار را نکرده‌اید، اثر انگشت SHA-1 بازی خود را در صفحه تنظیمات کنسول Firebase تنظیم کنید.

    می توانید هش SHA گواهی امضای خود را با دستور gradle signingReport دریافت کنید:

    ./gradlew signingReport

  2. فعال کردن بازی‌های Google Play به عنوان ارائه‌دهنده ورود به سیستم:

    1. در کنسول Firebase، بخش Authentication را باز کنید.

    2. شناسه سرویس گیرنده وب سرور و رمز سرویس گیرنده پروژه خود را ایجاد و به دست آورید:

      1. در برگه روش ورود به سیستم ، ارائه دهنده ورود به سیستم Google را فعال کنید.

      2. شناسه سرویس گیرنده وب سرور و راز را از ارائه دهنده ورود به سیستم Google کپی کنید.

    3. در برگه روش ورود ، ارائه‌دهنده ورود به بازی‌های Play را فعال کنید و شناسه سرویس گیرنده وب سرور پروژه خود و راز سرویس گیرنده را که در مرحله آخر دریافت کردید، مشخص کنید.

سرویس‌های «بازی‌های Play» را با اطلاعات برنامه Firebase خود پیکربندی کنید

  1. در کنسول Google Play ، برنامه Google Play خود را باز کنید یا یکی ایجاد کنید.

  2. در بخش رشد ، روی خدمات بازی‌های Play > راه‌اندازی و مدیریت > پیکربندی کلیک کنید.

  3. روی بله، بازی من قبلاً از Google API استفاده می‌کند ، پروژه Firebase خود را از لیست انتخاب کنید و سپس روی استفاده کلیک کنید.

  4. در صفحه پیکربندی خدمات بازی‌های Play، روی افزودن اعتبارنامه کلیک کنید.

    1. نوع سرور بازی را انتخاب کنید.
    2. در قسمت سرویس گیرنده OAuth ، شناسه مشتری وب پروژه خود را انتخاب کنید. مطمئن شوید که این همان شناسه مشتری است که هنگام فعال کردن ورود به سیستم بازی‌های Play مشخص کرده‌اید.
    3. تغییرات خود را ذخیره کنید
  5. هنوز در صفحه پیکربندی خدمات بازی‌های Play، دوباره روی افزودن اعتبارنامه کلیک کنید.

    1. نوع اندروید را انتخاب کنید.
    2. در قسمت سرویس گیرنده OAuth ، شناسه مشتری Android پروژه خود را انتخاب کنید. (اگر ID کلاینت اندروید خود را نمی بینید، مطمئن شوید که اثر انگشت SHA-1 بازی خود را در کنسول Firebase تنظیم کرده اید.)
    3. تغییرات خود را ذخیره کنید
  6. در صفحه آزمایش‌کنندگان ، آدرس‌های ایمیل کاربرانی را که نیاز دارند قبل از انتشار آن در فروشگاه Play، بتوانند وارد بازی خود شوند، اضافه کنید.

ورود به سیستم بازی‌های Play را در بازی خود ادغام کنید

قبل از اینکه بتوانید بازیکنان را وارد بازی خود کنید، باید ورود به سیستم بازی های Google Play را ادغام کنید.

ساده‌ترین و توصیه‌شده برای افزودن پشتیبانی از ورود به بازی‌های Play به یک پروژه Android C++، استفاده از Google Sign-in C++ SDK است.

برای افزودن ورود به بازی‌های Play به بازی خود با استفاده از Google Sign-in C++ SDK، موارد زیر را انجام دهید:

  1. مخزن افزونه Google Sign-in Unity را که حاوی SDK ++C نیز می باشد، کلون کنید یا دانلود کنید.

  2. پروژه موجود در دایرکتوری staging/native/ با استفاده از Android Studio یا gradlew build بسازید.

    این سازه خروجی خود را در دایرکتوری به نام google-signin-cpp کپی می کند.

  3. 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)
    

  4. در مرحله بعد، مولفه کمکی جاوا را که توسط 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.0.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. سپس، در بازی خود، یک شی GoogleSignIn را برای استفاده از ورود به سیستم بازی‌های Play و برای بازیابی کد اعتبار سرور پیکربندی کنید:

    #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() تماس بگیرید تا بازیکن وارد بازی‌های Play شود:

    Future<GoogleSignIn::SignInResult> &future = gsi.SignIn();
    

    هنگامی که Future برگردانده شده توسط SignIn() حل شد، می توانید کد اعتبار سرور را از نتیجه دریافت کنید:

    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 استفاده کنید.

  1. پس از اینکه بازیکن با استفاده از بازی‌های Play با موفقیت وارد سیستم شد، یک کد تأیید اعتبار برای حساب بازیکن دریافت کنید.

  2. سپس، کد احراز هویت از خدمات بازی‌های Play را با اعتبار Firebase مبادله کنید و از اعتبار Firebase برای احراز هویت بازیکن استفاده کنید:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  3. اگر برنامه شما دارای یک حلقه به روز رسانی است که به طور منظم اجرا می شود (مثلاً 30 یا 60 بار در ثانیه)، می توانید نتایج را یک بار در هر به روز رسانی با Auth::SignInAndRetrieveDataWithCredentialLastResult :

    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 ثبت کنید .

ثبت پاسخ تماس در آینده

برخی از برنامه ها دارای توابع Update هستند که 30 یا 60 بار در ثانیه فراخوانی می شوند. به عنوان مثال، بسیاری از بازی ها از این مدل پیروی می کنند. این برنامه ها می توانند توابع 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);
}
تابع callback نیز در صورت تمایل می تواند یک لامبدا باشد.
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 او مرتبط می‌شود. این حساب جدید به عنوان بخشی از پروژه Firebase شما ذخیره می‌شود و می‌تواند برای شناسایی کاربر در هر برنامه در پروژه شما استفاده شود.

در بازی خود می توانید UID Firebase کاربر را از firebase::auth::User object:

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، می‌توانید شناسه کاربری منحصر به فرد کاربر واردشده را از متغیر auth دریافت کنید و از آن برای کنترل داده‌هایی که کاربر می‌تواند به آن دسترسی داشته باشد استفاده کنید.

برای دریافت اطلاعات پخش‌کننده «بازی‌های Play» کاربر یا دسترسی به خدمات «بازی‌های Play»، از API‌های ارائه‌شده توسط سرویس‌های «بازی‌های Google Play» C++ SDK استفاده کنید.

برای خروج از سیستم کاربر، SignOut() را فراخوانی کنید:

auth->SignOut();