Uwierzytelniaj za pomocą usług gier Google Play z C++

Usługi Gier Google Play umożliwiają logowanie graczy w grze na Androida utworzonej w Firebase i napisanej w języku C++. Aby korzystać z usług gier Google Play, zaloguj się przez Firebase, najpierw zaloguj się w odtwarzaczu w Grach Google Play, a następnie poproś o kod autoryzacji OAuth 2.0. Następnie przekaż ten kod do PlayGamesAuthProvider, by wygenerować dane logowania Firebase, których możesz używać do uwierzytelniania w Firebase.

Zanim zaczniesz

Zanim zaczniesz korzystać z Uwierzytelniania Firebase, musisz:

  • Zarejestruj swój projekt C++ i skonfiguruj go pod kątem korzystania z Firebase.

    Jeśli Twój projekt C++ korzysta już z Firebase, oznacza to, że jest już zarejestrowany i skonfigurowany dla Firebase.

  • Dodaj pakiet SDK Firebase C++ do projektu w C++.

Pamiętaj, że dodanie Firebase do projektu C++ wymaga wykonania zadań zarówno w konsoli Firebase, jak i w otwartym projekcie C++ (np. musisz pobrać pliki konfiguracyjne Firebase z konsoli, a następnie przenieść je do projektu C++).

Skonfiguruj projekt Firebase

  1. Ustaw odcisk cyfrowy SHA-1 swojej gry na stronie Ustawienia w konsoli Firebase.

    Hasz SHA Twojego certyfikatu podpisywania możesz uzyskać za pomocą polecenia Gradle signingReport:

    ./gradlew signingReport

  2. Włącz Gry Google Play jako dostawcę logowania:

    1. W konsoli Firebase otwórz sekcję Uwierzytelnianie.

    2. Wygeneruj i uzyskaj identyfikator klienta serwera WWW oraz tajny klucz klienta:

      1. Na karcie Metoda logowania włącz dostawcę logowania Google.

      2. Skopiuj identyfikator klienta i obiekt tajny serwera WWW z usługi logowania Google.

    3. Na karcie Metoda logowania włącz dostawcę logowania w Grach Play i podaj identyfikator klienta serwera WWW oraz tajny klucz klienta uzyskane w ostatnim kroku.

Skonfiguruj usługi Gier Play, używając informacji z aplikacji Firebase

  1. W Konsoli Google Play otwórz lub utwórz aplikację Google Play.

  2. W sekcji Rozwój kliknij Usługi gier Play > Konfiguracja i zarządzanie > Konfiguracja.

  3. Kliknij Tak, moja gra już korzysta z interfejsów API Google, wybierz z listy swój projekt Firebase i kliknij Użyj.

  4. Na stronie konfiguracji usług gier Play kliknij Dodaj dane logowania.

    1. Wybierz typ Serwer gry.
    2. W polu Klient OAuth wybierz identyfikator klienta internetowego swojego projektu. Upewnij się, że to identyfikator klienta podany podczas włączania logowania w Grach Play.
    3. Zapisz zmiany.
  5. Pozostając na stronie konfiguracji usług gier Play, ponownie kliknij Dodaj dane logowania.

    1. Wybierz typ Androida.
    2. W polu Klient OAuth wybierz identyfikator klienta Androida dla swojego projektu. Jeśli nie widzisz identyfikatora klienta Androida, pamiętaj, aby ustawić odcisk cyfrowy SHA-1 gry w konsoli Firebase.
    3. Zapisz zmiany.
  6. Na stronie Testerzy dodaj adresy e-mail wszystkich użytkowników, którzy muszą mieć możliwość zalogowania się w Twojej grze, zanim opublikujesz ją w Sklepie Play.

Integrowanie logowania w Grach Play z grą

Zanim będzie można zalogować graczy w grze, musisz zintegrować logowanie w Grach Google Play.

Najłatwiejszym i zalecanym sposobem dodania obsługi logowania w Grach Play do projektu na Androida w języku C++ jest użycie pakietu SDK C++ do logowania przez Google.

Aby dodać do gry logowanie się przez Gry Play za pomocą pakietu SDK C++ logowania przez Google, wykonaj te czynności:

  1. Skopiuj lub pobierz repozytorium wtyczki Google Sign-in Unity, które zawiera też pakiet SDK C++.

  2. Zbuduj projekt znajdujący się w katalogu staging/native/ za pomocą Android Studio lub gradlew build.

    Kompilacja kopiuje dane wyjściowe do katalogu o nazwie google-signin-cpp.

  3. Dołącz pakiet SDK C++ do logowania przez Google w natywnym pliku tworzenia kodu gry:

    CMake

    W pliku CMakeLists.txt najwyższego poziomu:

    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

    W pliku 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. Następnie dodaj komponent pomocniczy Java, który jest wymagany przez pakiet SDK C++.

    Aby to zrobić, w pliku build.gradle na poziomie projektu dodaj katalog wyników kompilacji pakietu SDK jako repozytorium lokalne:

    allprojects {
        repositories {
            // ...
            flatDir {
                dirs 'path/to/google-signin-cpp'
            }
        }
    }
    

    W pliku build.gradle na poziomie modułu zadeklaruj komponent pomocniczy jako zależność:

    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. Następnie skonfiguruj w grze obiekt GoogleSignIn, aby korzystać z logowania przez Gry Play i pobierać kod autoryzacji serwera:

    #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. Na koniec wywołaj SignIn(), by zalogować gracza w Grach Play:

    Future<GoogleSignIn::SignInResult> &future = gsi.SignIn();
    

    Gdy wartość Przyszła zwrócona przez funkcję SignIn() zostanie rozpoznana, możesz pobrać kod uwierzytelniania serwera z wyniku:

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

Uwierzytelnij za pomocą Firebase

Gdy gracz zaloguje się w Grach Play, możesz użyć kodu autoryzacji, by uwierzytelnić się w Firebase.

  1. Gdy gracz zaloguje się za pomocą Gier Play, otrzyma kod autoryzacji do jego konta.

  2. Następnie wymień kod autoryzacji z usług gier Play na dane logowania Firebase i użyj danych logowania Firebase do uwierzytelnienia gracza:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  3. Jeśli Twój program ma pętlę aktualizacji, która działa regularnie (np. 30 lub 60 razy na sekundę), możesz sprawdzić wyniki raz na aktualizację za pomocą funkcji 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());
      }
    }

    A jeśli Twój program jest ukierunkowany na zdarzenia, możesz zarejestrować się na rozmowę telefoniczną w przyszłości.

Rejestrowanie oddzwonienia w przyszłości

Niektóre programy mają funkcje Update, które są wywoływane 30 lub 60 razy na sekundę. Na przykład wiele gier korzysta z tego modelu. Programy te mogą wywoływać funkcje LastResult, aby sondować wywołania asynchroniczne. Jeśli jednak Twój program jest oparty na zdarzeniach, możesz zarejestrować funkcje wywołań zwrotnych. Funkcja wywołania zwrotnego jest wywoływana po zakończeniu okresu przyszłego.
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);
}
Jeśli wolisz, funkcja wywołania zwrotnego może też być lambdą.
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);
}

Dalsze kroki

Gdy użytkownik loguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z jego identyfikatorem w Grach Play. Nowe konto będzie przechowywane w ramach Twojego projektu Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w Twoim projekcie.

W swojej grze możesz uzyskać identyfikator Firebase UID użytkownika z obiektu 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();
}

W Bazie danych czasu rzeczywistego Firebase i regułach zabezpieczeń Cloud Storage możesz uzyskać ze zmiennej auth unikalny identyfikator zalogowanego użytkownika i użyć go do kontrolowania, do jakich danych użytkownik ma dostęp.

Aby uzyskać informacje o użytkowniku w Grach Play lub uzyskać dostęp do usług Gier Play, użyj interfejsów API z pakietu C++ SDK usług gier Google Play.

Aby wylogować użytkownika, zadzwoń pod numer SignOut():

auth->SignOut();