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 para Android con Firebase y Jetpack Compose

En este codelab, crearás una aplicación para Android llamada Make It So. La interfaz de usuario de esta aplicación está construida completamente con Jetpack Compose , que es el moderno conjunto de herramientas de Android para crear una interfaz de usuario nativa: es intuitiva 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 y se comunican los componentes 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 empresarial, que a veces requiere que ViewModel llame a la capa Modelo .

Recomendamos encarecidamente leer este artículo para comprender cómo se aplica Modelo - Vista - ViewModel a una aplicación de Android creada con Jetpack Compose, ya que hará que el código base sea más fácil de entender y que los siguientes pasos sean más fáciles de completar.

lo que construirás

Make It So es una sencilla aplicación de lista de tareas pendientes que permite al usuario agregar y editar tareas, agregar indicadores, 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 Agregar tareaHazlo así Pantalla de inicio

Agregará algunas funciones 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 código específico en la aplicación
  • Cree una función para alternar usando Remote Config y use la implementación por etapas para iniciarla

lo que aprenderás

  • Cómo utilizar 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

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

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

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

Configurar base de fuego

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

Consola de base de fuego

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

Dentro de cada proyecto de Firebase, puedes 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 nombre del paquete y, opcionalmente, ingrese un apodo. Para este codelab, no es necesario 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 del proyecto de muestra, haga clic en Siguiente para pasar 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 debes hacer en la consola antes de pasar 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. Utilizará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ú Construir , seleccione Firestore y luego haga clic en Crear base de datos .
  2. Mantenga habilitado Inicio 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ás que esté en una región cercana a la mayoría de tus usuarios y en común con otros servicios de Firebase, como Functions. Para este codelab, puedes conservar la región predeterminada o seleccionar la región más cercana a ti.
  4. Haga clic en Habilitar para aprovisionar su base de datos de Firestore.

Tomémonos un momento para crear reglas de seguridad sólidas para la base de datos de Firestore. Abra el panel 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;
    }
  }
}

Básicamente, estas reglas dicen que cualquier usuario que haya iniciado sesión en la aplicación puede crear un documento por sí mismo dentro de cualquier colección. Luego, una vez creado, solo el usuario que creó ese documento podrá verlo, actualizarlo o eliminarlo.

Ejecute la aplicación

¡Ahora estás 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 Firebase

¿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 brindar la opción a los usuarios de realizar la conversión a una forma diferente de inicio de sesión. Teniendo esto en cuenta, en este codelab agregarás autenticación de correo electrónico y contraseña a la aplicación Make It So.

¡Es 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á detectada y manejada, y no se alcanzará la segunda línea en absoluto.

Tan pronto como se abra nuevamente la SettingsScreen , debe asegurarse de que las opciones para Iniciar sesión y Crear cuenta desaparezcan, 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/configuración/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/configuración/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.

¡Es hora de probar!

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

Hazlo así pantalla de configuraciónHazlo así, pantalla de registro

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

4. Tienda de fuego en la nube

¿Qué característica vas a agregar?

Para Cloud Firestore, agregará un oyente 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.

¡Es 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 según 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 el estado del currentUser cambia (al cerrar sesión, por ejemplo).

Ahora necesitas 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á crear la composable function en TasksScreens.kt , que representa la UI, estar al tanto de este flujo y recopilarlo como un estado. Cada vez que cambia 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( [...] )
    }
}

¡Es 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. Monitoreo del desempeño

¿Qué característica vas a agregar?

El rendimiento es algo muy importante a lo que hay que prestar atención porque es muy probable que los usuarios dejen de usar su aplicación si el rendimiento no es bueno y les toma demasiado tiempo completar una tarea simple al usarla. Es por eso que a veces es útil recopilar algunas métricas sobre un recorrido específico que realiza un usuario en su aplicación. Y para ayudarte 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.

¡Es hora de codificar!

Si abre el archivo Performance.kt , verá una función en línea llamada seguimiento. Esta función llama a la API de supervisión del rendimiento para crear un seguimiento personalizado y pasa el nombre del seguimiento como 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. A continuación, se muestra un ejemplo de cómo agregar un seguimiento personalizado a la función linkAccount que vio anteriormente (en AccountServiceImpl.kt ) en este codelab:

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 seguimientos personalizados a la aplicación Make it So y continúe con la siguiente sección para probar si funcionó como se esperaba.

¡Es hora de probar!

Una vez que termine de agregar los seguimientos personalizados, ejecute la aplicación y asegúrese de utilizar las funciones que desea medir varias veces. Luego dirígete a la consola de Firebase y ve al panel de Rendimiento . En la parte inferior de la pantalla, encontrará tres pestañas: Solicitudes de red , Seguimientos personalizados y Representación de pantalla .

Vaya a la pestaña Seguimientos personalizados y verifique que los seguimientos que agregó en el código base se muestren allí y que pueda ver cuánto tiempo suele llevar 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 codelab, utilizará Remote Config para crear una función de alternancia que mostrará u ocultará la nueva función de edición de tareas en la aplicación Make it So.

¡Es hora de codificar!

Lo primero que debes hacer es crear la configuración en Firebase console. Para hacerlo, debe navegar hasta el panel de Remote Config y hacer clic en el botón Agregar parámetro . Complete los campos según la imagen a continuación:

Configuración remota Crear un cuadro de diálogo de parámetro

Una vez que todos los campos estén completos, puede hacer clic en el botón Guardar y luego en Publicar . Ahora que el parámetro está creado y disponible para su código base, debe agregar el código que recuperará 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 garantizar que los valores más actualizados estarán disponibles en todas las pantallas desde el principio. ¡No es una buena experiencia de usuario si cambias 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 necesitarás 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 del 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 que apunte a 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 debería 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 ícono de tres puntos al final.

¡Es 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ías ver dos opciones al hacer clic en el ícono de tres puntos;
  • Si es true , deberías ver tres opciones al hacer clic en el ícono de tres puntos;

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

7. Felicitaciones

¡Felicitaciones, ha creado exitosamente una aplicación para Android con Firebase y Jetpack Compose!

Agregaste 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 hiciste encajar en la arquitectura MVVM recomendada.

Otras lecturas

Documentos de referencia