المصادقة باستخدام "خدمات ألعاب 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.

  • أضِف حزمة تطوير البرامج (SDK) Firebase C++ إلى مشروعك على C++.

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

إعداد مشروع Firebase

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

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

    ./gradlew signingReport

  2. تفعيل Google Play Games كموفِّر تسجيل دخول:

    1. في وحدة تحكُّم Firebase، افتح قسم Authentication

    2. إنشاء والحصول على معرّف عميل وعميل خادم الويب لمشروعك السر:

      1. ضمن علامة التبويب طريقة تسجيل الدخول، فعِّل تسجيل الدخول بـ Google المستخدم.

      2. نسخ معرِّف العميل وسر العميل لخادم الويب من عملية تسجيل الدخول على Google المستخدم.

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

إعداد Play Games services باستخدام معلومات تطبيقك على Firebase

  1. في جلسة المعمل، وحدة تحكُّم Google Play يُرْجَى فَتْحْ تَطْبِيقْ Google Play أَوْ إِنْشَاءْ تَطْبِيقْ.

  2. في قسم النمو، انقر على Play Games services > الإعداد الإدارة > الإعدادات.

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

  4. في صفحة إعداد "Play Games services"، انقر على إضافة بيانات اعتماد

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

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

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

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

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

لإضافة معلومات تسجيل الدخول إلى لعبتك من خلال "ألعاب Play" باستخدام حزمة تطوير البرامج (SDK) لـ C++ لتسجيل الدخول إلى Google، عليك اتّباع الخطوات التالية: التالي:

  1. استنسِخ مستودع مكوّنات Unity الإضافي لتسجيل الدخول إلى Google أو نزِّله. الذي يحتوي أيضًا على حزمة C++ SDK.

  2. يمكنك إنشاء المشروع المُضمّن في دليل staging/native/، إما باستخدام "استوديو Android" أو gradlew build.

    ينسخ الإصدار مخرجاته إلى دليل يُسمى google-signin-cpp.

  3. يُرجى تضمين حزمة تطوير البرامج (SDK) لـ C++ لتسجيل الدخول بحساب Google في ملف إنشاء الرمز الأصلي للعبتك:

    إنشاء فيديوهات Shorts

    في ملف 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. بعد ذلك، يمكنك تضمين مكوّن مساعد Java، وهو مطلوب بواسطة حزمة C++ SDK.

    لإجراء ذلك، أضِف إصدار حزمة تطوير البرامج (SDK) في ملف build.gradle على مستوى المشروع. دليل الإخراج كمستودع محلي:

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

    عند حلّ المستقبل الذي يعرضه 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());
      }
    }

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

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

تحتوي بعض البرامج على دوال 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::AuthResult> 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::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 للمستخدم من كائن firebase::auth::User:

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 في الوقت الفعلي" و"قواعد أمان Cloud Storage"، يمكنك الحصول على رقم تعريف المستخدِم الفريد الخاص بالمستخدم الذي سجّل الدخول من المتغيّر auth واستخدامه للتحكم في البيانات التي يمكن للمستخدم الوصول إليها.

للحصول على معلومات عن اللاعب على "ألعاب Play" أو الوصول إلى "خدمات ألعاب Play"، يجب اتّباع الخطوات التالية: استخدام واجهات برمجة التطبيقات المقدّمة من حزمة SDK الخاصة بـ C++ في "خدمات ألعاب Google Play"

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

auth->SignOut();