Compila una app para iOS con Firebase y el entorno flexible de App Engine

Last reviewed 2018-08-27 UTC

En este instructivo, se demuestra cómo escribir una app para iOS con almacenamiento de datos de backend, sincronización en tiempo real y registro de eventos del usuario con Firebase. Los servlets de Java que se ejecutan en el entorno flexible de App Engine detectan registros de usuarios nuevos almacenados en Firebase y los procesan.

En las instrucciones, se muestra cómo hacerlo con Firebase y el entorno flexible de App Engine.

Si deseas que tu aplicación procese datos del usuario o que organice eventos, puedes extender Firebase con el entorno flexible de App Engine para realizar una sincronización automática de datos en tiempo real.

La app de muestra, Playchat, almacena mensajes de chat en Firebase Realtime Database, que sincroniza esos datos en todos los dispositivos de forma automática. Playchat también escribe los registros de eventos del usuario en Firebase. Si quieres obtener más información sobre cómo la base de datos sincroniza los datos, consulta ¿Cómo funciona? en la documentación de Firebase.

En el siguiente diagrama, se muestra la arquitectura del cliente de Playchat.

Arquitectura de cliente de Playchat

Un conjunto de servlets de Java que se ejecutan en el entorno flexible de App Engine se registran como objetos de escucha con Firebase. Los servlets responden a los nuevos registros de eventos del usuario y procesan los datos de registro. Los servlets usan transacciones para garantizar que solo un servlet maneje cada registro de eventos del usuario.

En el siguiente diagrama, se muestra la arquitectura del servidor de Playchat.

Arquitectura de servidor de Playchat

La comunicación entre la app y el servlet ocurre en tres partes:

  • Cuando un usuario nuevo se conecta a Playchat, la app solicita un servlet de registro para ese usuario y agrega una entrada en /inbox/ en Firebase Realtime Database.

  • Uno de los servlets acepta la asignación y actualiza el valor de la entrada a su identificador de servlet. El servlet usa una transacción de Firebase para garantizar que sea el único servlet que pueda actualizar el valor. Una vez actualizado el valor, todos los demás servlets ignoran la solicitud.

  • Cuando el usuario accede, cierra sesión o cambia a un nuevo canal, Playchat registra la acción en /inbox/[SERVLET_ID]/[USER_ID]/; en este caso, [SERVLET_ID] es el identificador de la instancia del servlet y [USER_ID] es un valor de hash que representa al usuario.

  • El servlet detecta las entradas nuevas en la bandeja de entrada y recopila los datos de registro.

En esta app de muestra, los servlets copian los datos de registro de forma local y los muestran en una página web. En una versión de producción de esta app, los servlets podrían procesar los datos de registro o copiarlos en Cloud Storage, Cloud Bigtable o BigQuery para su almacenamiento y análisis.

Objetivos

En este instructivo, se muestra cómo realizar las siguientes acciones:

  • Compilar una app para iOS, Playchat, que almacena datos en Firebase Realtime Database

  • Ejecutar un servlet de Java en el entorno flexible de App Engine que se conecte a Firebase y reciba notificaciones cuando cambien los datos almacenados en Firebase

  • Usar estos dos componentes para compilar un servicio de backend distribuido de transmisión a fin de recolectar y procesar datos de registro

Costos

Firebase tiene un nivel de uso gratuito. Si el uso de estos servicios es menor que los límites especificados en el plan gratuito de Firebase, no se aplican cargos por usar Firebase.

Las instancias dentro del entorno flexible de App Engine se cobran según el costo de las máquinas virtuales subyacentes de Compute Engine.

Antes de comenzar

Instala el siguiente software:

Ejecuta el siguiente comando en una ventana de terminal para instalar el componente de Java de App Engine de la CLI de gcloud.

gcloud components install app-engine-java

Clona el código de muestra

  1. Clona el código de la app cliente.

    git clone https://github.com/GoogleCloudPlatform/firebase-ios-samples
    
  2. Clona el código del servlet de backend.

    git clone https://github.com/GoogleCloudPlatform/firebase-appengine-backend
    

Crea un proyecto de Firebase

  1. Crea una cuenta de Firebase o inicia sesión en una cuenta existente.

  2. Haz clic en Agregar proyecto.

  3. En Nombre del proyecto, ingresa: Playchat. Anota el ID del proyecto que se le asignó a tu proyecto, ya que se usa en varios pasos de este instructivo.

  4. Sigue los pasos de configuración restantes y haz clic en Crear proyecto.

  5. Después de que el asistente aprovisione tu proyecto, haz clic en Continuar.

  6. En la página Descripción general de tu proyecto, haz clic en el ícono de Configuración y, a continuación, haz clic en Configuración del proyecto.

  7. Haz clic en Agregar Firebase a tu app para iOS.

  8. En ID del paquete de iOS, ingresa: com.google.cloud.solutions.flexenv.PlayChat.

  9. Haz clic en Registrar app.

  10. Sigue los pasos en la sección Descargar archivo de configuración para agregar el archivo GoogleService-Info.plist a la carpeta PlayChat en tu proyecto.

  11. Haz clic en Siguiente en la sección Descargar archivo de configuración.

  12. Toma nota de las instrucciones a fin de usar CocoaPods para instalar y administrar las dependencias del proyecto. El administrador de dependencias de CocoaPods ya se configuró en el código de muestra.

  13. Ejecuta el siguiente comando para instalar las dependencias. Es posible que el comando tarde mucho tiempo en completarse.

    pod install
    

    Es posible que debas ejecutar pod repo update si durante la instalación de CocoaPods no se puede encontrar la dependencia de Firebase.

    Después de este paso, usa el archivo .xcworkspace recién creado en lugar del archivo .xcodeproj en todos tus desarrollos futuros en la app para iOS.

  14. Haz clic en Siguiente en la sección Agregar el SDK de Firebase.

  15. Toma nota del código requerido para inicializar Firebase en tu proyecto.

  16. Haz clic en Siguiente, en la sección Agregar código de inicialización.

  17. Haz clic en Omitir este paso en la sección Ejecutar tu app para verificar la instalación.

Crea Realtime Database

  1. En Firebase console, selecciona el proyecto.

  2. En el menú de la izquierda de la consola, selecciona Realtime Database en el grupo Compilar.

  3. Haz clic en Crear base de datos en la sección Realtime Database.

  4. Selecciona una ubicación cercana.

  5. En el cuadro de diálogo Reglas de seguridad, selecciona Comenzar en modo de prueba y, luego, haz clic en Habilitar.

    En este paso, se muestran los datos que almacenaste en Firebase. En los pasos posteriores de este instructivo, puedes repasar esta página web para ver los datos que la app cliente y el servlet de backend agregaron y actualizaron.

  6. En la pestaña Reglas de la base de datos, asegúrate de contar con las reglas de seguridad para lectura y escritura que especifican una fecha 30 días en el futuro con la unidad de tiempo definida en Tiempo de época de Unix. Por ejemplo, si creas la regla el 4 de agosto, esta debería vencer después del 4 de septiembre.

    {
      "rules": {
        ".read": "now < 1659639249000", //2022-08-04
        ".write": "now < 1659639249000" //2022-08-04
      }
    }
    
  7. Toma nota de la URL de Firebase de tu proyecto, que tiene el formato https://[FIREBASE_PROJECT_ID].firebaseio.com/ y aparece junto al ícono de un vínculo.

Habilita la autenticación de Google para el proyecto de Firebase

Hay una variedad de proveedores de acceso que puedes configurar para conectarte a tu proyecto de Firebase. En este instructivo, aprenderás a configurar la autenticación para que un usuario pueda acceder con una Cuenta de Google.

  1. En el menú de la izquierda de Firebase console, haz clic en Autenticación en el grupo Desarrollar.

  2. Haz clic en Configurar el método de acceso o en Comenzar si es la primera vez que visitas la página.

  3. En la pestaña Método de acceso, selecciona Google, usa el botón de activación Habilitar, selecciona el correo electrónico de asistencia y haz clic en Guardar.

Agrega una cuenta de servicio al proyecto de Firebase

El servlet de backend no usa una Cuenta de Google para acceder. En su lugar, se conecta a Firebase con una cuenta de servicio. Sigue los siguientes pasos a fin de crear una cuenta de servicio que pueda conectarse a Firebase y para agregar las credenciales de la cuenta de servicio al código del servlet.

  1. En el menú de la izquierda de Firebase console, al lado de la página principal del proyecto de Playchat, selecciona el ícono de Configuración y, luego, Configuración del proyecto.

  2. Selecciona la pestaña Cuentas de servicio y, luego, haz clic en el vínculo Administrar permisos de cuenta de servicio.

  3. Haz clic en Crear cuenta de servicio.

  4. Establece la siguiente configuración:

    1. En Nombre de la cuenta de servicio, ingresa playchat-servlet y, luego, haz clic en Crear y continuar.
    2. En Selecciona una función, selecciona Proyecto > Propietario y, luego, haz clic en Continuar.

    3. Haga clic en Listo.

  5. Haz clic en la cuenta de servicio que acabas de crear, en la pestaña CLAVES, haz clic en Agregar clave y, luego, en Crear clave nueva.

  6. Junto a Tipo de clave, haz clic en JSON y, luego, en Crear para descargar la clave.

  7. Guarda el archivo de claves JSON que descargaste para la cuenta de servicio en el proyecto de servicio de backend, firebase-appengine-backend, en el directorio src/main/webapp/WEB-INF/. El nombre del archivo tiene el siguiente formato: Playchat-[UNIQUE_ID].json.

  8. Edita src/main/webapp/WEB-INF/web.xml y los parámetros de inicialización de la siguiente manera:

    • Reemplaza JSON_FILE_NAME por el nombre del archivo de claves JSON que descargaste.

    • Reemplaza FIREBASE_URL por la URL de Firebase que anotaste antes.

      <init-param>
        <param-name>credential</param-name>
        <param-value>/WEB-INF/JSON_FILE_NAME</param-value>
      </init-param>
      <init-param>
        <param-name>databaseUrl</param-name>
        <param-value>FIREBASE_URL</param-value>
      </init-param>
      

Habilita la facturación y las API para el proyecto de Google Cloud

Para que el servicio de backend se ejecute en GCP, debes habilitar la facturación y las API del proyecto. El proyecto de Cloud es el mismo que creaste en Crea un proyecto de Firebase y tiene el mismo identificador de proyecto.

  1. En Google Cloud Console, selecciona el proyecto de Playchat.

    Ir a la página Proyectos

  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  3. Habilita las API de App Engine Admin and Compute Engine.

    Habilita las API

Compila y luego implementa el servicio de backend

El servicio de backend en este ejemplo usa una configuración de Docker para especificar su entorno de hosting. Debido a esta personalización, debes usar el entorno flexible de App Engine en lugar del entorno estándar de App Engine.

Para compilar el servlet de backend y luego implementarlo en el entorno flexible de App Engine, puedes usar el complemento de Maven de Google App Engine. Este complemento ya está especificado en el archivo de compilación de Maven incluido en este ejemplo.

Configura el proyecto

Si quieres que Maven sea capaz de compilar el servlet de backend de manera adecuada, debes proporcionarle el proyecto de Google Cloud Platform (GCP) para que pueda iniciar los recursos del servlet en él. El identificador del proyecto de GCP y el identificador del proyecto de Firebase son los mismos.

  1. Proporciona las credenciales que usa la CLI de gcloud para acceder a GCP.

    gcloud auth login
    
  2. Configura el proyecto como tu proyecto de Firebase con el siguiente comando y reemplaza [FIREBASE_PROJECT_ID] por el nombre del ID del proyecto de Firebase que anotaste antes.

    gcloud config set project [FIREBASE_PROJECT_ID]
    
  3. Verifica que el proyecto se haya configurado con una lista de las opciones de configuración.

    gcloud config list
    
  4. Si es la primera vez que usas App Engine, inicializa la app de App Engine:

    gcloud app create
    

Ejecuta el servicio en el servidor local (opcional)

Cuando desarrolles un nuevo servicio de backend, ejecuta el servicio de forma local antes de implementarlo en App Engine para iterar con rapidez los cambios sin la sobrecarga que puede generar una implementación completa en App Engine.

Si ejecutas el servidor de forma local, este no usa una configuración de Docker ni se ejecuta en un entorno de App Engine. En su lugar, Maven garantiza que todas las bibliotecas dependientes estén instaladas de forma local y que la app se ejecute en el servidor web de Jetty.

  1. En el directorio firebase-appengine-backend, crea y ejecuta el módulo de backend de manera local con el siguiente comando:

    mvn clean package appengine:run
    

    Si instalaste Google Cloud CLI en un directorio que no sea ~/google-cloud-sdk, agrega la ruta de instalación al comando como se muestra a continuación y reemplaza [PATH_TO_TOOL] por tu ruta personalizada.

    mvn clean package appengine:run -Dgcloud.gcloud_directory=[PATH_TO_TOOL]
    
  2. Si se te pregunta ¿Deseas que la aplicación “Python.app” acepte conexiones de red entrantes?, selecciona Permitir.

Cuando finalice la implementación, abre http://localhost:8080/printLogs para verificar que tu servicio de backend esté en ejecución. En la página web, se muestra Bandeja de entrada: seguido de un identificador de 16 dígitos. Este es el identificador de la bandeja de entrada del servlet que se ejecuta en tu máquina local.

Este identificador no cambia aunque actualices la página; tu servidor local pone en marcha una sola instancia del servlet. Esto es útil para realizar pruebas, porque solo hay un identificador de servlet almacenado en Firebase Realtime Database.

Para cerrar el servidor local, oprime Ctrl+C.

Implementa el servicio en el entorno flexible de App Engine

Cuando ejecutas el servicio de backend en el entorno flexible de App Engine, App Engine usa la configuración en /firebase-appengine-backend/src/main/webapp/Dockerfiles para compilar el entorno de hosting en el que se ejecuta el servicio. El entorno flexible pone en marcha varias instancias del servlet y las escala verticalmente para satisfacer la demanda.

  • En el directorio firebase-appengine-backend, crea y ejecuta el módulo de backend de manera local con el siguiente comando:

    mvn clean package appengine:deploy
    
    mvn clean package appengine:deploy -Dgcloud.gcloud_directory=[PATH_TO_GCLOUD]
    

A medida que se ejecuta la compilación, verás las líneas “Enviando contexto de compilación al daemon de Docker…”. El comando anterior sube tu configuración de Docker y la configura en el entorno flexible de App Engine.

Cuando finaliza la implementación, abre https://[FIREBASE_PROJECT_ID].appspot.com/printLogs; en este caso, [FIREBASE_PROJECT_ID] es el identificador de Crea un proyecto de Firebase. La página web muestra Bandeja de entrada: seguido de un identificador de 16 dígitos. Este es el identificador de la bandeja de entrada para un servlet que se ejecuta en el entorno flexible de App Engine.

Cuando actualizas la página, este identificador cambia de manera periódica a medida que App Engine pone en marcha múltiples instancias del servlet a fin de manejar las solicitudes entrantes de los clientes.

Actualiza el esquema de URL en la muestra de iOS

  1. En Xcode, con el espacio de trabajo de PlayChat abierto, abre la carpeta PlayChat.

  2. Abre GoogleService-Info.plist y copia el valor de REVERSED_CLIENT_ID.

  3. Abre Info.plist y navega hacia Tipos de URL clave > Elemento 0 (Editor) > Esquemas de URL > Elemento 0.

  4. Reemplaza el valor del marcador de posición, [REVERSED_CLIENT_ID], por el valor que copiaste de GoogleService-Info.plist.

Ejecuta y prueba la app para iOS

  1. En Xcode, con el lugar de trabajo PlayChat abierto, selecciona Producto > Ejecutar

  2. Cuando la app esté cargada en el simulador, accede con tu Cuenta de Google.

    Accede a Playchat

  3. Selecciona el canal de libros.

  4. Ingresa un mensaje.

    Envía un mensaje

Cuando lo hagas, la app de Playchat almacenará tu mensaje en Firebase Realtime Database. Firebase sincroniza los datos almacenados en la base de datos de todos los dispositivos. Los dispositivos que ejecuten Playchat mostrarán el nuevo mensaje cuando un usuario seleccione el canal libros.

Envía un mensaje

Verifica los datos

Luego de usar la app de Playchat para generar algunos eventos del usuario con la app de Playchat, puedes verificar que los servlets estén registrados a la escucha y recolecten registros de eventos del usuario.

Abre Firebase Realtime Database de tu app; en este caso [FIREBASE_PROJECT_ID] es el identificador de Crea un proyecto de Firebase.

https://console.firebase.google.com/project/[FIREBASE_PROJECT_ID]/database/data

En la parte inferior de Firebase Realtime Database, en la ubicación de datos /inbox/, hay un grupo de nodos con el prefijo client- seguidos por una clave generada de forma aleatoria que representa el acceso de la cuenta del usuario. A la última entrada en este ejemplo, client-1240563753, le sigue un identificador de 16 dígitos del servlet que se encuentra a la escucha de los eventos de registro de ese usuario, en este ejemplo, 0035806813827987.

Datos almacenados en Firebase Realtime Database

Justo arriba, en la ubicación de datos /inbox/, se encuentran los identificadores de servlet de todos los servlets asignados por el momento. En este ejemplo, solo un servlet recolecta registros. En /inbox/[SERVLET_IDENTIFIER] están los registros de usuario que la app escribió en ese servlet.

Abre la página de App Engine de tu servicio de backend en https://[FIREBASE_PROJECT_ID].appspot.com/printLogs; en este caso [FIREBASE_PROJECT_ID] es el identificador de Crea un proyecto de Firebase. En la página, se muestra el identificador del servlet que registró los eventos del usuario que generaste. También puedes ver las entradas de registro de esos eventos en el identificador de la bandeja de entrada del servlet.

Explora el código

La app para iOS de Playchat define una clase, FirebaseLogger, que usa a fin de escribir los registros de eventos del usuario en Firebase Realtime Database.

import Firebase

class FirebaseLogger {
  var logRef: DatabaseReference!

  init(ref: DatabaseReference!, path: String!) {
    logRef = ref.child(path)
  }

  func log(_ tag: String!, message: String!) {
    let entry: LogEntry = LogEntry(tag: tag, log: message)
    logRef.childByAutoId().setValue(entry.toDictionary())
  }
}

Cuando un usuario nuevo accede, Playchat llama a la función requestLogger a fin de agregar una entrada nueva a la ubicación /requestLogger/ en Firebase Realtime Database y establece un objeto de escucha para poder responder cuando un servlet actualiza el valor de esa entrada y acepta la asignación.

Cuando un servlet actualiza el valor, Playchat quita el objeto de escucha y escribe el registro “Acceso” en la bandeja de entrada del servlet.

func requestLogger() {
  ref.child(IBX + "/" + inbox!).removeValue()
  ref.child(IBX + "/" + inbox!)
    .observe(.value, with: { snapshot in
      print(self.inbox!)
      if snapshot.exists() {
        self.fbLog = FirebaseLogger(ref: self.ref, path: self.IBX + "/"
          + String(describing: snapshot.value!) + "/logs")
        self.ref.child(self.IBX + "/" + self.inbox!).removeAllObservers()
        self.msgViewController!.fbLog = self.fbLog
        self.fbLog!.log(self.inbox, message: "Signed in")
      }
    })
  ref.child(REQLOG).childByAutoId().setValue(inbox)
}

En el lado del servicio de backend, cuando se inicia una instancia del servlet, la función init(ServletConfig config) en MessageProcessorServlet.java se conecta a Firebase Realtime Database y agrega un objeto de escucha en la ubicación de datos /inbox/.

Cuando se agrega una nueva entrada a la ubicación de datos /inbox/, el servlet actualiza el valor con su identificador, una señal a la app de Playchat de que el servlet acepta la asignación a fin de procesar registros para ese usuario. El servlet usa las transacciones de Firebase para garantizar que solo un servlet pueda actualizar el valor y aceptar la asignación.

/*
 * Receive a request from a client and reply back its inbox ID.
 * Using a transaction ensures that only a single servlet instance replies
 * to the client. This lets the client know to which servlet instance
 * send consecutive user event logs.
 */
firebase.child(REQLOG).addChildEventListener(new ChildEventListener() {
  public void onChildAdded(DataSnapshot snapshot, String prevKey) {
    firebase.child(IBX + "/" + snapshot.getValue()).runTransaction(new Transaction.Handler() {
      public Transaction.Result doTransaction(MutableData currentData) {
        // Only the first servlet instance writes its ID to the client inbox.
        if (currentData.getValue() == null) {
          currentData.setValue(inbox);
        }
        return Transaction.success(currentData);
      }

      public void onComplete(DatabaseError error, boolean committed, DataSnapshot snapshot) {}
    });
    firebase.child(REQLOG).removeValue();
  }
  // ...
});

Después de que un servlet acepta una asignación para procesar los registros de eventos del usuario, agrega un objeto de escucha que detecta cuando la app de Playchat escribe un nuevo archivo de registro en la bandeja de entrada del servlet. El servlet responde mediante la recuperación de los datos de registro nuevos de Firebase Realtime Database.

/*
 * Initialize user event logger. This is just a sample implementation to
 * demonstrate receiving updates. A production version of this app should
 * transform, filter, or load to another data store such as Google BigQuery.
 */
private void initLogger() {
  String loggerKey = IBX + "/" + inbox + "/logs";
  purger.registerBranch(loggerKey);
  firebase.child(loggerKey).addChildEventListener(new ChildEventListener() {
    public void onChildAdded(DataSnapshot snapshot, String prevKey) {
      if (snapshot.exists()) {
        LogEntry entry = snapshot.getValue(LogEntry.class);
        logs.add(entry);
      }
    }

    public void onCancelled(DatabaseError error) {
      localLog.warning(error.getDetails());
    }

    public void onChildChanged(DataSnapshot arg0, String arg1) {}

    public void onChildMoved(DataSnapshot arg0, String arg1) {}

    public void onChildRemoved(DataSnapshot arg0) {}
  });
}

Limpia

Sigue estos pasos a fin de evitar que se apliquen cargos a tu cuenta de Google Cloud Platform para los recursos que se usaron en este instructivo:

Borra el proyecto de Google Cloud Platform y Firebase

La forma más sencilla de detener los cargos de facturación es borrar el proyecto que creaste para este instructivo. Aunque creaste el proyecto en Firebase console, también puedes borrarlo en la consola de Google Cloud, ya que los proyectos de Firebase y Cloud son los mismos.

  1. En la consola de Google Cloud, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Borra las versiones no predeterminadas de tu app de App Engine

Si no quieres borrar tu proyecto de GCP y Firebase, puedes reducir los costos si eliminas las versiones no predeterminadas de tu app del entorno flexible de App Engine.

  1. En la consola de Google Cloud, ve a la página Versiones de App Engine.

    Ir a Versiones

  2. Selecciona la casilla de verificación de la versión no predeterminada de la app que deseas borrar.
  3. Para borrar la versión de la app, haz clic en Borrar.

¿Qué sigue?

  • Analiza y archiva datos: en este ejemplo, los servlets almacenan datos de registro solo en la memoria. Para ampliar esta muestra, puedes hacer que los servlets archiven, transformen y analicen los datos con servicios como Google Cloud Storage, Cloud Bigtable, Cloud Dataflow y BigQuery.

  • Distribuye de manera uniforme la carga de trabajo entre los servlets: App Engine proporciona ajuste de escala automático y manual. Con el ajuste de escala automático, el entorno flexible detecta cambios en la carga de trabajo y luego agrega o quita instancias de VM en el clúster. Con el manual, debes especificar un número estático de instancias para manejar el tráfico. Para obtener más información sobre cómo configurar el escalamiento, consulta la sección sobre configuración de escalamiento de servicio en la documentación de App Engine.

    Debido a que los registros de actividad de los usuarios se asignan a los servlets mediante el acceso a Firebase Realtime Database, puede que la carga de trabajo no se distribuya de manera uniforme. Por ejemplo, un servlet podría procesar más registros de eventos del usuario que otros servlets.

    Puedes mejorar la eficiencia si implementas un administrador de cargas de trabajo que controle la carga de trabajo de manera independiente en cada VM. Este balanceo de la carga de trabajo podría basarse en métricas como las solicitudes de registro por segundo o la cantidad de clientes en simultáneo.

  • Recupera registros de eventos del usuario no procesados: en esta implementación de muestra, si una instancia del servlet falla, la app cliente asociada con esa instancia no deja de enviar eventos de registro a la bandeja de entrada del servlet en Firebase Realtime Database. En una versión de producción de esta app, el servicio de backend debe detectar esta situación para recuperar los registros de eventos del usuario no procesados.

  • Implementa funciones adicionales con productos de IA de Cloud: explora cómo proporcionar funciones basadas en AA con productos y servicios de IA de Cloud. Por ejemplo, puedes ampliar esta implementación de ejemplo a fin de proporcionar una función de traducción de voz mediante una combinación de API de Voz a texto, Traducción y Texto a voz. Si quieres obtener más información, consulta Agrega traducción de voz a tu app para Android.