Esegui l'autenticazione utilizzando i servizi per i giochi di Google Play con C++

Puoi utilizzare i servizi per i giochi di Google Play per far accedere i giocatori a un gioco Android sviluppato su Firebase e scritto in C++. Per utilizzare l'accesso ai servizi per i giochi di Google Play con Firebase, fai prima accedere il giocatore con Google Play Giochi e richiedi un codice di autenticazione OAuth 2.0. Quindi, passa il codice di autenticazione a PlayGamesAuthProvider per generare una credenziale Firebase, che puoi utilizzare per autenticarti con Firebase.

Prima di iniziare

Prima di poter utilizzare Firebase Authentication, devi:

  • Registra il tuo progetto C++ e configuralo in modo che utilizzi Firebase.

    Se il tuo progetto C++ utilizza già Firebase, è già registrato e configurato per Firebase.

  • Aggiungi l'SDK Firebase C++ al tuo progetto C++.

Tieni presente che l'aggiunta di Firebase al tuo progetto C++ comporta attività sia nel Console Firebase e nel tuo progetto C++ aperto (ad esempio, scarichi di configurazione di Firebase dalla console, quindi spostali nel progetto C++).

Configura il progetto Firebase

  1. Se non l'hai ancora fatto, imposta la fingerprint SHA-1 del tuo gioco nella pagina Impostazioni della console Firebase.

    Puoi ottenere l'hash SHA del certificato di firma con il comando gradlesigningReport:

    ./gradlew signingReport

  2. Abilita Google Play Games come provider di accesso:

    1. Nella console Firebase, apri il Sezione Authentication.

    2. Genera e ottieni l'ID client e il client del server web del tuo progetto secret:

      1. Nella scheda Metodo di accesso, attiva l'opzione Accedi con Google. o il provider di servizi di terze parti.

      2. Copia l'ID client e il secret del server web da Accedi con Google o il provider di servizi di terze parti.

    3. Nella scheda Metodo di accesso, attiva Play Games. di accesso e specificare l'ID client del server web e del client secret ottenuto nell'ultimo passaggio.

Configura Play Games services con le informazioni dell'app Firebase

  1. Nella Console Google Play, apri l'app Google Play o creane una.

  2. Nella sezione Crescita, fai clic su Play Games services > Configurazione e Gestione > Configurazione.

  3. Fai clic su Sì, il mio gioco utilizza già API di Google, seleziona il progetto Firebase dall'elenco e poi fai clic su Utilizza.

  4. Nella pagina di configurazione di Play Games services, fai clic su Aggiungi credenziale.

    1. Seleziona il tipo di server di gioco.
    2. Nel campo Client OAuth, seleziona l'ID client web del tuo progetto. Essere assicurati che sia lo stesso ID client specificato al momento dell'attivazione Accesso con Play Games.
    3. Salva le modifiche.
  5. Sempre nella pagina di configurazione di Play Games services, fai nuovamente clic su Aggiungi credenziale.

    1. Seleziona il tipo Android.
    2. Nel campo Client OAuth, seleziona l'ID client Android del tuo progetto. Se non vedi il tuo ID client Android, assicurati di impostare il Impronta SHA-1 nella console Firebase.)
    3. Salva le modifiche.
  6. Nella pagina Tester, aggiungi gli indirizzi email di tutti gli utenti che devono poter accedere al tuo gioco prima di pubblicarlo suPlay Store.

Integra l'accesso di Play Giochi nel tuo gioco

Prima di far accedere i giocatori al tuo gioco, devi integrare Google Play Accesso ai giochi.

Il modo più semplice e consigliato per aggiungere il supporto per l'accesso a Play Giochi a un progetto Android C++ è utilizzare l'SDK C++ di Accesso Google.

Per aggiungere l'accesso a Play Giochi al tuo gioco utilizzando l'SDK C++ di Accesso Google, svolgi i seguenti passaggi:

  1. Clona o scarica il repository del plug-in di accesso con Google per Unity, che contiene anche l'SDK C++.

  2. Compila il progetto contenuto nella directory staging/native/ utilizzando Android Studio o gradlew build.

    La compilazione copia il proprio output in una directory denominata google-signin-cpp.

  3. Includi l'SDK C++ di Accedi con Google nel file di creazione del codice nativo del tuo gioco:

    CMake

    Nel file CMakeLists.txt di primo livello:

    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)

    build-ndk

    Nel file 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. Poi, includi il componente helper Java, richiesto dall'SDK C++.

    Per farlo, aggiungi la directory di output della compilazione dell'SDK come repository locale nel file build.gradle a livello di progetto:

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

    Inoltre, nel file build.gradle a livello di modulo, dichiara il componente helper come dipendenza:

    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. Poi, nel tuo gioco, configura un oggetto GoogleSignIn per utilizzare l'accesso a Play Giochi e recuperare un codice di autenticazione del server:

    #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. Infine, chiama SignIn() per far accedere il giocatore a Play Giochi:

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

    Quando si risolve il Futuro restituito da SignIn(), puoi ottenere l'autenticazione del server il codice tratto dal risultato:

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

Esegui l'autenticazione con Firebase

Dopo che il giocatore ha eseguito l'accesso con Play Giochi, puoi utilizzare il codice di autorizzazione per con Firebase.

  1. Dopo che il giocatore ha eseguito l'accesso utilizzando Play Giochi, ricevi un codice di autenticazione per il suo account.

  2. Quindi, scambia il codice di autenticazione dei servizi per i giochi di Google Play con una credenziale Firebase e utilizza la credenziale Firebase per autenticare il giocatore:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  3. Se il tuo programma ha un ciclo di aggiornamento che viene eseguito regolarmente (ad esempio, 30 o 60 volte al secondo), puoi controllare i risultati una volta per aggiornamento con 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());
      }
    }

    Oppure, se il tuo programma è basato su eventi, potresti preferire registrare un callback sul Futuro.

Registra un callback su un Future

Alcuni programmi hanno funzioni Update che vengono chiamate 30 o 60 volte al secondo. Ad esempio, molti giochi seguono questo modello. Questi programmi possono chiamare LastResult per eseguire il polling delle chiamate asincrone. Tuttavia, se il tuo programma è basato su eventi, ti consigliamo di registrare le funzioni di callback. Una funzione di callback viene chiamata al termine del 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);
}
Se preferisci, la funzione di callback può essere anche una funzione lambda.
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);
}

Passaggi successivi

Dopo che un utente ha eseguito l'accesso per la prima volta, viene creato un nuovo account utente e collegati al suo ID Play Giochi. Questo nuovo account viene archiviato nel progetto Firebase e può essere utilizzato per identificare un utente in ogni app del progetto.

Nel tuo gioco, puoi recuperare l'UID Firebase dell'utente dall'oggetto 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();
}

Nelle regole di sicurezza di Firebase Realtime Database e Cloud Storage, puoi recuperare l'ID utente univoco dell'utente che ha eseguito l'accesso dalla variabile auth e utilizzarlo per controllare i dati a cui un utente può accedere.

Per ottenere le informazioni del giocatore di Play Giochi di un utente o per accedere ai servizi per i giochi di Play, utilizza le API fornite dall'SDK C++ dei servizi per i giochi di Google Play.

Per disconnettere un utente, chiama SignOut():

auth->SignOut();