TransitOS — Transporte Público Libre para Valencia
Un cliente de código abierto para transporte público en Android, empezando con Metrovalencia (FGV). Llegadas en vivo, planificador de viajes y un mapa de red interactivo — sin anuncios, sin rastreo, y una arquitectura de proveedores para añadir cualquier operador sin tocar la app.
TransitOS es un cliente de código abierto para transporte público en Android. Empieza con Metrovalencia (FGV) y está diseñado para crecer hasta una plataforma multi-operador: autobuses EMT, Renfe Cercanías y más. Es libre, no está financiado por nadie y respeta tu privacidad: sin anuncios, sin rastreo, sin analíticas, nunca.
Por qué existe
Las apps oficiales de transporte de Valencia van con anuncios, exigen cuenta y están cargadas de analíticas. Quieres saber cuándo sale el próximo tren y te encuentras un banner, un muro de inicio de sesión y una docena de rastreadores. Esa es la norma en el software de transporte público, y no tiene por qué ser así.
TransitOS es la versión en la que la app simplemente te dice la próxima llegada. Es código abierto bajo AGPL-3.0, no guarda nada que no necesite, y el mapa de red se renderiza sobre tiles de OpenStreetMap, que respetan la privacidad. El enfoque de privacidad es estructural: no hay ningún backend que registre tus búsquedas, porque la app habla directamente con los datos del operador.
La arquitectura de proveedores
La decisión de ingeniería interesante es el modelo de proveedores. Cada operador de transporte expone los datos de forma distinta: endpoints distintos, esquemas distintos, idiosincrasias distintas. La trampa es dejar que las rarezas de un operador se filtren al resto de la app.
TransitOS lo resuelve con una arquitectura limpia y estricta, y una regla de dependencia unidireccional:
Presentación (app, feature-*, core-ui, core-design)
| depende de
v
Dominio (core) -> modelos, contratos de repositorio, AppResult
| implementado por
v
Datos (provider-*, core-network, core-data) -> impls de repositorio, Ktor, DataStore
La capa de dominio define un único contrato TransitRepository: las operaciones que cualquier sistema de transporte debe soportar (llegadas en vivo, planificación de viajes, búsqueda de estaciones). Cada operador vive en su propio módulo — :provider-metrovalencia implementa ese contrato contra los datos de FGV. La app depende solo del contrato; nunca sabe con qué operador está hablando.
Añadir un operador nuevo significa añadir un módulo. ¿Quieres los autobuses EMT? Crea :provider-emt, implementa TransitRepository, registra su módulo de Koin en :app. Nada más cambia en la app — ni la UI, ni el planificador, ni el mapa. Esa separación es lo que hace realista la ambición multi-ciudad en lugar de un reconstrucción cada vez.
Cómo funciona
Llegadas en vivo. Cada estación y línea consulta al proveedor los tiempos estimados en tiempo real. Los resultados vuelven mediante un AppResult tipado, de modo que la UI distingue carga, datos y error sin un montón de booleanos nulables.
Planificador de viajes. Múltiples alternativas de viaje con modos de hora de salida o de llegada y un margen de transborno configurable. El planificador funciona contra el contrato del proveedor, así que cada operador obtiene planificación gratis en cuanto implementa las llegadas.
Mapa de red. Todas las estaciones, los colores oficiales de las líneas y las polilíneas renderizadas sobre tiles de OpenStreetMap mediante osmdroid. Funciona como un índice visual de toda la red: toca una estación, mira sus líneas y próximas llegadas.
Rutas guardadas. Etiquetas personalizadas (“Casa”, “Trabajo”) para acceder con un toque a los viajes que haces de verdad. Se guardan en local con DataStore.
Temas e i18n. Sistema / Claro / Oscuro / AMOLED negro puro, además de inglés, español y valenciano. Todo controlable por el usuario, sin viaje al servidor.
Lo destacable
El límite del proveedor es todo el proyecto. La mayoría de apps de transporte se construyen como un monolito contra la API de un operador. Separar el contrato de la implementación hace que la app sea reutilizable de verdad: la misma UI y el mismo planificador sirven para Valencia hoy y para cualquier otra ciudad mañana, sin duplicación.
La arquitectura limpia y estricta merece la pena. La regla de dependencia unidireccional (presentación → dominio → datos) parece sobrecarga en el papel. En la práctica es lo que hace posible el modelo de proveedores: nada en la UI sabe nada de FGV, así que cambiar la fuente de datos es un cambio de configuración, no una refactorización.
Privacidad como arquitectura, no como ajuste. No hay ningún SDK de analítica que desactivar, porque nunca se añadió. La app habla con el operador; el mapa habla con OSM; nada habla con una empresa de publicidad.
Stack
- Kotlin 2.0.21 con Coroutines y Flow
- Jetpack Compose (gestionado por BOM), Material 3, color dinámico
- Ktor 3 para red · Koin 4 para inyección de dependencias
- DataStore para preferencias · osmdroid para el mapa de red
- Gradle Version Catalog (
libs.versions.toml) como única fuente de verdad - minSdk 26 · target / compile SDK 35
Estado
Activa y usable. Metrovalencia está completamente cubierta: llegadas en vivo, planificador de viajes, mapa de red, rutas guardadas y búsqueda. Hay APKs precompiladas en la página de releases. Todavía no está en Google Play; instala el APK manualmente o compílalo tú mismo.
Código: github.com/IgnacioLD/TransitOS.