คุณสามารถใช้บริการเกมของ 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 Console ให้ไปที่
การตั้งค่า > แท็บทั่วไปเลื่อนลงไปที่การ์ดแอปของคุณ เลือกแอป Android แล้ว เพิ่มลายนิ้วมือ SHA-1 ในช่องลายนิ้วมือของใบรับรอง SHA
คุณรับแฮช SHA ของใบรับรองการลงนามได้ด้วยคำสั่ง gradle
signingReport./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 Games ก่อนจึงจะให้ผู้เล่นลงชื่อเข้าใช้เกมได้
วิธีที่ง่ายที่สุดและแนะนำในการเพิ่มการรองรับการลงชื่อเข้าใช้ Play Games ในโปรเจ็กต์ Android C++ คือการใช้ Google Sign-in C++ SDK
หากต้องการเพิ่มการลงชื่อเข้าใช้ Play Games ลงในเกมโดยใช้ Google Sign-in C++ SDK ให้ทำดังนี้
โคลนหรือดาวน์โหลดที่เก็บปลั๊กอิน Google Sign-In สำหรับ Unity ซึ่งมี SDK ของ C++ ด้วย
สร้างโปรเจ็กต์ที่อยู่ในไดเรกทอรี
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.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)
จากนั้นให้รวมคอมโพเนนต์ตัวช่วย Java ซึ่ง SDK C++ ต้องใช้
โดยให้เพิ่มไดเรกทอรีเอาต์พุตบิลด์ SDK เป็นที่เก็บในเครื่องในไฟล์
build.gradleระดับโปรเจ็กต์allprojects { repositories { // ... flatDir { dirs 'path/to/google-signin-cpp' } } }และในไฟล์
build.gradleระดับโมดูล ให้ประกาศคอมโพเนนต์ตัวช่วย เป็นทรัพยากร Dependency ดังนี้dependencies { implementation 'com.google.android.gms:play-services-auth:22.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') }จากนั้นในเกม ให้กำหนดค่าออบเจ็กต์
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 Games สำหรับผู้เล่น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 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::SignInAndRetrieveDataWithCredentialLastResultfirebase::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
ฟังก์ชันเพื่อสำรวจการเรียกแบบไม่พร้อมกันได้
อย่างไรก็ตาม หากโปรแกรมของคุณทำงานตามเหตุการณ์ คุณอาจต้องการลงทะเบียนฟังก์ชันการเรียกกลับ
ระบบจะเรียกใช้ฟังก์ชัน 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();