אימות באמצעות שירותי המשחקים של Google Play עם C++

אתה יכול להשתמש בשירותי Google Play Games כדי להיכנס שחקנים למשחק אנדרואיד שנבנה על Firebase ונכתב ב-C++. כדי להשתמש בשירותי Google Play Games, היכנס באמצעות Firebase, תחילה היכנס לנגן באמצעות Google Play Games, ובקש קוד אימות 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 hash של תעודת החתימה שלך עם הפקודה gradle signingReport :

    ./gradlew signingReport

  2. הפעל את Google Play Games כספק כניסה:

    1. במסוף Firebase, פתח את הקטע אימות .

    2. צור והשיג את מזהה הלקוח של שרת האינטרנט של הפרויקט שלך ואת סוד הלקוח:

      1. בכרטיסייה שיטת כניסה , הפעל את ספק הכניסה של Google .

      2. העתק את מזהה הלקוח והסוד של שרת האינטרנט מספק הכניסה של Google .

    3. בכרטיסייה שיטת כניסה , הפעל את ספק הכניסה של Play Games וציין את מזהה הלקוח של שרת האינטרנט של הפרויקט שלך ואת סוד הלקוח, שקיבלת בשלב האחרון.

הגדר את שירותי Play Games עם פרטי אפליקציית Firebase שלך

  1. ב- Google Play Console , פתח את אפליקציית Google Play שלך או צור אחת.

  2. בקטע 'גדל' , לחץ על שירותי הפעלה של משחקים > הגדרה וניהול > תצורה .

  3. לחץ על כן, המשחק שלי כבר משתמש בממשקי API של Google , בחר בפרויקט Firebase שלך ​​מהרשימה ולאחר מכן לחץ על השתמש .

  4. בדף התצורה של שירותי Play Games, לחץ על הוסף פרטי כניסה .

    1. בחר את סוג שרת המשחק .
    2. בשדה לקוח OAuth , בחר את מזהה לקוח האינטרנט של הפרויקט שלך. ודא שזהו אותו מזהה לקוח שציינת כשהפעלת את הכניסה ל-Play משחקים.
    3. שמור את השינויים שלך.
  5. עדיין בדף התצורה של שירותי Play Games, לחץ שוב על הוסף פרטי כניסה .

    1. בחר את סוג האנדרואיד .
    2. בשדה לקוח OAuth , בחר את מזהה לקוח Android של הפרויקט שלך. (אם אינך רואה את מזהה לקוח Android שלך, הקפד להגדיר את טביעת האצבע SHA-1 של המשחק שלך בקונסולת Firebase.)
    3. שמור את השינויים שלך.
  6. בדף הבודקים , הוסף את כתובות האימייל של המשתמשים שצריכים להיות מסוגלים להיכנס למשחק שלך לפני שתשחרר אותו בחנות Play.

שלב את הכניסה של Play Games לתוך המשחק שלך

לפני שתוכל להכניס שחקנים למשחק שלך, עליך לשלב כניסה ל-Google Play Games.

הדרך הקלה והמומלצת ביותר להוסיף תמיכה בכניסה ל-Play Games לפרויקט C++ Android היא להשתמש ב- Google Sign-in C++ SDK .

כדי להוסיף כניסה של Play Games למשחק שלך באמצעות Google Sign-in C++ SDK, בצע את הפעולות הבאות:

  1. שכפל או הורד את מאגר הפלאגין של Google Sign-in Unity , המכיל גם את C++ SDK.

  2. בנה את הפרויקט הכלול בספריית staging/native/ , באמצעות Android Studio או gradlew build .

    ה-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. לאחר מכן, כלול את רכיב Java Helper, אשר נדרש על ידי C++ SDK.

    לשם כך, בקובץ build.gradle ברמת הפרויקט, הוסף את ספריית הפלט SDK build כמאגר מקומי:

    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 Games וכדי לאחזר קוד אישור שרת:

    #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 Games עבור אישור 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 כדי לסקר שיחות אסינכרוניות. עם זאת, אם התוכנית שלך מונעת מאירועים, ייתכן שתעדיף לרשום פונקציות התקשרות חוזרת. פונקציית התקשרות חוזרת נקראת עם השלמת העתיד.
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 Games שלו. החשבון החדש הזה מאוחסן כחלק מפרויקט Firebase שלך, וניתן להשתמש בו כדי לזהות משתמש בכל אפליקציה בפרויקט שלך.

במשחק שלך, אתה יכול לקבל את Firebase UID של המשתמש מ- 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 וב-Cloud Storage, תוכל לקבל את מזהה המשתמש הייחודי של המשתמש המחובר ממשתנה auth , ולהשתמש בו כדי לשלוט לאילו נתונים המשתמש יכול לגשת.

כדי לקבל מידע על נגן Play משחקים של משתמש או כדי לגשת לשירותי Play משחקים, השתמש בממשקי ה-API המסופקים על ידי שירותי Google Play Games C++ SDK .

כדי לצאת ממשתמש, התקשר ל- SignOut() :

auth->SignOut();