Вы можете использовать сервисы Google Play Games для авторизации игроков в Android-игре, созданной на Firebase и написанной на C++. Чтобы использовать сервисы Google Play Games для авторизации через 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 вашего сертификата подписи можно получить с помощью команды gradle
signingReport:./gradlew signingReport
Подробную информацию о том, как получить SHA-отпечаток вашего приложения, см. в разделе «Аутентификация клиента» .
Включите Google Play Games в качестве способа авторизации:
В консоли Firebase перейдите в раздел Безопасность > Аутентификация .
Сгенерируйте и получите идентификатор клиента веб-сервера и секретный ключ клиента для вашего проекта:
На вкладке «Способ входа» включите поставщика услуг входа Google .
Скопируйте идентификатор клиента веб-сервера и секретный ключ из сервиса авторизации Google .
На вкладке «Метод входа» включите поставщика авторизации Play Games и укажите идентификатор клиента веб-сервера вашего проекта и секретный ключ клиента, которые вы получили на предыдущем шаге.
Настройте Play Games services используя информацию о вашем приложении Firebase.
В консоли Google Play откройте своё приложение Google Play или создайте новое.
В разделе «Развитие» нажмите Play Games services > «Настройка и управление» > «Конфигурация» .
Нажмите «Да, моя игра уже использует API Google» , выберите свой проект 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++ — использовать SDK Google Sign-in для C++ .
Чтобы добавить авторизацию через Play Games в вашу игру с помощью Google Sign-in C++ SDK, выполните следующие действия:
Клонируйте или загрузите репозиторий плагина Google Sign-in Unity , который также содержит SDK для C++.
Соберите проект, находящийся в каталоге
staging/native/, используя либо Android Studio, либоgradlew build.В процессе сборки выходные данные копируются в каталог с именем
google-signin-cpp.Включите SDK Google Sign-in C++ в файл 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, который требуется для работы 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: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 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 Games на учетные данные Firebase и используйте эти учетные данные для аутентификации игрока:
firebase::auth::Credential credential = firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code); firebase::Future<firebase::auth::AuthResult> result = auth->SignInAndRetrieveDataWithCredential(credential);Если в вашей программе есть цикл обновления, который выполняется регулярно (например, 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 .
Зарегистрируйте обратный вызов в Future
В некоторых программах есть функцииUpdate , которые вызываются 30 или 60 раз в секунду. Например, многие игры следуют этой модели. Такие программы могут вызывать функции LastResult для асинхронного опроса. Однако, если ваша программа управляется событиями, вы можете предпочесть регистрировать функции обратного вызова. Функция обратного вызова вызывается по завершении 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 Realtime Database и Cloud Storage вы можете получить уникальный идентификатор пользователя, вошедшего в систему, из переменной auth и использовать его для управления доступом пользователя к данным.
Чтобы получить информацию об игроке Play Games или получить доступ к сервисам Play Games, используйте API, предоставляемые C++ SDK сервисов Google Play Games .
Для выхода пользователя из системы вызовите SignOut() :
auth->SignOut();