Cree una aplicación de Android con Firebase y Jetpack Compose

1. Introducción

Última actualización: 2022-11-16

Creación de una aplicación de Android con Firebase y Jetpack Compose

En este laboratorio de programación, creará una aplicación de Android llamada Make It So . La interfaz de usuario de esta aplicación se creó completamente con Jetpack Compose , que es el conjunto de herramientas moderno de Android para crear una interfaz de usuario nativa: es intuitivo y requiere menos código que escribir archivos .xml y vincularlos a Actividades, Fragmentos o Vistas.

El primer paso para comprender qué tan bien funcionan juntos Firebase y Jetpack Compose es comprender la arquitectura moderna de Android. Una buena arquitectura hace que el sistema sea fácil de entender, fácil de desarrollar y fácil de mantener, ya que deja muy claro cómo se organizan los componentes y cómo se comunican entre sí. En el mundo de Android, la arquitectura recomendada se llama Model - View - ViewModel . El Modelo representa la capa que accede a los Datos en la aplicación. La vista es la capa de la interfaz de usuario y no debe saber nada sobre la lógica empresarial. Y ViewModel es donde se aplica la lógica comercial, que a veces requiere que ViewModel llame a la capa Model .

Recomendamos encarecidamente leer este artículo para comprender cómo se aplica Model - View - ViewModel a una aplicación de Android creada con Jetpack Compose, ya que facilitará la comprensión del código base y la realización de los siguientes pasos.

lo que vas a construir

Make It So es una sencilla aplicación de lista de tareas pendientes que permite al usuario agregar y editar tareas, agregar banderas, prioridades y fechas de vencimiento, y marcar las tareas como completadas. Las siguientes imágenes muestran las dos páginas principales de esta aplicación: la página de creación de tareas y la página principal con la lista de tareas creadas.

Hazlo así Pantalla de agregar tareaHazlo así Pantalla de inicio

Agregará algunas características que faltan en esta aplicación:

  • Autenticar usuarios con correo electrónico y contraseña
  • Agregue un oyente a una colección de Firestore y haga que la interfaz de usuario reaccione a los cambios
  • Agregue seguimientos personalizados para monitorear el rendimiento de un código específico en la aplicación
  • Cree un conmutador de función usando Remote Config y use el lanzamiento por etapas para iniciarlo

lo que aprenderás

  • Cómo usar Firebase Authentication, Performance Monitoring, Remote Config y Cloud Firestore en una aplicación moderna de Android
  • Cómo hacer que las API de Firebase encajen en una arquitectura MVVM
  • Cómo reflejar los cambios realizados con las API de Firebase en una interfaz de usuario de Compose

Lo que necesitarás

2. Obtenga la aplicación de muestra y configure Firebase

Obtener el código de la aplicación de muestra

Clona el repositorio de GitHub desde la línea de comandos:

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Configurar base de fuego

Lo primero que debe hacer es ir a la consola de Firebase y crear un proyecto de Firebase haciendo clic en el botón "+ Agregar proyecto", como puede ver a continuación:

consola base de fuego

Siga los pasos en la pantalla para completar la creación del proyecto.

Dentro de cada proyecto de Firebase, puede crear diferentes aplicaciones: para Android, iOS, Web, Flutter y Unity. Elige la opción de Android, como ves aquí:

Descripción general del proyecto Firebase

Luego sigue estos pasos:

  1. Ingrese com.example.makeitso como el nombre del paquete y, opcionalmente, ingrese un apodo. Para este codelab, no necesita agregar el certificado de firma de depuración.
  2. Haga clic en Siguiente para registrar su aplicación y acceder al archivo de configuración de Firebase.
  3. Haga clic en Descargar google-services.json para descargar su archivo de configuración y guardarlo en el directorio make-it-so-android/app .
  4. Haga clic en Siguiente . Debido a que los SDK de Firebase ya están incluidos en el archivo build.gradle en el proyecto de muestra, haga clic en Siguiente para saltar a los Siguientes pasos .
  5. Haga clic en Continuar a la consola para finalizar.

Para que la aplicación Make it So funcione correctamente, hay dos cosas que debe hacer en la consola antes de saltar al código: habilitar los proveedores de autenticación y crear la base de datos de Firestore. Primero, habilitemos la autenticación para que los usuarios puedan iniciar sesión en la aplicación:

  1. En el menú Generar , seleccione Autenticación y luego haga clic en Comenzar .
  2. En la tarjeta Método de inicio de sesión , seleccione Correo electrónico/Contraseña y habilítelo.
  3. A continuación, haga clic en Agregar nuevo proveedor y seleccione y habilite Anónimo .

A continuación, configure Firestore. Usarás Firestore para almacenar las tareas de un usuario que haya iniciado sesión. Cada usuario obtendrá su propio documento dentro de una colección de la base de datos.

  1. En el menú Generar , seleccione Firestore y luego haga clic en Crear base de datos .
  2. Mantenga activado Iniciar en modo de producción y haga clic en Siguiente .
  3. Cuando se le solicite, seleccione la ubicación donde se almacenarán sus datos de Cloud Firestore. Al desarrollar una aplicación de producción, querrá que esté en una región cercana a la mayoría de sus usuarios y en común con otros servicios de Firebase, como Functions. Para este codelab, puede conservar la región predeterminada o seleccionar la región más cercana a usted.
  4. Haga clic en Habilitar para aprovisionar su base de datos de Firestore.

Tomemos un momento para crear reglas de seguridad sólidas para la base de datos de Firestore. Abra el panel de control de Firestore y vaya a la pestaña Reglas . Luego actualice las reglas de seguridad para que se vean así:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

Estas reglas básicamente dicen que cualquier usuario que haya iniciado sesión en la aplicación puede crear un documento para sí mismo dentro de cualquier colección. Luego, una vez creado, solo el usuario que creó ese documento podrá ver, actualizar o eliminar ese documento.

Ejecutar la aplicación

¡Ahora está listo para ejecutar la aplicación! Abra la carpeta make-it-so-android/start en Android Studio y ejecute la aplicación (se puede hacer usando un emulador de Android o un dispositivo Android real).

3. Autenticación de base de fuego

¿Qué característica vas a agregar?

En el estado actual de la aplicación de muestra Make It So , un usuario puede comenzar a usar la aplicación sin tener que iniciar sesión primero. Utiliza autenticación anónima para lograr esto. Sin embargo, las cuentas anónimas no permiten que un usuario acceda a sus datos en otros dispositivos o incluso en sesiones futuras. Aunque la autenticación anónima es útil para una incorporación cálida, siempre debe proporcionar la opción para que los usuarios cambien a una forma diferente de inicio de sesión. Con esto en mente, en este laboratorio de programación, agregará autenticación de correo electrónico y contraseña a la aplicación Make It So.

¡Hora de codificar!

Tan pronto como el usuario crea una cuenta, al escribir un correo electrónico y una contraseña, debe solicitar a la API de autenticación de Firebase una credencial de correo electrónico y luego vincular la nueva credencial a la cuenta anónima. Abra el archivo AccountServiceImpl.kt en Android Studio y actualice la función linkAccount para que tenga el siguiente aspecto:

modelo/servicio/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

Ahora abra SignUpViewModel.kt y llame a la función linkAccount del servicio dentro del bloque launchCatching de la función onSignUpClick :

pantallas/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

Primero intenta autenticarse y, si la llamada tiene éxito, pasa a la siguiente pantalla (la SettingsScreen ). Mientras ejecuta estas llamadas dentro de un bloque launchCatching , si ocurre un error en la primera línea, la excepción será capturada y manejada, y la segunda línea no será alcanzada en absoluto.

Tan pronto como se vuelva a abrir la SettingsScreen , debe asegurarse de que las opciones para Iniciar sesión y Crear cuenta hayan desaparecido, porque ahora el usuario ya está autenticado. Para hacer esto, hagamos que SettingsViewModel escuche el estado del usuario actual (disponible en AccountService.kt ), para verificar si la cuenta es anónima o no. Para hacerlo, actualice uiState en SettingsViewModel.kt para que tenga el siguiente aspecto:

pantallas/configuraciones/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

Lo último que debe hacer es actualizar uiState en SettingsScreen.kt para recopilar los estados emitidos por SettingsViewModel :

pantallas/configuraciones/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

Ahora, cada vez que el usuario cambie, la SettingsScreen se recompondrá para mostrar las opciones de acuerdo con el nuevo estado de autenticación del usuario.

¡Hora de probar!

Ejecute Make it So y navegue a la configuración haciendo clic en el ícono de ajustes en la esquina superior derecha de la pantalla. Desde allí, haz clic en la opción de crear cuenta:

Pantalla de configuración Make it SoMake it So pantalla de registro

Escriba un correo electrónico válido y una contraseña segura para crear su cuenta. Debería funcionar y deberías ser redirigido a la página de configuración, donde verás dos nuevas opciones: cerrar sesión y eliminar tu cuenta. Puede verificar la nueva cuenta creada en el panel de Autenticación en la consola de Firebase haciendo clic en la pestaña Usuarios.

4. Almacén de fuego en la nube

¿Qué característica vas a agregar?

Para Cloud Firestore, agregará un agente de escucha a la colección de Firestore que almacena los documentos que representan las tareas que se muestran en Make it So . Una vez que agregue este oyente, recibirá todas las actualizaciones realizadas en esta colección.

¡Hora de codificar!

Actualice el Flow disponible en StorageServiceImpl.kt para que se vea así:

modelo/servicio/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

Este código agrega un oyente a la colección de tareas en función del user.id Cada tarea está representada por un documento en una colección llamada tasks , y cada una de ellas tiene un campo llamado userId . Tenga en cuenta que se emitirá un nuevo Flow si cambia el estado del currentUser (al cerrar sesión, por ejemplo).

Ahora debe hacer que el Flow en TasksViewModel.kt refleje lo mismo que en el servicio:

pantallas/tareas/TasksViewModel.kt

val tasks = storageService.tasks

Y lo último será hacer que la composable function en TasksScreens.kt , que representa la interfaz de usuario, sea consciente de este flujo y lo recopile como un estado. Cada vez que cambie el estado, la función componible se recompondrá automáticamente y mostrará el estado más reciente al usuario. Agregue esto a la TasksScreen composable function :

pantallas/tareas/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

Una vez que la función componible tiene acceso a estos estados, puede actualizar LazyColumn (que es la estructura que usa para mostrar una lista en la pantalla) para que se vea así:

pantallas/tareas/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

¡Hora de probar!

Para probar que funcionó, agregue una nueva tarea usando la aplicación (haciendo clic en el botón Agregar en la esquina inferior derecha de la pantalla). Una vez que termine de crear la tarea, debería aparecer en la colección de Firestore en Firestore Console. Si inicia sesión en Make it So en otros dispositivos con la misma cuenta, podrá editar sus tareas pendientes y ver cómo se actualizan en todos los dispositivos en tiempo real.

5. Supervisión del rendimiento

¿Qué característica vas a agregar?

Es muy importante prestar atención al rendimiento porque es muy probable que los usuarios dejen de usar su aplicación si el rendimiento no es bueno y se toman demasiado tiempo para completar una tarea simple al usarla. Es por eso que a veces es útil recopilar algunas métricas sobre un viaje específico que realiza un usuario en su aplicación. Y para ayudarlo con eso, Firebase Performance Monitoring ofrece seguimientos personalizados . Siga los siguientes pasos para agregar seguimientos personalizados y medir el rendimiento en diferentes fragmentos de código en Make it So .

¡Hora de codificar!

Si abre el archivo Performance.kt , verá una función en línea llamada rastrear. Esta función llama a la API de supervisión del rendimiento para crear un seguimiento personalizado, pasando el nombre del seguimiento como un parámetro. El otro parámetro que ve es el bloque de código que desea monitorear. La métrica predeterminada recopilada para cada seguimiento es el tiempo que tarda en ejecutarse por completo:

modelo/servicio/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

Puede elegir qué partes del código base cree que es importante medir y agregarle seguimientos personalizados. Este es un ejemplo de cómo agregar un seguimiento personalizado a la función linkAccount que viste anteriormente (en AccountServiceImpl.kt ) en este laboratorio de código:

modelo/servicio/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

¡Ahora es tu turno! Agregue algunos rastros personalizados a la aplicación Make it So y continúe con la siguiente sección para probar si funcionó como se esperaba.

¡Hora de probar!

Una vez que termine de agregar las trazas personalizadas, ejecute la aplicación y asegúrese de usar las funciones que desea medir varias veces. Luego diríjase a la consola Firebase y vaya al panel de rendimiento . En la parte inferior de la pantalla, encontrará tres pestañas: Solicitudes de red , Rastreos personalizados y Representación de pantalla .

Vaya a la pestaña Seguimientos personalizados y verifique que los seguimientos que agregó en la base de código se muestren allí y que pueda ver cuánto tiempo lleva ejecutar estos fragmentos de código.

6. Configuración remota

¿Qué característica vas a agregar?

Hay una multitud de casos de uso para Remote Config, desde cambiar la apariencia de su aplicación de forma remota hasta configurar diferentes comportamientos para diferentes segmentos de usuarios. En este laboratorio de código, usará Remote Config para crear un conmutador de función que mostrará u ocultará la nueva función de tarea de edición en la aplicación Make it So.

¡Hora de codificar!

Lo primero que debe hacer es crear la configuración en la consola de Firebase. Para hacerlo, debe navegar hasta el panel de configuración remota y hacer clic en el botón Agregar parámetro . Rellene los campos de acuerdo a la siguiente imagen:

Cuadro de diálogo Crear un parámetro de Remote Config

Una vez que todos los campos estén llenos, puede hacer clic en el botón Guardar y luego Publicar . Ahora que el parámetro está creado y disponible para su base de código, debe agregar el código que obtendrá los nuevos valores para su aplicación. Abra el archivo ConfigurationServiceImpl.kt y actualice la implementación de estas dos funciones:

modelo/servicio/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

La primera función obtiene los valores del servidor y se llama tan pronto como se inicia la aplicación, en SplashViewModel.kt . Es la mejor manera de asegurarse de que los valores más actualizados estarán disponibles en todas las pantallas desde el principio. No es una buena experiencia para el usuario si cambia la interfaz de usuario o el comportamiento de la aplicación más tarde, cuando el usuario está haciendo algo.

La segunda función devuelve el valor booleano que se publicó para el parámetro que acaba de crear en la consola. Y deberá recuperar esta información en TasksViewModel.kt , agregando lo siguiente a la función loadTaskOptions :

pantallas/tareas/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

Está recuperando el valor en la primera línea y usándolo para cargar las opciones de menú para los elementos de la tarea en la segunda línea. Si el valor es false , significa que el menú no contendrá la opción de edición. Ahora que tiene la lista de opciones, debe hacer que la interfaz de usuario la muestre correctamente. Mientras crea una aplicación con Jetpack Compose, debe buscar la composable function que declara cómo debe verse la interfaz de usuario de TasksScreen . Así que abra el archivo TasksScreen.kt y actualice LazyColum para señalar las opciones disponibles en TasksViewModel.kt :

pantallas/tareas/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem es otra composable function que declara cómo debe verse la interfaz de usuario de una sola tarea. Y cada tarea tiene un menú con opciones que se muestra cuando el usuario hace clic en el icono de tres puntos al final de la misma.

¡Hora de probar!

¡Ahora estás listo para ejecutar la aplicación! Verifica que el valor que publicaste usando Firebase console coincida con el comportamiento de la aplicación:

  • Si es false , solo debería ver dos opciones al hacer clic en el icono de tres puntos;
  • Si es true , debería ver tres opciones al hacer clic en el icono de tres puntos;

Intente cambiar el valor un par de veces en la consola y reinicie la aplicación. ¡Así de fácil es lanzar nuevas funciones en su aplicación usando Remote Config!

7. Felicitaciones

¡Enhorabuena, ha creado correctamente una aplicación de Android con Firebase y Jetpack Compose!

Agregó Firebase Authentication, Performance Monitoring, Remote Config y Cloud Firestore a una aplicación de Android creada completamente con Jetpack Compose para la interfaz de usuario, ¡y la hizo encajar en la arquitectura MVVM recomendada!

Otras lecturas

Documentos de referencia