1. Antes de comenzar, ¿Qué es Firebase?
2. Firebase Authentication y Firestore
3. Manos a la obra ¿por dónde empezamos?
4. Crear y configurar el proyecto
5. Authentication
6. Firestore
7. Conclusiones
Antes de comenzar, ¿Qué es Firebase?
Firebase es una plataforma de desarrollo en la nube que permite la integración con dispositivos móviles y web. Firebase lo componen una serie de herramientas y utilidades que se integran con nuestros proyectos para facilitarnos el desarrollo backend de nuestras aplicaciones.
Una de las herramientas más conocidas y usada por los desarrolladores móviles es Crashlytics, pero no es la única que debemos de tener en cuenta. En este artículo vamos hablar de Authentication, un servicio de backend que permite la autenticación, registro y todas las utilidades relacionadas con la autenticación de los usuarios. Y Firestore, una base de datos a tiempo real para conectar nuestras aplicaciones a un sistema de persistencia de datos.
Firebase Authentication y Firestore
Firebase Authentication
Muchas apps y webs necesitan un sistema de registro e identificación de usuarios. Authentication nos proporciona un servicio completo integrando con su SDK que nos permitirá implementar registros de usuarios, accesos con diferentes proveedores (email, redes sociales, sms…), seguridad, recuperación de contraseñas, etc.
Firebase Auth se integra con otros servicios de la propia plataforma de firebase y se srive de estándares como OAuth 2.0 y OpenID, de forma que se pueda integrar con un backend personalizado y no tener que depender de otras herramientas de la plataforma.
¿Cuáles son las principales funcionalidades que nos permite Auth?
- FirebaseUI Auth: Proporciona una solución directa de UI con todos los flujos relacionados con la autenticación (email, recuperar contraseña, acceder por redes…)
- SDK Authentication: Autenticación basada en correcto electrónico o proveedores de identidad (Facebook, Google, Apple, Twitter…)
Si deseas conocer toda la información adicional de este servicio de Firebase puedes hacerlo en el siguiente enlace https://firebase.google.com/docs/auth
Firebase Firestore
Firestore es una base de datos NoSQL fléxible, escalable y almacenada en la nube que permite almacenar y sincronizar datos tanto a nivel cliente como servidor.
Al igual que Realtime Database (otra versión anterior de base de datos de Firebase) nos permite mantener sincronizados tus datos a tiempo real y ofrece un soporte de datos sin conexión.
Firestore tiene una integración con otros productos de Firebase y Google Cloud, como Functions o Auth.
Entre sus principales funciones están:
- Flexibilidad: Permite estructuras de datos flexibles y jerárquicas organizando tus datos en colecciones y documentos.
- Consultas expresivas: Podemos recoger conjuntos de datos, documentos o parte de estos, podemos filtrar, ordenar entre otras funciones.
- Tiempo real: Además de poder hacer consultas de forma única, podemos configurar para sincronizar nuestros datos a tiempo real y recibir de forma instantánea cualquier nueva actualización sobre nuestros datos. El ejemplo más claro para esto sería un chat, donde los mensajes se mostrarían de forma inmediata sin necesidad de recargar o hacer ninguna acción.
- Trabajo sin conexión: Mediante la caché que Firestore almacena podemos leer, escuchar y escribir sobre nuestros datos incluso sin conexión, y configurarlo para que cuando se recupere la red nuestros nuevos datos se sincronicen con la nube.
Debemos de tener en cuenta que existe diferencia entre un sistema de base de datos NoSQL y uno SQL, si como desarrolladores/as aterrizamos en este nuevo concepto de base de datos debemos de entender que el sistema de almacenado, de construcción de nuestras colecciones y documentos difiere de cómo lo haríamos en un sistema SQL.
Si deseas conocer toda la información adicional de este servicio de Firebase puedes hacerlo en el siguiente enlace https://firebase.google.com/docs/firestore
Manos a la obra ¿por dónde empezamos?
Después de una breve introducción sobre Firebase Auth y Firestore vamos a mostrar un breve ejemplo de cómo implementar un sistema de login y registro en una aplicación android, y como obtener datos de Firestore.
Crear y configurar el proyecto
Los primeros pasos que vamos a seguir son los de crear el proyecto en Firebase y configurarlo en nuestro proyecto Android.
Los requisitos para estos primeros pasos son:
- Tener una cuenta de gmail
- Crear un proyecto desde 0 en Android Studio
Crear proyecto en Firebase
1. Accedemos a la consola de firebase en https://console.firebase.google.com/
2. Seleccionamos Agregar Proyecto o si es tu primera vez Crear un proyecto
3. En el primer paso seleccionamos un nombre para nuestro proyecto:
4. En el segundo paso habilitamos Google Analytics (no es obligatorio) para poder activar ciertas herramientas como Crashlytics, Test AB, Events, etc .
5. En el tercer paso seleccionamos la región de nuestro proyecto y aceptamos las condiciones y términos de uso:
Agregar Firebase a nuestro proyecto Android
- En la pantalla principal de nuestro proyecto de Firebase seleccionamos el icono de Android para agregar nuestro proyecto Firebase a nuestro proyecto en Android previamente creado:
- El primer paso es agregar nuestro nombre de paquete de proyecto, de forma opcional podemos agregarle un sobrenombre a la aplicación y agregar el certificado de firmas SHA-1 (puede ser editado en la configuración del proyecto) En mi caso solo agregare el nombre del paquete del proyecto:
- Descargamos el archivo de configuración .json y lo movemos al directorio app de nuestro proyecto:
- Agregamos la SDK de Firebase a nuestro proyecto implementando a nivel de gradle el pugin. Primero en el gradle a nivel de proyecto (podemos hacerlo usando DSL o Groovy según tengamos configurado):
Y a nivel de gradle de módulo app:
Sincronizamos y esperamos que se cargue la SDK.
Una vez finalizamos podemos ver que en nuestra consola de proyecto ya tenemos agregado nuestro proyecto Android:
Authentication
Configuración de Auth
Lo primero que tenemos que hacer es activar y configurar en Firebase nuestra herramienta de autenticación, para ellos nos dirigimos a la consola de Firebase y en el menú lateral izquierdo sobre Compilación seleccionamos Authentication:
En la pantalla principal de la herramienta pulsamos en comenzar:
En la pestaña de sign-methods vamos activar el proveedor nativo de email/contraseña que será el que usemos para este ejemplo. Y habilitamos correo y contraseña:
Una vez tenemos este proveedor activo, ya podemos implementar su uso desde nuestra app Android gracias a la SDK de Firebase Authentication, antes de ello podemos navegar y explorar el panel de Authentication y observaremos que tenemos pestañas como:
- Templates: Donde podemos confeccionar los mensajes por defectos de correos, códigos de confirmación, sms, etc…
- Usage: Estadísticas de uso y datos analíticos.
- Settings: Configuración avanzada.
- Users: Lista de user registrados y su información (proveedor de registro, id, fecha…)
Una vez tenemos activado nuestro servicio de Auth en Firebase, vamos a configurar la SDK que nos permitirá conectarnos y hacer uso de todas sus funcoinalidades. Para ello nos vamos a nuestro archivo gradle del módulo app y agregamos la implementación de la SDK:
Sincronizamos y listo. Ya podemos comenzar a trabajar con Auth.
Registro con email y password
Antes de comenzar a trabajar con Authentication necesitamos crear una instancia e inicializar FirebaseAuth:
NOTA: Es recomendable que esta inicialización e instancia se realice en el repositorio ya se mediante inyección de dependencia y en el propio Repositorio.
La SDK de Authentication nos provee de una función que dado un email y contraseña nos lo registra en su sistema de autenticación. Ver documentación:
Podemos observar que esta función recibe un email y password y procesa de forma interna el registro, si se completa nos devuelve una Task que puede ser satisfactoria o no.
Si la tarea finaliza correctamente el usuario se ha registrado con éxito, y si no, podemos capturar la excepción de lo que ha sucedido de la propia task.
Firebase Auth tiene definidas algunas excepciones como usuario que ya existen, contraseña débil, contraseña inválida, etc que nos pueden ayudar a controlar mejor los errores que recibimos de la SDK.
Una vez nos hemos registrado, para comprobar que todo funciona correctamente podemos irnos a nuestro panel de Authentication en la consola de Firebase y en la pestaña Users podremos ver todos los usuarios que están registrados en nuestra app.
Login con email y password
Una vez nos hemos registrado, vamos a ver cómo podemos hacer login, llamaremos a signInWithEmailAndPassword una función que recibide email y password y procesa dentro de los usuarios registrados en nuestro sistemas si este existe:
Al igual que con el caso del registro obtenemos una task cuando la petición se complete, y en el caso de que se complete de forma satisfactoria nos devolverá el objeto currentUser. En el caso de que exista un error podremos tratar la excepción y ver que nos devuelve.
Tanto en el ejemplo de registro como el de login, hemos usado addOnCompleteListener pero además podemos usar también addOnFailureListener de forma complementaria, ya que el error puede venir precedido por problemas de conexión, de tipados, etc.. puedes consultar todos los listener que permite cada función de Authentication para que se adapte a tus necesidades.
Control de login activo
Para conocer cuando el usuario tiene el login activo, porque se logueo de forma correcta podemos hacerlo gracias al currentUser, este siempre que no sea null es que existe una sesión activa de ese usuario. Si manejamos este flujo correctamente podemos implementar que la navegación entre pantallas o la restricción de ciertas partes visuales de la aplicación se realice en función de si el usuario está o no logado:
Cerrar sesión
Si lo que necesitamos es cerrar la sesión, y de tal forma destruir el currentUser podemos hacer uso de signOut():
Firestore
Configuración de Firestore
Al igual que hicimos con Auth, para activar Firestore vamos a la consola de Firebase, y en el panel lateral izquierdo, dentro de compilación seleccionamos Firestore Database:
En la pantalla principal de Firestore, le damos a Crear base de datos:
El primer paso de la configuración de esta herramienta es establecer las reglas de seguridad. Existen reglas de producción y de pruebas, en este caso seleccionaremos las de modo de pruebas que nos dan 30 días de lectura y escritura sin filtro:
Es muy importante no subir a producción NUNCA con el modo de prueba. Las reglas de producción pueden configurarse y son muy flexibles, podemos dar a determinados usuarios solo potestad de escritura, de lectura, por intervalos de tiempo, o inclusive usuarios que solo estén logueados con authentication. Para saber más de las reglas de seguridad de Firebase Firestore puedes consultar el siguiente enlace https://firebase.google.com/docs/firestore/security/get-started
En el paso siguiente, debemos de seleccionar la región de configuración. En nuestro caso eur3 – Europa. Y pulsamos habilitar:
Ya tenemos configurado Firestore, pero ¿cómo creamos una base de datos? Este punto podría dar para un solo artículo, pero como la finalidad de este es hacer una introducción a dicha herramientas haremos una breve demostración de cómo crear nuestra base de datos.
Tenemos que entender que en Firestore trabajaremos con:
- Colecciones: Son un conjunto de documentos
- Documentos: Son un conjunto de datos (puede contener numéricos, texto, arrays, referencias a otros documentos o incluso, de forma más avanzadas otras colecciones)
Si hiciéramos la comparación con un sistema SQL las colecciones serían las tablas, y los documentos las filas. En el ejemplo que veremos tenemos una colección llamada “playas” que contiene una serie de documentos que definen cada playa:
Para confeccionar base de datos en Firestore, al ser estos modelos NoSQL debemos de intentar anidar lo menos posible, y hacer los documentos lo más atómicos que podamos.
Te recomiendo que antes que si quieres confeccionar tus bases de datos con firestore de la forma óptima puedes visitar el siguiente enlace:
https://firebase.google.com/docs/firestore/data-model
Para finalizar, una vez tenemos configurado Firestore, debemos de agregar la implementación en gradle de la SDK para Android, añadiendo a nuestro fichero gradle del módulo de app:
Ya lo tenemos todo configurado y listo para comenzar a trabajar con Firestore.
Obtener documentos de una colección
Para trabajar con Firestore, y al igual que hicimos con Auth, debemos de inicializar una instancia de la SDK:
Una vez tenemos nuestra instancia lista, podemos probar cómo obtener todos los documentos de una colección.
Existen otras muchas formas de lectura, como por ejemplo obtener solo un documento concreto, o documentos de la colección filtrados, etc..
Puedes ojear todos los casos en la documentación oficial: https://firebase.google.com/docs/firestore/query-data/get-data
En este caso vamos a llamar a collection y como parámetro debemos de pasarle el nombre que le dimos a nuestra colección al crearla.
Usamos get() para obtener todos los documentos de dicha colección, y sus correspondientes callback tanto para cuando se realiza la consulta de forma satisfactoria como para cuando falla:
Como podemos observar cuando el resultado es satisfactorio nos devuelve en result, que es un DocumentSnapshot pero lo más normal es que necesitemos convertir dicho objeto en uno personalizado. Para ello creamos una Data Class con los mismos parámetros que tenemos en nuestros documentos de la base de datos. Y podemos hacer la conversión de la siguiente forma:
De esta forma podemos obtener cada documento que contiene nuestra colección, convertirlos a nuestros propios objetos y trabajar con ellos, ya sea agregándoles a una lista para mostrarlos o lo que necesitemos:
Obtener documentos de una colección a tiempo real
Una peculiaridad que Firestore es que su SDK nos provee de un sistema de escucha a tiempo real, es decir, hacemos la petición a una colección y esta nos devuelve los documentos, tal y como vimos en el punto anterior, pero en este caso cualquier cambio sobre cualquier documento de la colección será informado a tiempo real de forma que el usuario no tenga que hacer ningún refresco de UI ni llamadas a los servicios para obtener dichos cambios. El ejemplo más claro de esto sería un chat, donde en el momento que recibes un mensaje se carga automáticamente sin necesidad de que el usuario interactúe con la aplicación:
Para hacer peticiones de tiempo real debemos de usar el callback addSnapShotListener y dentro del mismo condicionar si existe algún error y si se ha recibido algún cambio.
NOTA: Debemos de tener en cuenta que el uso de actualizaciones a tiempo real puede ser peligroso si no controlamos bien el volumen de datos que se van a tratar y si lo hacemos de forma correcta. Recordemos que FIrebase es gratuito hasta cierto número de llamadas de lectura y escritura.
Insertar nuevo documento
Ahora veamos cómo hacemos si queremos añadir un nuevo documento a una colección. Para ello usaremos la función set () que recibe como parámetro el objeto del documento que queremos insertar:
Debemos tener en cuenta varios puntos. Primero, como podemos observar en este caso al documento le estamos pasando por parámetro una id: “LA”, es importante entender que esa id debe de ser única por cada documento ya que la función set en el caso de recibir un id que ya existe ACTUALIZARÁ el documento, y esto puede llegar a ser peligroso para nuestros datos si no lo controlamos bien. En mi caso personal suelo generar alguna id random y usarla como id del documento, y a su vez en el propio documento crear un atributo con esa misma id.
Otro detalle para tener en cuenta, hemos comentado que set () recibe el objeto que queremos insertar como documento, pero si los datos que queremos insertar no los tenemos como objeto podemos usar un Hashmap de forma que cada valor se asocia con el atributo del documento:
De este modo podemos crear nuevos documentos para nuestras colecciones.
Actualizar documento
En el punto anterior comentamos que si hacemos uso del set () y pasamos la documento su id existente, este en vez insertar actualizará el documento con los nuevos datos que el objeto contenga. Esto podría servir como modo para actualizar un documento, pero ¿y si solo queremos actualizar un par de cambios del documento? En este caso, aunque podríamos enviar el objeto completo, pero solo con los atributos nuevos que queremos editar, pero es más seguro usar update ()
Esta función recibe un map, donde se especifican que campos y que valores son los que queremos modificar:
Esta forma de actualizar es más segura, ya que solo se modificarán los atributos que nosotros determinemos dentro del documento, en el caso de querer modificar todo el documento podríamos usar set ().
Eliminar documento
Si lo que necesitamos es eliminar un documento de nuestra colección podemos hacerlo usando delete () y borrará el documento asociado a la id.
Como en todas las funciones de la SDK tenemos el callback tanto de si el borrado se hace de forma satisfactoria como si no.
Conclusiones
Como habéis podido apreciar Firebase es una plataforma que nos ofrece muchas herramientas y utilidades que podemos integrar en nuestras aplicaciones Android de forma muy sencilla.
En este artículo hemos visto Auth y Firestore como opciones para implementar un sistema de autenticación sólido, seguro y completo, y un sistema de base de datos que nos permite la persistencia de lo mismo, su acceso y tratamiento.
Llegados a este punto puede que nos surjan algunas dudas como ¿para qué nos puede servir Auth y Firestore?, ¿Cuáles son los costes?, ¿Cuáles son los inconvenientes?, ¿Cómo lo integramos en proyectos empresariales?
¿Para qué nos puede servir Auth y Firestore?
En pequeños proyectos de presupuestos reducidos, o proyectos personales. Auth y Firestore nos proveen de los servicios de un backend y esto, aunque la plataforma tiene su coste, a grandes rasgos nos ahorra tiempo e integración de un sistema de backend completo. Un cliente cuyo presupuesto esté limitado, o proyectos personales donde quieras conectar diferentes plataformas con un mismo backend, son escenarios perfectos para el uso de estas herramientas.
¿Costes?
Firebase tiene dos planes, uno gratuito y limitado (spark) y otro de pago por uso (blaze)
Algunos de los servicios de Firebase son totalmente gratuitos, como por ejemplo Analytics, Test AB, Crashlytics, etc
Por ejemplo, en cuanto a Firestore, en el plan Spark tenemos 50.000 lecturas por día, y en el plan Blaze a partir de esas 50.000 lecturas pasaremos a 100.000 documentos a 0.06 dólares.
Si quieres ver la lista de precios, servicios y el simulador de presupuestos puedes hacerlo en https://firebase.google.com/pricing
¿Cuáles son los inconvenientes?
Haciendo referencia a la cuestión anterior, tener un servicio de pago por uso puede ser peligroso si no preparamos nuestra app para posibles sobrecargas de tráfico o crecimiento de la misma, hacer un buen uso de la SDK, cachear datos, evitar llamadas a los servicios salvo que sean necesarias son buenas prácticas que nos pueden ahorrar algún que otro susto en nuestra factura.
Otro inconveniente que suele darse en aplicaciones que usan Firestore sobre todo es que la misma crezca mucho, tanto en complejidad como en lógica y necesitemos un sistema de base de datos más potente, esto supondría una migración total de nuestro backend.
¿Cómo integrarlo en proyectos de empresa?
En la mayoría de los casos, siendo realistas, como desarrolladores Android no tenemos capacidad de decisión sobre material de backend, aquí son otros departamentos y el propio cliente quien define tecnologías en base a sus necesidades. Eso no nos exime de conocer la tecnología y poder ofrecerlas para ciertas funcionalidades concretas en el desarrollo de alguna tarea, por ejemplo, en mi caso real, integramos Firestore para hacer llamadas a servicios y poder escuchar cambios en tiempo real y solo una parte de la lógica de la aplicación estaba en Firestore, todo lo demás seguía en un backend ajeno.
Conocer la tecnología y su alcance nos puede ayudar a defender su uso en caso de tener tareas o integraciones concretas donde estos servicios puedan ayudarnos.