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

Usługi Gier Google Play możesz wykorzystać do logowania graczy w grze na Androida opartej na Firebase i napisanej w C++. Aby używać logowania w usługach Gier Google Play z Firebase, najpierw zaloguj gracza w usługach Gier Google Play i poproś o kod autoryzacji OAuth 2.0. Następnie przekaż kod autoryzacji do funkcji PlayGamesAuthProvider, aby wygenerować dane logowania Firebase, których możesz użyć do uwierzytelniania w Firebase.

Zanim zaczniesz

Zanim zaczniesz korzystać z Firebase Authentication, musisz:

  • Zarejestruj projekt C++ i skonfiguruj go tak, aby korzystał z Firebase.

    Jeśli Twój projekt w C++ korzysta już z Firebase, jest już zarejestrowany i skonfigurowany pod kątem tej usługi.

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

Pamiętaj, że dodanie Firebase do projektu C++ wymaga wykonania czynności zarówno w Firebasekonsoli, jak i w otwartym projekcie C++ (np. pobierasz z konsoli pliki konfiguracyjne Firebase, a następnie przenosisz je do projektu C++).

Konfigurowanie projektu w Firebase

  1. Określ odcisk cyfrowy SHA-1 aplikacji, jeśli nie zostało to jeszcze zrobione.

    1. W konsoli Firebase otwórz Ustawienia > karta Ogólne.

    2. Przewiń w dół do karty Twoje aplikacje, wybierz aplikację na Androida i dodaj odcisk cyfrowy SHA-1 w polu Odciski cyfrowe certyfikatu SHA.

    Skrót SHA certyfikatu podpisywania możesz uzyskać za pomocą polecenia gradle signingReport:

    ./gradlew signingReport

    Więcej informacji o tym, jak uzyskać odcisk cyfrowy SHA aplikacji, znajdziesz w artykule Uwierzytelnianie klienta.

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

    1. W konsoli Firebase otwórz Bezpieczeństwo > Uwierzytelnianie.

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

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

      2. Skopiuj identyfikator klienta i tajny klucz serwera internetowego od dostawcy logowania Google.

    3. Na karcie Metoda logowania włącz dostawcę logowania Play Games i określ identyfikator klienta serwera WWW projektu oraz tajny klucz klienta, które zostały uzyskane w ostatnim kroku.

Skonfiguruj Play Games services za pomocą informacji o aplikacji w Firebase.

  1. W Google Playkonsoli otwórz aplikację Google Play lub utwórz nową.

  2. W sekcji Rozwój kliknij Play Games services > Konfiguracja i zarządzanie > Konfiguracja.

  3. Kliknij Tak, w swojej grze używam już interfejsów API Google, wybierz z listy projekt Firebase i kliknij Użyj.

  4. Na stronie konfiguracji Play Games services kliknij Dodaj dane logowania.

    1. Wybierz typ Serwer gry.
    2. W polu Klient OAuth wybierz identyfikator klienta usługi internetowej projektu. Upewnij się, że jest to ten sam identyfikator klienta, który został podany podczas włączania logowania za pomocą Play Games.
    3. Zapisz zmiany.
  5. Na stronie konfiguracji Play Games services ponownie kliknij Dodaj dane logowania.

    1. Wybierz typ Android.
    2. W polu Klient OAuth wybierz identyfikator klienta Androida w swoim projekcie. (Jeśli nie widzisz identyfikatora klienta Androida, upewnij się, że w Firebase konsoli ustawiono odcisk cyfrowy SHA-1 gry).
    3. Zapisz zmiany.
  6. Na stronie Testerzy dodaj adresy e-mail użytkowników, którzy muszą mieć możliwość zalogowania się w Twojej grze przed jej opublikowaniem w Play Store.

Integrowanie logowania w Grach Play z grą

Zanim zaczniesz logować graczy w swojej grze, musisz zintegrować logowanie w Grach Google Play.

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

Aby dodać do gry logowanie w Gry Play za pomocą pakietu C++ SDK do logowania przez Google:

  1. Sklonuj lub pobierz repozytorium wtyczki logowania przez Google do Unity, które zawiera też pakiet SDK w C++.

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

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

  3. Uwzględnij pakiet SDK do logowania przez Google w pliku make kodu natywnego 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 wyjściowy kompilacji pakietu SDK jako repozytorium lokalne:

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

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

    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')
    }
    
  5. Następnie w grze skonfiguruj obiekt GoogleSignIn, aby używać logowania w usługach Gier 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 funkcję SignIn(), aby zalogować gracza w Grach Play:

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

    Gdy obiekt Future zwrócony przez SignIn() zostanie rozwiązany, możesz uzyskać kod autoryzacji 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();
        }
    }
    

Uwierzytelnianie za pomocą Firebase

Gdy gracz zaloguje się w usługach Gier Play, możesz użyć kodu autoryzacji do uwierzytelnienia w Firebase.

  1. Gdy gracz zaloguje się w usługach Gier Play, uzyskaj kod autoryzacji konta gracza.

  2. Następnie wymień kod autoryzacji z usług gier Play na dane logowania Firebase i użyj ich 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 jest uruchamiana regularnie (np. 30 lub 60 razy na sekundę), możesz sprawdzać 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());
      }
    }

    Jeśli Twój program jest oparty na zdarzeniach, możesz zarejestrować wywołanie zwrotne w obiekcie Future.

Rejestrowanie wywołania zwrotnego w przypadku obiektu Future

Niektóre programy mają funkcje Update, które są wywoływane 30 lub 60 razy na sekundę. Wiele gier korzysta z tego modelu. Te programy mogą wywoływać funkcje LastResult, aby sprawdzać wywołania asynchroniczne. Jeśli jednak program jest oparty na zdarzeniach, możesz zarejestrować funkcje wywołania zwrotnego. Po zakończeniu działania obiektu Future wywoływana jest funkcja wywołania zwrotnego.
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);
}
Funkcja wywołania zwrotnego może być też 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 zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i połączone z jego identyfikatorem w Grach Play. To nowe konto jest przechowywane w ramach projektu w Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w projekcie.

W 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 regułach zabezpieczeń Bazy danych czasu rzeczywistego Firebase i Cloud Storage możesz pobrać unikalny identyfikator zalogowanego użytkownika ze zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik ma dostęp.

Aby uzyskać informacje o graczu w Grach Play lub dostęp do usług Gier Play, użyj interfejsów API udostępnianych przez pakiet C++ SDK dla usług Gier Google Play.

Aby wylogować użytkownika, wywołaj funkcję SignOut():

auth->SignOut();