Mit den Google Play-Spieldiensten mit C++ authentifizieren

Mit den Google Play Games-Diensten können sich Spieler in einem Android-Spiel anmelden, das auf Firebase basiert und in C++ geschrieben wurde. Wenn Sie die Google Play Games-Dienste für die Anmeldung mit Firebase verwenden möchten, melden Sie den Spieler zuerst bei Google Play Games an und fordern Sie dabei einen OAuth 2.0-Autorisierungscode an. Übergeben Sie den Autorisierungscode dann an PlayGamesAuthProvider, um Anmeldedaten für Firebase zu generieren, mit denen Sie sich bei Firebase authentifizieren können.

Hinweis

Bevor Sie Firebase Authentication, verwenden können, müssen Sie Folgendes tun:

  • Registrieren Sie Ihr C++-Projekt und konfigurieren Sie es für die Verwendung von Firebase.

    Wenn Ihr C++-Projekt bereits Firebase verwendet, ist es bereits registriert und für Firebase konfiguriert.

  • Fügen Sie Ihrem C++-Projekt das Firebase C++ SDK hinzu.

Das Hinzufügen von Firebase zu Ihrem C++-Projekt umfasst Aufgaben in der Firebase Console und in Ihrem geöffneten C++-Projekt. Sie laden beispielsweise Firebase-Konfigurationsdateien aus der Console herunter und verschieben sie dann in Ihr C++-Projekt.

Das Firebase-Projekt einrichten

  1. Geben Sie den SHA-1-Fingerabdruck Ihrer App an, falls noch nicht geschehen.

    1. Rufen Sie in der Firebase Console die Einstellungen > Tab „Allgemein“ auf.

    2. Scrollen Sie nach unten zur Karte Meine Apps , wählen Sie Ihre Android-App aus und fügen Sie Ihren SHA-1-Fingerabdruck in das Feld SHA-Zertifikat-Fingerabdrücke ein.

    Sie können den SHA-Hash Ihres Signaturzertifikats mit dem Gradle-Befehl signingReport abrufen:

    ./gradlew signingReport

    Weitere Informationen zum Abrufen des SHA-Fingerabdrucks Ihrer App finden Sie unter Client authentifizieren.

  2. Aktivieren Sie Google Play Games als Anmeldeanbieter:

    1. Rufen Sie in der Firebase Console Security > Authentication auf.

    2. Generieren und rufen Sie die Webserver-Client-ID und den Clientschlüssel Ihres Projekts ab:

      1. Aktivieren Sie auf dem Tab Anmeldemethode den Anmeldeanbieter Google.

      2. Kopieren Sie die Webserver-Client-ID und den Clientschlüssel vom Anmeldeanbieter Google.

    3. Aktivieren Sie auf dem Tab Anmeldemethode den Anmeldeanbieter Play Games und geben Sie die Webserver-Client-ID und den Clientschlüssel Ihres Projekts an, die Sie im letzten Schritt erhalten haben.

Play Games services mit den Informationen Ihrer Firebase-App konfigurieren

  1. Öffnen Sie in der Google Play Console, Ihre Google Play App oder erstellen Sie eine.

  2. Klicken Sie im Bereich Wachstum auf Play Games services > Einrichtung und Verwaltung > Konfiguration.

  3. Klicken Sie auf Ja, in meinem Spiel kommen bereits Google-APIs zum Einsatz, wählen Sie Ihr Firebase Projekt aus der Liste aus und klicken Sie dann auf Verwenden.

  4. Klicken Sie auf der Play Games services Konfigurationsseite auf Anmeldedaten hinzufügen.

    1. Wählen Sie den Typ Gameserver aus.
    2. Wählen Sie im Feld OAuth-Client die Web-Client-ID Ihres Projekts aus. Achten Sie darauf, dass dies dieselbe Client-ID ist, die Sie beim Aktivieren der Play Games Anmeldung angegeben haben.
    3. Speichern Sie die Änderungen.
  5. Klicken Sie noch einmal auf der Play Games services Konfigurationsseite auf Anmeldedaten hinzufügen.

    1. Wählen Sie den Typ Android aus.
    2. Wählen Sie im Feld OAuth-Client die Android-Client-ID Ihres Projekts aus. Wenn Sie Ihre Android-Client-ID nicht sehen, prüfen Sie, ob Sie den SHA-1-Fingerabdruck Ihres Spiels in der Firebase Console festgelegt haben.
    3. Speichern Sie die Änderungen.
  6. Fügen Sie auf der Seite Tester die E-Mail-Adressen aller Nutzer hinzu, die sich in Ihrem Spiel anmelden können müssen, bevor Sie es auf dem Play Store veröffentlichen.

Play Games-Anmeldung in Ihr Spiel einbinden

Bevor sich Spieler in Ihrem Spiel anmelden können, müssen Sie die Google Play Games-Anmeldung einbinden.

Die einfachste und empfohlene Methode, einem C++ Android-Projekt Unterstützung für die Play Games-Anmeldung hinzuzufügen, ist die Verwendung des Google Sign-in C++ SDK.

So fügen Sie Ihrem Spiel die Play Games-Anmeldung mit dem Google Sign-in C++ SDK hinzu:

  1. Klonen oder laden Sie das Google Sign-in Unity-Plug-in-Repository, das auch das C++ SDK enthält.

  2. Erstellen Sie das Projekt im Verzeichnis staging/native/ entweder mit Android Studio oder gradlew build.

    Bei der Erstellung wird die Ausgabe in ein Verzeichnis mit dem Namen google-signin-cpp kopiert.

  3. Fügen Sie das Google Sign-in C++ SDK in die Make-Datei des nativen Codes Ihres Spiels ein:

    CMake

    In der CMakeLists.txt-Datei der obersten Ebene:

    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

    In der Datei 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. Fügen Sie als Nächstes die Java-Hilfskomponente hinzu, die vom C++ SDK benötigt wird.

    Fügen Sie dazu in der build.gradle-Datei auf Projektebene das SDK-Build-Ausgabeverzeichnis als lokales Repository hinzu:

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

    Deklarieren Sie die Hilfskomponente in der build.gradle-Datei auf Modulebene als Abhängigkeit:

    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')
    }
    
  5. Konfigurieren Sie dann in Ihrem Spiel ein GoogleSignIn-Objekt, um die Play Games-Anmeldung zu verwenden und einen Serverautorisierungscode abzurufen:

    #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. Rufen Sie schließlich SignIn() auf, um den Spieler bei Play Games anzumelden:

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

    Wenn die von SignIn() zurückgegebene Future-Funktion aufgelöst wird, können Sie den Serverautorisierungscode aus dem Ergebnis abrufen:

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

Mit Firebase authentifizieren

Nachdem sich der Spieler mit Play Games angemeldet hat, können Sie den Autorisierungscode verwenden, um sich bei Firebase zu authentifizieren.

  1. Nachdem sich der Spieler erfolgreich mit Play Games angemeldet hat, rufen Sie einen Autorisierungscode für das Konto des Spielers ab.

  2. Tauschen Sie dann den Autorisierungscode von den Play Games-Diensten gegen Anmeldedaten für Firebase ein und verwenden Sie die Anmeldedaten für Firebase, um den Spieler zu authentifizieren:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  3. Wenn Ihr Programm eine Aktualisierungsschleife hat, die regelmäßig ausgeführt wird (z. B. 30- oder 60-mal pro Sekunde), können Sie die Ergebnisse einmal pro Aktualisierung mit Auth::SignInAndRetrieveDataWithCredentialLastResult prüfen:

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

    Wenn Ihr Programm ereignisgesteuert ist, können Sie auch einen Callback für die Future-Funktion registrieren.

Callback für eine Future-Funktion registrieren

Einige Programme haben Update-Funktionen, die 30- oder 60-mal pro Sekunde aufgerufen werden. Viele Spiele folgen diesem Modell. Diese Programme können die LastResult-Funktionen aufrufen, um asynchrone Aufrufe abzufragen. Wenn Ihr Programm ereignisgesteuert ist, können Sie auch Callback-Funktionen registrieren. Eine Callback-Funktion wird nach Abschluss der Future-Funktion aufgerufen.
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);
}
Die Callback-Funktion kann auch eine Lambda-Funktion sein.
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);
}

Nächste Schritte

Wenn sich ein Nutzer zum ersten Mal anmeldet, wird ein neues Nutzerkonto erstellt und mit seiner Play Games-ID verknüpft. Dieses neue Konto wird als Teil Ihres Firebase-Projekts gespeichert und kann verwendet werden, um einen Nutzer in allen Apps Ihres Projekts zu identifizieren.

In Ihrem Spiel können Sie die Firebase-UID des Nutzers aus dem Objekt firebase::auth::User abrufen:

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

In den Sicherheitsregeln für die Firebase Realtime Database und Cloud Storage können Sie die eindeutige Nutzer-ID des angemeldeten Nutzers aus der Variablen auth abrufen und damit steuern, auf welche Daten ein Nutzer zugreifen kann.

Wenn Sie die Spielerinformationen eines Nutzers in Play Games abrufen oder auf die Play Games-Dienste zugreifen möchten, verwenden Sie die APIs, die vom Google Play Games-Dienste C++ SDK bereitgestellt werden.

Rufen Sie SignOut() auf, um einen Nutzer abzumelden:

auth->SignOut();