Una vez más aquí. Hoy vengo a dejar un artículo sobre una aplicación que me hice para mi mismo. El caso es que hace unas semanas, debido a una pequeña obra que hice en mi casa, necesité un nivel, para dejar unas estanterías rectas. El caso es que el día que lo necesité, no tenía un nivel funcional a mano. Y esto fue lo que me dio la idea de utilizar el teléfono móvil para poder tener un nivel siempre a mano. Días después me puse a escribir código, retomando contacto con un IDE que hacía mucho que no usaba, Android Studio. El caso es que poco a poco pude compilar con éxito est app para Android, a la que he llamado NivelAzo. Y esta aplicación ahora se quedará en mi teléfono para el día que quizás nunca más llegue …
En el mundo del desarrollo de aplicaciones móviles, personalmente creo que quedan pocas cosas útiles que desarrollar. Por este motivo, a menudo los proyectos más sencillos suelen resultar los más útiles. A continuación vamos a echar un vistazo al desarrollo que hice durante mis ratos libres durante una semana de esta herramienta que puede resultar útil en momentos puntuales. Se trata de una aplicación de nivel de burbuja para Android.
¿Qué es la App de nivel «NivelAzo»?
Esta aplicación de nivel, es una herramienta digital simple. Nació pensando en transformar tu smartphone en un nivel de burbuja funcional. Para ello se utilizan los sensores integrados en el dispositivo, concretamente el acelerómetro. La app muestra una interfaz gráfica con una bola que se desplaza para indicar la inclinación de una superficie.
Esta App se ha desarrollada en Kotlin para la plataforma Android. El desarrollo de ella me ha permitido retomar algo que tenía muy olvidado, como es el desarrollo de Apps. En este caso, además vamos a interactuar con los sensores del hardware, gestionando la orientación de la pantalla. Todo ello mediante una interfaz de usuario reactiva.
¿Cómo funciona el acelerómetro de tu smartphone?
Como decía, el corazón de esta aplicación es el acelerómetro del smartphone. Este sensor, presente en la mayoría de los smartphones modernos, mide la aceleración a la que está sometido el dispositivo. Cuando el teléfono está en reposo sobre una superficie, la única fuerza de aceleración que detecta es la de la gravedad terrestre, que siempre apunta hacia el centro de la Tierra.
La aplicación aprovecha esta constante física. Al leer los valores del acelerómetro en los ejes X, Y y Z, puede determinar la orientación del dispositivo con respecto al vector de la gravedad.
- Eje Y (vertical del teléfono): Mide la inclinación hacia adelante y hacia atrás.
- Eje X (horizontal del teléfono): Mide la inclinación lateral.
- Eje Z (perpendicular a la pantalla): Mide si el dispositivo está boca arriba o boca abajo.
Traduciendo estos valores numéricos a una posición en la pantalla, la aplicación puede simular el comportamiento de una burbuja en un nivel físico. Cuando el dispositivo está perfectamente nivelado, la «bola» se sitúa en el centro.
Características principales de la aplicación
Aunque su concepto es simple, la app «NivelAzo» incorpora varias características clave para garantizar su funcionalidad y usabilidad:
- Detección de inclinación en tiempo real: Utiliza el SensorManager de Android para recibir actualizaciones constantes del acelerómetro, proporcionando una respuesta visual inmediata.
- Interfaz gráfica intuitiva: Una bola que se mueve dentro de un área delimitada sirve como indicador visual. Su posición central indica una superficie nivelada.
- Soporte completo de orientación: La aplicación está diseñada para funcionar tanto en modo vertical (portrait) como horizontal (landscape), adaptándose a cómo el usuario sostiene el dispositivo.
- Calibración sencilla: Incluye una función para calibrar el «punto cero», permitiendo al usuario ajustar la referencia de nivelación según sus necesidades.
Análisis del código fuente. Un vistazo bajo el capó
Para entender realmente cómo funciona la aplicación, es fundamental analizar su código. Nos centraremos en dos áreas críticas: la configuración en AndroidManifest.xml y la lógica de la actividad principal.
El Manifiesto de la aplicación: AndroidManifest.xml
El archivo de manifiest es la carta de presentación de cualquier aplicación de Android. Aquí se declaran sus componentes, permisos y requisitos de hardware.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" /> <application ...> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:configChanges="orientation|screenSize|screenLayout" android:screenOrientation="fullSensor" android:theme="@style/Theme.Nivel"> ... </activity> </application> </manifest>
Analicemos las líneas más importantes:
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
Esta línea es crucial. Le dice a Google Play Store que la aplicación requiere un acelerómetro para funcionar. Los dispositivos que no cuenten con este sensor no podrán instalarla, evitando así malas experiencias de usuario.
android:screenOrientation=»fullSensor»: Esta propiedad le indica al sistema operativo que la orientación de la actividad debe ser determinada por el sensor de orientación física. Permite que la app rote en las cuatro direcciones (vertical, vertical invertido, horizontal a la izquierda y horizontal a la derecha).
android:configChanges=»orientation|screenSize|screenLayout»: Por defecto, Android destruye y vuelve a crear una actividad cada vez que cambia la orientación de la pantalla. Esto provocaría un parpadeo y la pérdida del estado actual en nuestra app. Con esta línea, le decimos al sistema: «No te preocupes, yo me encargaré manualmente de los cambios de orientación, tamaño y diseño de pantalla sin necesidad de reiniciar la actividad». Esto es vital para una experiencia fluida.
La lógica principal y el sensorManager
Aunque no mostremos el archivo Kotlin completo, la lógica principal reside en MainActivity. El flujo de trabajo es el siguiente:
- Obtener el SensorManager: En el método onCreate(), la actividad obtiene una instancia del servicio de sensores del sistema.
- Registrar un Listener: Se registra un SensorEventListener para el Sensor.TYPE_ACCELEROMETER. Esto le dice a Android: «Avísame cada vez que haya una nueva lectura del acelerómetro».
- Procesar los datos en onSensorChanged: Este es el método que se ejecuta cada vez que el sensor reporta nuevos valores.
- Recibe un objeto SensorEvent que contiene un array de floats (event.values) con las lecturas de los ejes X, Y y Z.
- Actualizar la UI: La lógica de la aplicación toma estos valores, los normaliza y calcula la nueva posición (coordenadas X e Y) de la bola en la pantalla. Finalmente, invalida la vista para que se redibuje con la bola en su nueva posición.
Usabilidad y experiencia de usuario
Durante las pruebas, se detectó un problema de usabilidad significativo: la nivelación no funciona correctamente en todas las orientaciones horizontales. Cuando el teléfono se coloca en modo landscape, la bola tiende a quedarse en un lado de la pantalla, y solo marca el nivel correctamente si la pantalla mira hacia arriba.
Este es un problema clásico en aplicaciones que dependen de sensores. El sistema de coordenadas del sensor es fijo con respecto al dispositivo, pero el sistema de coordenadas de la pantalla cambia cuando el usuario rota el teléfono. Por ejemplo, lo que era el eje X para el sensor puede convertirse en el eje Y para la pantalla.
Hacia una solución. Remapeando coordenadas
La solución a este desafío pasa por detectar la rotación actual de la pantalla y remapear los ejes del sensor para que coincidan con los de la pantalla. Android proporciona las herramientas para ello:
- Display.getRotation(): Este método permite obtener la rotación actual de la pantalla (0, 90, 180 o 270 grados).
- SensorManager.remapCoordinateSystem(): Esta potente función permite transformar una matriz de rotación (que representa los valores del sensor) de un sistema de coordenadas a otro.
- La implementación correcta implicaría, dentro del onSensorChanged, comprobar la rotación actual y, si no es la orientación natural, usar remapCoordinateSystem para obtener los valores de aceleración correctos para la orientación actual de la pantalla antes de calcular la posición de la bola.
Cómo compilar y ejecutar el proyecto
Si eres un desarrollador y quieres experimentar con este código, puedes hacerlo siguiendo estos pasos:
- Clona el repositorio: Obtén el código fuente desde su repositorio de GitHub.
- Abre en Android Studio: Importa el proyecto en Android Studio. El IDE se encargará de sincronizar las dependencias de Gradle automáticamente.
- Compila y ejecuta: Conecta un dispositivo físico (recomendado para probar sensores reales) o usa un emulador y pulsa el botón «Run».
Conclusión y próximos pasos
Esta aplicación de nivel es un ejemplo perfecto de cómo una idea simple puede convertirse en un proyecto de aprendizaje. Nos obliga a interactuar con el hardware del dispositivo, a gestionar el ciclo de vida de las actividades de forma avanzada y a resolver problemas complejos de transformación de coordenadas.
Los próximos pasos para este proyecto son claros: implementar la lógica de remapeo de coordenadas para solucionar el error de orientación y añadir pruebas instrumentadas que simulen diferentes rotaciones y valores del sensor para garantizar que la solución es robusta.
Como comenté al comienzo de este post, el propósito de esta aplicación es ofrecer una solución rápida y accesible para tareas cotidianas que requieren nivelación, desde colgar un cuadro hasta ajustar una estantería.
No lo he buscado, pero me imagino que en internet, habrá un buen puñado de aplicación que harán esto mismo .. y quizás de una mejor forma. Pero esta es la mía. Se puede descargar directamente el archivo .apk desde la página de lanzamientos del proyecto. Y si quieres ver el código fuente o descargarlo, puedes hacerlo desde el repositorio en el que he alojado este proyecto.