El mapa de Google, mis radares, una sola app
Quería una sola cosa en la pantalla del coche. El mapa de Google, el tráfico de Google y las indicaciones giro a giro de Google, con mis propios datos de radares encima, avisándome solo de los radares que de verdad apuntan a mi lado de la carretera.
No encontré nada en Android Auto que hiciera eso. Google Maps tiene el mapa y las rutas, pero no hay manera de cargarle tu propia base de datos de radares. Así que lo estoy construyendo yo.
Se llama AutoNavAlerts. Es una app de navegación para Android Auto construida sobre el Navigation SDK de Google, con un sistema de avisos de radares y puntos de interés escrito encima. La primera fuente de radares es PocketGPSWorld, con mi propia suscripción de pago. El código es público bajo la Apache License 2.01 en github.com/damo2929/AutoNavAlerts.
Esta es la primera parte de una serie. Cuenta lo que hace la app, lo que Google deja y no deja hacer a una app de terceros en la pantalla de un coche, y cómo se construyó, porque casi cada línea la escribió Claude, el modelo de IA de Anthropic, conmigo poniendo las reglas, probándolo y respondiendo del resultado. Esa última parte es una historia por sí sola.
Es la versión 0.1.0. Se instala a mano, no está en la Play Store, y ha hecho un solo viaje real. Léelo como un diario de obra, no como un lanzamiento.
Lo que hace hoy
Esto es lo que hay en la versión de prueba, y para qué sirve cada parte:
| Área | Qué hace |
|---|---|
| Navegación | Mapa de Google con tráfico, búsqueda de lugares, vista previa de la ruta con la hora de llegada, giro a giro en la pantalla del coche, la barra lateral y la pantalla del conductor |
| Ir a un contacto | Di o escribe un nombre y las direcciones guardadas del contacto salen encima de los resultados de Places. Solo la dirección que eliges va a Google |
| Convive con tu música | Solo plantillas de navegación, así que la música conserva su tarjeta en pantalla dividida. La voz de los avisos baja la música, nunca la pausa |
| Avisos de radares | Tres fases por radar, solo para radares que miran en tu sentido de la marcha, en la carretera por la que vas |
| Tramos de velocidad media | Un tramo empieza solo cuando hay otro radar con el mismo límite por delante, y termina en el último radar |
| Panel de velocidad | Tu velocidad y el límite de la vía, siempre uno al lado del otro, abajo a la derecha |
| Límites sin conexión | Una descarga de los límites de OpenStreetMap para el Reino Unido: 1.326.619 vías en 29 MB en el teléfono. Nada se consulta mientras conduces |
| Rutas para coche eléctrico | La ruta más rápida y la ruta de bajo consumo de Google una al lado de la otra, y eliges tú |
| Datos de radares | Tu propia suscripción a PocketGPSWorld, comprobada a diario, nunca cambiada mientras navegas. O importa archivos iGO, KML, GPX, OV2 o CSV |
| Avisar de un radar | Un toque en el coche guarda posición, rumbo y límite, con un comentario hablado opcional. Revisar y enviar se hace en el teléfono, nunca conduciendo |
Los avisos de radares son la razón de ser de la app, así que se llevan la siguiente sección.
Un radar solo cuenta si te mira a ti
Un aviso de radar que salta por la otra calzada es peor que no tener aviso. Te enseña a ignorarlo. Así que la primera regla firme del diseño es que un radar avisa solo cuando mira en tu sentido de la marcha, y esa regla no se afloja nunca, no se esquiva con un valor por defecto y no se abandona cuando los datos son incómodos.
El motor se ejecuta con cada posición, hasta diez por segundo. Para cada radar cercano hace cuatro preguntas, por orden:
| Comprobación | Pasa cuando | Por qué está ahí |
|---|---|---|
| Bastante cerca | dentro de la distancia de disparo más 200 m, con un tope de 3 km | ningún trabajo gastado en radares a kilómetros |
| Por delante | el rumbo hacia el radar a menos de 45° de tu rumbo | un radar que has dejado atrás es historia |
| Mirando hacia ti | el rumbo del radar a menos de 45° de tu rumbo, o del rumbo hacia el radar en una curva | la otra calzada se queda callada |
| En tu carretera | a menos de 50 m de la ruta por delante, o un pasillo de 40 m que se ensancha con la distancia en conducción libre | la carretera paralela se queda callada |
Los 45° no son generosos. Los archivos TomTom de PocketGPSWorld dan la dirección de un radar en ocho puntos cardinales, así que 22,5° se los comen los datos antes que nada. Un rumbo de GPS cuesta unos grados más, y la curva de la carretera unos cuantos más. Por eso no se deja que nada más se coma ese margen.
Un radar que no pasa la comprobación de dirección se sigue dibujando en el mapa, atenuado, con una flecha que indica hacia dónde mira. Lo puedes ver. Simplemente no te habla.
Las fases van por tiempo, no por distancias fijas. El primer aviso llega a 15 segundos a tu velocidad actual y el segundo a la mitad, los dos con un mínimo para que nunca se echen encima del tercero. El tercero es fijo a 100 yardas, y es obligatorio siempre que el sonido está activado. La distancia de disparo solo crece durante una aproximación, así que frenar fuerte no acorta el aviso que ya te tocaba.
Lo que Google deja hacer a una app en la pantalla del coche
Aquí es donde se pone interesante, porque una app de terceros en Android Auto no es Google Maps. Funciona dentro de las reglas de la Car App Library de Android Auto, que da a las apps «a set of visual templates approved for driver safety»2, y dentro de lo que el Navigation SDK decide exponer.
Tres huecos le dieron forma a la app más que nada de lo que yo decidí construir:
| Qué | Google Maps en el coche | Una app sobre el Navigation SDK |
|---|---|---|
| Avisar de un accidente, policía u obras | incluido | no se ofrece. La propia documentación de Google: «real-time disruptions are not available on Android Auto»3 |
| El límite de velocidad de la vía | se muestra | solo el porcentaje que lo superas, y solo mientras vas por encima4 |
| Toque en los propios controles del mapa del SDK | n/a | ninguno. Android Auto «limits screen surface interaction to a series of SurfaceCallback methods»2 |
Pongamos el límite de velocidad. Google lo sabe. Google le dice a una app cuánto lo superas, como porcentaje y nivel de gravedad, y nada en absoluto mientras vas por debajo. ¿Puedo preguntar por qué a un conductor se le permite conocer el límite solo cuando ya lo está incumpliendo? No me van a contestar, así que la app le da la vuelta. Mientras vas por encima, calcula el límite a partir de tu velocidad y el porcentaje. Por debajo, usa el radar al que te acercas, luego la descarga de OpenStreetMap, y muestra un guion en vez de nada cuando no tiene ningún límite.
Avisar de incidencias tiene la misma forma. Las API para hacerlo existen en la vista de navegación del teléfono y no en la del coche. Alguien ya se lo ha pedido a Google5, y sigue abierto. La app busca esas API en tiempo de ejecución, así que si un SDK posterior las añade, el botón de aviso de Google aparece sin cambiar mi código. Un trabajo de GitHub Actions lo comprueba cada trimestre y abre una incidencia el día que ocurra.
La regla del toque me pilló de verdad. El mapa del coche del SDK dibuja su propia tarjeta de llegada, cabecera, botón de recentrar, velocímetro y barra de viaje. Ninguno admite un toque, porque ningún toque llega a la vista del SDK. Parecen botones y no hacen nada. Así que están todos desactivados, y la app dibuja sus propios controles donde un toque sí llega.
Trae tu propia clave, trae tus propios datos
Dos decisiones mantienen esta app honrada en cuanto a dinero y licencias, y las dos son deliberadas.
No hay clave de Maps incluida. Google Maps Platform necesita «a billing-enabled Cloud project»6, y el Navigation SDK necesita un proyecto con él habilitado7. Si yo incluyera una clave, todo lo que condujera cualquiera se me facturaría a mí, o la clave se filtraría y se me facturaría a mí igualmente. Así que cada usuario trae su propia clave, en su propia cuenta de Google Cloud. La app del teléfono puede crear una con tu propia cuenta de Google, o puedes pegarla. Se guarda cifrada en el teléfono. No hay alternativa de ningún tipo, y la app no hace ni una sola llamada al SDK hasta que tu clave está puesta.
No hay datos de radares en la app. PocketGPSWorld licencia su base de datos para uso individual, marca cada descarga con el socio que la hace, y prohíbe ponerla en cualquier sitio donde pueda llegar alguien que no sea el comprador. Así que la app nunca la incluye, nunca la aloja y nunca la sincroniza entre teléfonos. Entras con tu propia suscripción, y el teléfono descarga tu propia copia marcada a un almacenamiento privado excluido de las copias de seguridad. En el banco de pruebas eran 19.826 radares en 33 conjuntos, un conjunto por archivo, nunca fusionados.
La sincronización automática es educada al respecto. Lee el feed RSS público de PocketGPSWorld una vez al día8 y solo inicia sesión cuando hay una versión nueva. Nunca cambia los radares mientras navegas.
Hay una cláusula de su licencia que esto no deja del todo resuelta, la de incorporar los datos a una aplicación. Para mi propio uso lo acepto. Antes de que la app llegue a nadie más, PocketGPSWorld recibe un correo preguntándolo.
Dos días, 87 commits, y primero un documento de diseño
Ahora la parte que va a dar que hablar. Yo no tecleé este código. Lo hizo Claude, a través de Claude Code, con dos modelos, Claude Fable y Claude Opus. Yo escribí los requisitos, tomé cada decisión, llevé el banco de pruebas, conduje el coche y revisé lo que volvía. Cada commit con cambios escritos por IA lleva una línea final que lo dice, y el README también.
Estas son las cifras, leídas del repositorio:
| Medida | Valor |
|---|---|
| Commits | 87, desde las 22:10 del 11 de octubre hasta las 12:44 del 13 de octubre de 2026 |
| Commits con una línea de coautor de Claude | 83 (56 Fable, 27 Opus) |
| Kotlin en la app y su biblioteca central | 15.334 líneas |
| Pruebas unitarias | 211, en 3.464 líneas |
DESIGN.md, la especificación | 1.763 líneas, escritas antes de cualquier código |
El documento de diseño fue primero, y es lo más útil que le puedo decir a cualquiera que haga esto. Su primera línea dice que no se escribe código hasta que esté aprobado, y que cualquier cambio posterior se hace ahí primero. Cada clase tiene su tarea escrita al lado. Cada umbral tiene un motivo. Cada regla que puse está marcada como mía, con la fecha.
Eso importa porque un modelo olvida. Una sesión larga se resume, y el resumen se queda con la idea general y tira el detalle, y el detalle es donde están los fallos. El propio AGENTS.md del repositorio lo dice claro: no te fíes de un resumen de estos archivos de memoria ni de una sesión anterior. El agente vuelve al documento. Cada vez.
Además, dos agentes trabajaron en paralelo en la segunda fase, uno en la guía de ruta, el mapa y las pantallas, el otro en la ubicación, los avisos, la voz y los marcadores del mapa. Cada uno era dueño de una lista escrita de archivos, y las interfaces entre ellos se fijaron de antemano: añadir, no renombrar. Se fusionaron sin problemas porque la frontera se decidió antes de que ninguno empezara, no se descubrió después.
Cada regla firme salió de algo que vi
El diseño tiene una lista de reglas firmes, y ninguna salió de una pizarra. Cada una salió de ver la cosa funcionar en la Desktop Head Unit9, el emulador de pantalla de coche de Google en el PC, o en el coche, y verla hacer algo mal.
| Regla firme | Lo que vi que la convirtió en regla |
|---|---|
| Un radar avisa solo cuando mira hacia ti | los avisos por la otra calzada son ruido que te enseña a ignorar los avisos |
| Nada en la pantalla del coche que no funcione | dos botones de parar en pantalla, uno de ellos muerto |
| Ninguna función mostrada dos veces | esa misma pareja, más dos botones de recentrar, dos indicadores de velocidad |
| Una sola cancelación, la de Google | la tarjeta de la esquina con la X es la propia de Android Auto, dibujada a partir del viaje que publica la app, así que el botón de parar de la app se fue |
| Nada que tiemble en la pantalla del coche | la pantalla Más temblando con el coche aparcado, porque reenviaba una pantalla idéntica cada segundo y Android Auto anima cada refresco |
| Todos los botones a la derecha | los botones del mapa estaban arriba a la izquierda hasta que la pantalla del coche informaba de su tamaño; ahora una columna por el borde derecho desde el principio, nada nuestro a la izquierda |
| Nunca una clave de Maps incluida | lo que conduce cada uno no se le factura a nadie más |
El temblor es mi favorito, porque es muy pequeño y se habría colado. Una fila de GPS en directo se actualizaba una vez por segundo. Cada actualización reenviaba la pantalla entera, sin cambios, y el host la animaba, así que todas las filas de debajo bailaban con el coche parado. El arreglo es una comparación: redibujar solo cuando una línea ha cambiado. La regla es más grande que el arreglo. Una pantalla que está quieta tiene que verse quieta, y se comprueba con una ráfaga de capturas que tienen que ser idénticas.
Ese es el trabajo de verdad cuando una IA escribe el código. No se cansa y no le importa reescribir, pero no puede ver la pantalla del coche. Tú sí. Escribir lo que viste como una regla, con la fecha, es lo que impide que vuelva tres sesiones después.
Lo que el código hizo mal, y cómo se pilló
Bastante. Nada exótico, y cada fallo se pilló ejecutándolo, no leyéndolo:
| Fallo | Qué hacía | Cómo se pilló |
|---|---|---|
| Ruta asignada al tramo equivocado | La ruta de Google desde un coche aparcado iba al norte, cambiaba de sentido en una rotonda y volvía al sur por la misma carretera. El emparejador fijó el coche al tramo hacia el norte a 10 m, así que cada radar hacia el sur estaba «fuera de la carretera» por más de un kilómetro. Nada avisó | un viaje guionizado en el banco; el registro de avisos decía offRoad lateral=1204 para cada radar |
| Vigilante de voz demasiado corto | permitía 1,5 s más 70 ms por carácter. Los números tardan más en decirse, así que cada aviso de segunda fase se cortaba a mitad de frase | los registros de voz de una pasada en el banco |
| Un límite de frecuencia en el motor | una ventana de tres segundos hacía que, con dos radares en un mismo cruce, uno se perdiera para siempre | rastrear los avisos que se quedaron callados en el primer viaje real |
| Un rumbo obsoleto | el emulador da un rumbo de 0° hagas lo que hagas, así que en una carretera hacia el sur cada radar fallaba la comprobación de dirección | una pasada simulada por la A61 |
| Cambios de límite dichos como avisos de radar | un cambio de límite por delante se ponía en cola como aviso de radar de primera fase | el registro de voz en el banco |
El segundo merece una pausa. Cada prueba individual pasaba. El código era correcto según su propia medida. Simplemente tenía un tiempo límite elegido por alguien que nunca había oído a un teléfono leer una distancia en voz alta. La prueba que pilla eso es una voz de verdad, cronometrada, en una pasada de verdad.
El primer viaje real
El 12 de octubre puse una versión de lanzamiento en mi teléfono y la saqué en el XPENG G6 con Android Auto inalámbrico. Dos cosas salieron mal. Una ruta fijada con el coche aparcado se borraba sola a los pocos segundos de arrancar. Y algunos avisos se decían y otros no, sin ningún patrón que yo pudiera ver.
Luego el problema peor. No quedaba nada que leer. ColorOS, en mi teléfono, tira las líneas de registro de la app, así que el viaje no dejó ninguna prueba. ¿Fue la app, el SDK de Google o el propio Android Auto? No podía decirlo.
Así que el arreglo del primer viaje no fue un cambio de código. Fueron pruebas. La app ahora escribe dos registros en el teléfono todo el tiempo, uno para las rutas y el mapa y otro para cada decisión de aviso, en lotes de 15 segundos, más un grabador de viaje opcional que guarda cada posición para poder repetir un viaje en el banco. Luego se arreglaron las suposiciones, cada una escrita para hacer menos y dejar constancia de lo que hizo. Cada forma en que puede terminar la guía de ruta registra ahora quién la terminó.
En el banco desde entonces, Android Auto llamó a parar una vez, a los 2 minutos 35 segundos de un viaje guiado. Yo estaba haciendo clic por la Desktop Head Unit en ese momento, así que lo más probable es que fuera la X de su propia tarjeta. No ha pasado sin nadie tocando la pantalla. El próximo viaje lo aclarará, porque esta vez el viaje deja rastro.
Lo que viene
La lista del banco sigue siendo larga. Los próximos viajes comprueban el botón de cancelar, los escenarios de curvas y de sentido contrario, el paso entre el GPS del coche y el del teléfono, y si la pantalla del conductor del G6 muestra siquiera las tarjetas de giro de una app de terceros.
Las próximas partes de esta serie entran a fondo en las matemáticas del motor de avisos, los apaños para el límite de velocidad, los formatos de PocketGPSWorld, y el propio banco de pruebas: cómo se prueba una app de Android Auto sin coche, con un GPS guionizado y un emulador que cree que todas las carreteras van al norte.
La máquina teclea, el listón lo pones tú
He visto mucho hablar de IA que escribe código, casi todo de gente que la vende o de gente a la que le da miedo. Lo que yo encontré es más aburrido que las dos cosas, y más útil.
Teclea rápido y no se aburre. Reescribe una pantalla por cuarta vez sin un suspiro. Lo que no hace es darse cuenta de que la pantalla Más tiembla, o de que una frase se cortó, o de que hay un botón muerto al lado de uno vivo. No puede ver el coche. Eso me tocaba verlo a mí, y la única razón por la que está arreglado es que escribí cada cosa como una regla que tiene que leer antes de tocar nada.
Así que la responsabilidad no se mueve. El código es mío porque yo pongo el listón con el que se mide y yo soy el que va en el coche. Nada de lo que lo mantuvo honrado es un método de IA. Escribir la especificación antes que el código, apuntar lo que aprendes y guardar pruebas en vez de adivinar es como se ha hecho siempre la ingeniería bien hecha. La herramienta no cambia eso. Lo que hace es que se descubra antes quién se lo estaba saltando.
Apache License, Version 2.0 — la licencia bajo la que se publica el código de AutoNavAlerts. ↩︎
Google — Navigation SDK for Android: Android Auto — la Car App Library ofrece «a set of visual templates approved for driver safety», y «Android Auto limits screen surface interaction to a series of SurfaceCallback methods». ↩︎ ↩︎
Google — Navigation SDK for Android: real-time disruptions — «real-time disruptions are not available on Android Auto». ↩︎
Google — Navigation SDK for Android: speed alerts —
onSpeedingUpdated(float percentageAboveLimit, SpeedAlertSeverity speedAlertSeverity): el porcentaje por encima del límite y un nivel de gravedad, no el límite en sí. ↩︎googlemaps/flutter-navigation-sdk issue #726 — «Incident reporting on Android Auto & CarPlay», abierta el 17 de junio de 2026, todavía abierta. ↩︎
Google Maps Platform — Get started — «you must create a billing-enabled Cloud project and enable the desired APIs or SDKs». ↩︎
Google — Navigation SDK for Android: set up your project — «A Google Cloud console project with the Navigation SDK enabled.» ↩︎
PocketGPSWorld — la base de datos de radares del Reino Unido de la que sincroniza la app, con la suscripción propia de cada usuario. ↩︎
Android Developers — Test using the Desktop Head Unit — el emulador de Google para la pantalla del coche de Android Auto. ↩︎