คุณสามารถใช้บริการเกมของ Google Play เพื่อให้ผู้เล่นลงชื่อเข้าใช้เกม Android ที่สร้างด้วย Firebase และเขียนด้วย C++ ได้ หากต้องการใช้การลงชื่อเข้าใช้บริการเกมของ Google Play ด้วย Firebase ให้ผู้เล่นลงชื่อเข้าใช้ด้วย Google Play Games ก่อน แล้วขอรหัสการให้สิทธิ์ OAuth 2.0 เมื่อดำเนินการดังกล่าว จากนั้นส่งรหัสการให้สิทธิ์ไปยัง PlayGamesAuthProvider เพื่อสร้างข้อมูลเข้าสู่ระบบ Firebase ซึ่งคุณสามารถใช้เพื่อตรวจสอบสิทธิ์กับ Firebase ได้
ก่อนเริ่มต้น
คุณต้องดำเนินการต่อไปนี้ก่อนจึงจะใช้ Firebase Authentication, ได้
ลงทะเบียนโปรเจ็กต์ C++ และกำหนดค่าให้ใช้ Firebase
หากโปรเจ็กต์ C++ ใช้ Firebase อยู่แล้ว แสดงว่าโปรเจ็กต์นั้นได้ลงทะเบียนและกำหนดค่าสำหรับ Firebase แล้ว
เพิ่ม Firebase C++ SDK ลงในโปรเจ็กต์ C++
โปรดทราบว่าการเพิ่ม Firebase ลงในโปรเจ็กต์ C++ เกี่ยวข้องกับงานทั้งใน Firebaseคอนโซลและในโปรเจ็กต์ C++ ที่เปิดอยู่ (เช่น คุณดาวน์โหลด ไฟล์กำหนดค่า Firebase จากคอนโซล แล้วย้ายไฟล์เหล่านั้นไปยังโปรเจ็กต์ C++)
ตั้งค่าโปรเจ็กต์ Firebase
ระบุลายนิ้วมือ SHA-1 ของแอปหากยังไม่ได้ระบุ
ในคอนโซล Firebase ให้ไปที่
การตั้งค่า > ทั่วไป แท็บเลื่อนลงไปที่การ์ดแอปของคุณ เลือกแอป Android แล้วเพิ่มลายนิ้วมือ SHA-1 ในช่องลายนิ้วมือของใบรับรอง SHA
คุณสามารถรับแฮช SHA ของใบรับรองที่ลงนามด้วยคำสั่ง
signingReportของ Gradle ได้ดังนี้./gradlew signingReport
ดูรายละเอียดเกี่ยวกับวิธีรับลายนิ้วมือ SHA ของแอปได้ที่หัวข้อการตรวจสอบสิทธิ์ไคลเอ็นต์
เปิดใช้ Google Play Games เป็นผู้ให้บริการลงชื่อเข้าใช้
ในคอนโซล Firebase ให้ไปที่ความปลอดภัย > การตรวจสอบสิทธิ์
สร้างและรับรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์ของเว็บเซิร์ฟเวอร์ของโปรเจ็กต์โดยทำดังนี้
ในแท็บวิธีการลงชื่อเข้าใช้ ให้เปิดใช้ผู้ให้บริการลงชื่อเข้าใช้ Google
คัดลอกรหัสไคลเอ็นต์และรหัสลับของเว็บเซิร์ฟเวอร์จากผู้ให้บริการลงชื่อเข้าใช้ Google
ในแท็บวิธีการลงชื่อเข้าใช้ ให้เปิดใช้ผู้ให้บริการลงชื่อเข้าใช้Play Games แล้วระบุรหัสไคลเอ็นต์และ รหัสลับไคลเอ็นต์ของเว็บเซิร์ฟเวอร์ของโปรเจ็กต์ ซึ่งคุณได้รับในขั้นตอนสุดท้าย
กำหนดค่า Play Games services ด้วยข้อมูลแอป Firebase
ใน Google Play Console, ให้เปิดแอป Google Play หรือสร้างแอป
ในส่วน เพิ่มยอด ให้คลิก Play Games services > การตั้งค่าและการจัดการ > การกำหนดค่า
คลิกใช่ เกมของฉันใช้ Google APIs อยู่แล้ว เลือกโปรเจ็กต์ Firebase จากรายการ แล้วคลิกใช้
ในหน้าการกำหนดค่าPlay Games services ให้คลิก เพิ่มข้อมูลเข้าสู่ระบบ
- เลือกประเภทเซิร์ฟเวอร์เกม
- ในช่องไคลเอ็นต์ OAuth ให้เลือกรหัสไคลเอ็นต์เว็บของโปรเจ็กต์ ตรวจสอบว่ารหัสไคลเอ็นต์นี้เป็นรหัสไคลเอ็นต์เดียวกับที่คุณระบุเมื่อเปิดใช้ Play Gamesการลงชื่อเข้าใช้
- บันทึกการเปลี่ยนแปลง
ในหน้าการกำหนดค่าPlay Games services ให้คลิก เพิ่มข้อมูลเข้าสู่ระบบ อีกครั้ง
- เลือกประเภทAndroid
- ในช่องไคลเอ็นต์ OAuth ให้เลือกรหัสไคลเอ็นต์ Android ของโปรเจ็กต์ (หากไม่เห็นรหัสไคลเอ็นต์ Android โปรดตรวจสอบว่าคุณได้ตั้งค่าลายนิ้วมือ SHA-1 ของเกม ในคอนโซล Firebase แล้ว)
- บันทึกการเปลี่ยนแปลง
ในหน้าผู้ทดสอบ ให้เพิ่มอีเมลของผู้ใช้ที่ต้อง ลงชื่อเข้าใช้เกมได้ก่อนที่คุณจะเผยแพร่เกมใน Play Store
ผสานรวมการลงชื่อเข้าใช้ Play Games เข้ากับเกม
คุณต้องผสานรวมการลงชื่อเข้าใช้บริการเกมของ Google Play ก่อนจึงจะให้ผู้เล่นลงชื่อเข้าใช้เกมได้
วิธีที่ง่ายที่สุดและแนะนำให้ใช้เพื่อเพิ่มการรองรับการลงชื่อเข้าใช้ Play Games ลงในโปรเจ็กต์ Android C++ คือการใช้ Google Sign-in C++ SDK
หากต้องการเพิ่มการลงชื่อเข้าใช้ Play Games ลงในเกมโดยใช้ Google Sign-in C++ SDK ให้ทำดังนี้
โคลนหรือดาวน์โหลดที่เก็บปลั๊กอิน Google Sign-in Unity ซึ่งมี C++ SDK ด้วย
สร้างโปรเจ็กต์ที่อยู่ในไดเรกทอรี
staging/native/โดยใช้ Android Studio หรือgradlew buildการสร้างจะคัดลอกเอาต์พุตไปยังไดเรกทอรีที่ชื่อว่า
google-signin-cppรวม Google Sign-in C++ SDK ไว้ในไฟล์ Make ของโค้ดแบบเนทีฟของเกมโดยทำดังนี้
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.mkinclude $(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)
จากนั้นรวมคอมโพเนนต์ Java Helper ซึ่ง C++ SDK ต้องใช้
หากต้องการทำเช่นนั้น ให้เพิ่มไดเรกทอรีเอาต์พุตบิลด์ SDK เป็นที่เก็บในเครื่องในไฟล์
build.gradleระดับโปรเจ็กต์allprojects { repositories { // ... flatDir { dirs 'path/to/google-signin-cpp' } } }และประกาศคอมโพเนนต์ Helper เป็นทรัพยากร Dependency ในไฟล์
build.gradleระดับโมดูลdependencies { implementation 'com.google.android.gms:play-services-auth:21.5.1' // 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') }จากนั้นกำหนดค่าออบเจ็กต์
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);สุดท้าย ให้เรียกใช้
SignIn()เพื่อให้ผู้เล่นลงชื่อเข้าใช้ Play GamesFuture<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 Games แล้ว คุณสามารถใช้รหัสการให้สิทธิ์เพื่อตรวจสอบสิทธิ์กับ Firebase ได้
หลังจากที่ผู้เล่นลงชื่อเข้าใช้โดยใช้ Play Games สำเร็จแล้ว ให้รับรหัสการให้สิทธิ์สำหรับบัญชีของผู้เล่น
จากนั้นแลกรหัสการให้สิทธิ์จากบริการเกมของ Play เป็นข้อมูลเข้าสู่ระบบ Firebase และใช้ข้อมูลเข้าสู่ระบบ Firebase เพื่อตรวจสอบสิทธิ์ผู้เล่นโดยทำดังนี้
firebase::auth::Credential credential = firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code); firebase::Future<firebase::auth::AuthResult> result = auth->SignInAndRetrieveDataWithCredential(credential);หากโปรแกรมมีลูปการอัปเดตที่ทำงานเป็นประจำ (เช่น 30 หรือ 60 ครั้งต่อวินาที) คุณสามารถตรวจสอบผลลัพธ์ได้ 1 ครั้งต่อการอัปเดตด้วย
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()); } }
หรือหากโปรแกรมของคุณขับเคลื่อนด้วยเหตุการณ์ คุณอาจต้องการ ลงทะเบียน Callback ใน Future
ลงทะเบียน Callback ใน Future
บางโปรแกรมมีฟังก์ชันUpdate ที่เรียกใช้ 30 หรือ 60 ครั้งต่อวินาที
เช่น เกมจำนวนมากใช้โมเดลนี้ โปรแกรมเหล่านี้สามารถเรียกใช้ฟังก์ชัน LastResult เพื่อโพลการเรียกแบบไม่พร้อมกัน
อย่างไรก็ตาม หากโปรแกรมของคุณขับเคลื่อนด้วยเหตุการณ์ คุณอาจต้องการลงทะเบียนฟังก์ชัน Callback
ระบบจะเรียกใช้ฟังก์ชัน Callback เมื่อ 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); }
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 และใช้เพื่อระบุผู้ใช้ในทุกแอปในโปรเจ็กต์ได้
ในเกม คุณสามารถรับ UID 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 Games ของผู้ใช้หรือเข้าถึงบริการเกมของ Play ให้ใช้ API ที่มีให้โดย Google Play Games services C++ SDK
หากต้องการออกจากระบบผู้ใช้ ให้เรียกใช้ SignOut() โดยทำดังนี้
auth->SignOut();