Ir a la consola

Autentica con los Servicios de juego de Google Play con C++

Puedes usar los Servicios de juego de Google Play para incorporar jugadores en un juego de Android creado a partir de Firebase y escrito en C++. Para usar el acceso de los Servicios de juego de Google Play con Firebase, el jugador debe acceder a Google Play Juegos y, en ese momento, debes solicitar un código de autorización OAuth 2.0. Después, pasa el código de Auth a PlayGamesAuthProvider para generar una credencial de Firebase que podrás usar para autenticar con la plataforma.

Antes de comenzar

Para poder usar Firebase Authentication, debes realizar los siguientes pasos:

  • Registra tu proyecto de C++ y configúralo para usar Firebase.

    Si tu proyecto de C++ ya usa Firebase, significa que ya está registrado y configurado para esa plataforma.

  • En el archivo build.gradle de nivel de proyecto, asegúrate de incluir el repositorio Maven de Google en las secciones buildscript y allprojects.

  • Agrega el SDK de Firebase C++ a tu proyecto de C++.

Ten en cuenta que agregar Firebase al proyecto de C++ implica realizar tareas en Firebase console y en tu proyecto abierto de C++ (por ejemplo, descargar archivos de configuración de Firebase desde la consola y transferirlos al proyecto de C++).

Configura el proyecto de Firebase

  1. Si aún no lo has hecho, configura la huella digital SHA-1 de tu juego en la página Configuración de Firebase console.

    Puedes obtener la huella digital SHA-1 de tu clave con el comando keytool:

    keytool -exportcert -list -v \
        -alias YOUR-KEY-NAME -keystore PATH-TO-KEYSTORE

  2. Habilita Google Play Juegos como proveedor de acceso:

    1. Encuentra el secreto de cliente y el ID de cliente del servidor web del proyecto. El ID de cliente del servidor web identifica tu proyecto de Firebase en los servidores de autenticación de Google Play.

      Sigue estos pasos para encontrar esos valores:

      1. Abre el proyecto de Firebase en la página de credenciales de la Consola de API de Google.
      2. En la sección ID de cliente OAuth 2.0, abre la página de detalles Cliente web (creado automáticamente por el servicio de Google). Esta página muestra el ID y el secreto de cliente del servidor web.
    2. Luego, en Firebase console, abre la sección Authentication.

    3. En la pestaña Método de acceso, habilita el proveedor de acceso Play Juegos. Deberás especificar el secreto de cliente y el ID de cliente del servidor web del proyecto, que obtuviste de la Consola de API.

  1. Abre Google Play Console y haz clic en Servicios de juego.
  2. Haz clic en Agregar juego nuevo. En el diálogo de juego nuevo, haz clic en Ya utilizo las API de Google en mi juego y haz clic en el nombre de tu proyecto de Firebase en la lista. Selecciona una categoría de juego y haz clic en Continuar para ir a la página de detalles del juego.
  3. Asegúrate de que todas las API necesarias estén habilitadas al final de la página de detalles del juego.
  4. Luego, abre la página Apps vinculadas y haz clic en Android. Especifica el nombre del paquete de tu juego y haz clic en Guardar y continuar. La consola mostrará tu ID de cliente de Android. Puedes ignorar este valor.
  5. En la página Pruebas, incluye en la lista blanca las direcciones de correo electrónico de los usuarios que deben poder acceder a tu juego antes de su lanzamiento en Play Store.

Integra el acceso a Play Juegos en tu juego

Antes de que incorpores jugadores en tu juego, debes integrar el acceso a Google Play Juegos.

Usar el SDK de C++ de Acceso con Google es la manera recomendada y más sencilla de agregar compatibilidad para el acceso a Play Juegos a un proyecto de Android C++.

Para agregar el acceso a tu juego con Play Juegos mediante el SDK de C++ de Acceso con Google, haz lo siguiente:

  1. Clona o descarga el repositorio del complemento de Unity de Acceso con Google, que también contiene el SDK de C++.

  2. Compila el proyecto contenido en el directorio staging/native/ con Android Studio o gradlew build.

    La compilación copia los resultados en un directorio llamado google-signin-cpp.

  3. Incluye el SDK de C++ de Acceso con Google en el archivo de construcción de código nativo del juego:

    CMake

    En el archivo CMakeLists.txt de nivel superior:

    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

    En el archivo 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. A continuación, incluye el componente auxiliar de Java, que necesita el SDK de C++.

    Para ello, en el archivo build.gradle de nivel de proyecto, agrega el directorio de resultados de compilación del SDK como repositorio local:

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

    Y, en el archivo build.gradle de nivel de módulo, declara el componente auxiliar como dependencia:

    dependencies {
        implementation 'com.google.android.gms:play-services-auth:16.0.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. A continuación, en tu juego, configura un objeto GoogleSignIn para usar el acceso a Play Juegos y recuperar un código de Auth del servidor:

    #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. Por último, llama a SignIn() para incorporar al jugador en Play Juegos:

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

    Cuando se resuelva el valor Future que se genere con SignIn(), podrás obtener del resultado el código de Auth del servidor:

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

Autentica con Firebase

Después de que el jugador acceda con Play Juegos, puedes usar el código Auth para realizar la autenticación con Firebase.

  1. Después de que el jugador acceda correctamente mediante Play Juegos, obtén un código de Auth para la cuenta del jugador:

  2. Luego, intercambia el código de Auth desde los servicios de Play Juegos para obtener una credencial de Firebase. A continuación, usa esa credencial para autenticar al jugador de la siguiente manera:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  3. Si tu programa tiene un bucle de actualización que se ejecuta de manera regular (por ejemplo, 30 o 60 veces por segundo), puedes verificar los resultados una vez por actualización con Auth::SignInWithCredentialLastResult:

    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredentialLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        firebase::auth::User* user = *result.result();
        printf("Sign in succeeded for `%s`\n", user->display_name().c_str());
      } else {
        printf("Sign in failed with error '%s'\n", result.error_message());
      }
    }

    Si tu programa es controlado por eventos, te recomendamos que registres una devolución de llamada en Future.

Registra una devolución de llamada en Future

Algunos programas tienen funciones Update que se llaman 30 o 60 veces por segundo. Por ejemplo, muchos juegos siguen este modelo. Estos programas pueden llamar a las funciones LastResult para sondear las llamadas asíncronas. Sin embargo, si tu programa es controlado por eventos, tal vez prefieras registrar las funciones de devolución de llamada. Se solicita una función de devolución de llamada una vez que se complete 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::User*> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // `&my_program_context` is passed verbatim to OnCreateCallback().
  result.OnCompletion(OnCreateCallback, &my_program_context);
}
La función de devolución de llamada también puede ser lambda, si así lo prefieres.
void CreateUserUsingLambda(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::User*> 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);
}

Próximos pasos

Cuando un usuario accede por primera vez, se crea una nueva cuenta de usuario y se vincula con su ID de Play Juegos. Esta cuenta nueva se almacena como parte de tu proyecto de Firebase y se puede usar para identificar a un usuario en todas las apps del proyecto.

En el juego, puedes obtener el UID de Firebase del usuario desde el objeto firebase::auth::User

firebase::auth::User* user = auth->current_user();
if (user != nullptr) {
  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();
}

En las reglas de seguridad de Firebase Realtime Database y de Cloud Storage, puedes obtener el ID único del usuario que accedió a partir de la variable auth y usarlo para controlar los datos a los que tiene acceso.

A fin de obtener la información de jugador de Play Juegos de un usuario o para acceder a los servicios de Play Juegos, usa las API que proporcionó el SDK de C++ de Servicios de juego de Google Play.

Para cerrar la sesión de un usuario, llama a SignOut() de la siguiente manera:

auth->SignOut();