المصادقة باستخدام خدمات ألعاب Google Play مع C ++

يمكنك استخدام خدمات ألعاب Google Play لتسجيل دخول اللاعبين إلى لعبة Android مبنية على Firebase ومكتوبة بلغة C ++. لاستخدام خدمات ألعاب Google Play ، قم بتسجيل الدخول باستخدام Firebase ، قم أولاً بتسجيل الدخول إلى المشغل باستخدام ألعاب Google Play ، واطلب رمز مصادقة OAuth 2.0 عند القيام بذلك. بعد ذلك ، قم بتمرير رمز المصادقة إلى PlayGamesAuthProvider لإنشاء بيانات اعتماد Firebase ، والتي يمكنك استخدامها للمصادقة مع Firebase.

قبل ان تبدأ

قبل أن تتمكن من استخدام مصادقة Firebase ، تحتاج إلى:

  • سجل مشروع C ++ الخاص بك وقم بتكوينه لاستخدام Firebase.

    إذا كان مشروع C ++ الخاص بك يستخدم Firebase بالفعل ، فسيتم تسجيله وتهيئته بالفعل لـ Firebase.

  • أضف Firebase C ++ SDK إلى مشروع C ++ الخاص بك.

لاحظ أن إضافة Firebase إلى مشروع C ++ الخاص بك يتضمن مهامًا في كل من وحدة تحكم Firebase وفي مشروع C ++ المفتوح (على سبيل المثال ، يمكنك تنزيل ملفات تهيئة Firebase من وحدة التحكم ، ثم نقلها إلى مشروع C ++ الخاص بك).

قم بإعداد مشروع Firebase الخاص بك

  1. إذا لم تكن قد قمت بذلك بالفعل ، فقم بتعيين بصمة إصبع SHA-1 للعبتك في صفحة الإعدادات بوحدة تحكم Firebase.

    يمكنك الحصول على تجزئة SHA لشهادة التوقيع الخاصة بك باستخدام أمر signingReport :

    ./gradlew signingReport

  2. قم بتمكين ألعاب Google Play كموفر لتسجيل الدخول:

    1. ابحث عن معرّف عميل خادم الويب الخاص بمشروعك وسر العميل. يحدد معرّف عميل خادم الويب مشروع Firebase لخوادم مصادقة Google Play.

      للعثور على هذه القيم:

      1. افتح مشروع Firebase في صفحة بيانات اعتماد وحدة تحكم Google APIs .
      2. في قسم معرّفات عميل OAuth 2.0 ، افتح صفحة تفاصيل عميل الويب (الذي تم إنشاؤه تلقائيًا بواسطة خدمة Google) . تسرد هذه الصفحة معرف عميل خادم الويب والسر.
    2. بعد ذلك ، في وحدة تحكم Firebase ، افتح قسم المصادقة .

    3. في علامة تبويب طريقة تسجيل الدخول ، قم بتمكين موفر تسجيل الدخول إلى ألعاب Play . ستحتاج إلى تحديد معرف عميل خادم الويب الخاص بمشروعك وسر العميل ، والذي حصلت عليه من وحدة تحكم واجهات برمجة التطبيقات.

هيئ خدمات ألعاب Play باستخدام معلومات تطبيق Firebase

  1. في Google Play Console ، افتح تطبيق Google Play أو أنشئ واحدًا.

  2. في قسم Grow ، انقر فوق خدمات ألعاب Play> الإعداد والإدارة> التكوين .

  3. انقر فوق نعم ، لعبتي تستخدم Google APIs بالفعل ، وحدد مشروع Firebase الخاص بك من القائمة ، ثم انقر فوق استخدام .

  4. في صفحة تكوين خدمات ألعاب Play ، انقر على إضافة بيانات الاعتماد .

    1. حدد نوع خادم اللعبة .
    2. في حقل عميل OAuth ، حدد معرّف عميل الويب لمشروعك. تأكد من أن هذا هو نفس معرّف العميل الذي حددته عند تمكين تسجيل الدخول إلى ألعاب Play.
    3. احفظ التغييرات.
  5. لا يزال في صفحة تكوين خدمات ألعاب Play ، انقر فوق إضافة بيانات الاعتماد مرة أخرى.

    1. حدد نوع Android .
    2. في حقل عميل OAuth ، حدد معرّف عميل Android الخاص بمشروعك. (إذا كنت لا ترى معرّف عميل Android ، فتأكد من تعيين بصمة SHA-1 للعبة في وحدة تحكم Firebase.)
    3. احفظ التغييرات.
  6. في صفحة المختبرين ، أضف عناوين البريد الإلكتروني لأي مستخدم يحتاج إلى أن يكون قادرًا على تسجيل الدخول إلى لعبتك قبل إصدارها في متجر Play.

ادمج تسجيل الدخول إلى "ألعاب Play" في لعبتك

قبل أن تتمكن من تسجيل دخول اللاعبين إلى لعبتك ، يجب عليك دمج تسجيل الدخول إلى "ألعاب Google Play".

الطريقة الأسهل والموصى بها لإضافة دعم تسجيل الدخول إلى ألعاب Play إلى مشروع C ++ Android هي استخدام Google Sign-in C ++ SDK .

لإضافة "ألعاب Play" ، قم بتسجيل الدخول إلى لعبتك باستخدام Google Sign-in C ++ SDK ، قم بما يلي:

  1. قم بنسخ أو تنزيل مستودع البرنامج المساعد لتسجيل الدخول إلى Google ، والذي يحتوي أيضًا على C ++ SDK.

  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- بناء

    في ملف 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. بعد ذلك ، قم بتضمين مكون Java helper ، المطلوب بواسطة 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:20.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')
    }
    
  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 Games:

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

    عندما يحل المستقبل الذي تم إرجاعه بواسطة 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::User*> result =
        auth->SignInWithCredential(credential);
    
  3. إذا كان برنامجك يحتوي على حلقة تحديث تعمل بانتظام (لنقل 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());
      }
    }

    أو ، إذا كان برنامجك مدفوعًا بالأحداث ، فقد تفضل تسجيل رد اتصال على المستقبل .

تسجيل معاودة الاتصال على المستقبل

تحتوي بعض البرامج على وظائف Update تسمى 30 أو 60 مرة في الثانية. على سبيل المثال ، تتبع العديد من الألعاب هذا النموذج. يمكن لهذه البرامج استدعاء وظائف LastResult المكالمات غير المتزامنة. ومع ذلك ، إذا كان برنامجك مدفوعًا بالأحداث ، فقد تفضل تسجيل وظائف رد الاتصال. يتم استدعاء وظيفة رد الاتصال عند الانتهاء من المستقبل.
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);
}
يمكن أن تكون وظيفة رد الاتصال أيضًا lambda ، إذا كنت تفضل ذلك.
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 الخاص به. يتم تخزين هذا الحساب الجديد كجزء من مشروع Firebase الخاص بك ، ويمكن استخدامه لتحديد مستخدم عبر كل تطبيق في مشروعك.

في لعبتك ، يمكنك الحصول على معرف المستخدم Firebase UID من كائن firebase::auth::User :

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();
}

في قاعدة بيانات Firebase Realtime وقواعد أمان التخزين السحابي ، يمكنك الحصول على معرف المستخدم الفريد للمستخدم الذي قام بتسجيل الدخول من متغير auth ، واستخدامه للتحكم في البيانات التي يمكن للمستخدم الوصول إليها.

للحصول على معلومات لاعب Play Games الخاص بالمستخدم أو للوصول إلى خدمات ألعاب Play ، استخدم واجهات برمجة التطبيقات التي توفرها خدمات ألعاب Google Play C ++ SDK .

لتسجيل خروج مستخدم ، اتصل SignOut() :

auth->SignOut();