Qué es MapConductor: elegir el SDK de mapas después, no antes

Un SDK de código abierto que pone los principales SDK de mapas detrás de una API común. Qué hace y cuándo conviene tenerlo.

MapConductor es un SDK de código abierto para manejar SDK de mapas a través de una sola API común. Está disponible para Android (Jetpack Compose), iOS (SwiftUI) y React (TypeScript), y hoy soporta 15 proveedores. La licencia es Apache-2.0.

Como este es el primer artículo, vale la pena volver a escribir qué hace y cuándo sirve.

Los SDK de mapas están todos bien hechos

Google Maps, Mapbox, HERE, ArcGIS, MapLibre, MapTiler, TomTom, Longdo, Mappls: cada uno se fue puliendo durante mucho tiempo y cada uno tiene lo suyo. Detalle en calles y direcciones, navegación, conexión con activos GIS, libertad de diseño, regiones cubiertas. A la pregunta “cuál es el mejor” no hay respuesta general: cambia según la app que se construya y la región a la que se llegue.

Y sin embargo, desde el lado de la implementación, esa elección queda prácticamente sellada en las primeras líneas. El código que dibuja el mapa se enlaza a fondo con los tipos y conceptos de un SDK concreto, así que cuando querés comparar más adelante, lo que ya no te queda es la forma de comparar.

Esto no es un reproche al diseño de nadie. Es más bien el resultado de que cada uno diseñó con cuidado para su propio terreno fuerte: los conceptos y los nombres no coinciden. Emparejar lo que no coincide es tarea de quien escribe encima, no de quien provee el SDK. MapConductor se hace cargo de esa capa.

Qué hace

Tu aplicación depende únicamente de la API unificada de MapConductor. Las diferencias entre proveedores las absorben los controladores, así que al cambiar de proveedor solo se tocan tres cosas: el módulo que incluís, el tipo de la vista de mapa y el tipo del objeto de estado. Cómo escribís marcadores, formas, movimientos de cámara y eventos no cambia.

kotlin
// Declará los overlays fuera de la bifurcación: al cambiar de proveedor no se reescriben
val overlays: @Composable MapViewScope.() -> Unit = {
    Marker(markerState)
    Polyline(routeState)
}

if (useMapLibre) {
    MapLibreMapView(state = maplibre, content = overlays)
} else {
    GoogleMapView(state = googlemaps, content = overlays)
}

También podés poner dos mapas lado a lado y cambiar en tiempo de ejecución. Si le pasás al otro la última posición de cámara, ni siquiera salta la imagen.

No solo se empareja la forma de escribir

Lo que más preocupa al oír “API común” es, seguramente, que se empareje la escritura pero no los resultados. Que el zoom 14 se vea distinto según el entorno, que la distancia entre dos puntos no coincida entre Android e iOS: eso pasa de verdad.

MapConductor se hace cargo de esa parte.

Lo que traemos propioLo que gracias a eso coincide
Cálculo geográficoDistancia, rumbo, área e interpolación implementados con la misma fórmula en Kotlin, Swift y TypeScript. Al no depender de las utilidades de cada SDK, los números que se muestran no se desvían entre plataformas
CámaraConvertimos entre zoom y altitud de cámara, calibrado con mediciones. El zoom 14 abarca lo mismo en cualquier proveedor
Dibujo de marcadoresCon pocos, marcadores nativos; al pasar los 2.000 cambia internamente a teselas ráster. Con decenas de miles la cámara sigue fluida y el código de la app no cambia ni una línea
FormasDonde el proveedor no tiene la función —polígonos con agujeros, rutas de círculo máximo— lo dibujamos como teselas ráster y llegamos al mismo resultado visual
AtribuciónLa regla que cambia la atribución según el zoom y el área visible es para nosotros parte del diseño del mapa

Un envoltorio que solo llama a los métodos de cada SDK termina pudiendo lo que puede el SDK con menos funciones. Por eso preferimos dibujar nosotros lo que falta.

Para qué sirve

Se aprende una sola API

Como los conceptos y los nombres cambian según el proveedor, cada cambio de proveedor y cada salto de plataforma obliga a reaprender. Con MapConductor aprendés una API, y en Android, iOS y React tiene el mismo nombre y el mismo significado. Lo que aprendiste en Android sirve tal cual en iOS, y cuando entra alguien al equipo no tiene que leer tantas cosas como proveedores haya.

Se puede escribir código donde no aparece el nombre de ningún SDK de mapas

GeoPoint y MarkerState no pertenecen a ningún SDK de mapas. Armar una ruta, decidir si algo cae dentro de un área, definir qué se muestra: esa lógica se puede escribir separada de los tipos del SDK. Y los componentes de mapa compartidos se pueden sacar como biblioteca en vez de rehacerlos para cada proveedor.

La discusión de la especificación se hace una sola vez

Si en Android, iOS y Web usás SDK de mapas distintos, ni el comportamiento de los marcadores ni el significado de los números de cámara coinciden, y terminás discutiendo la misma funcionalidad tres veces. Con un modelo común, esas tres veces se vuelven una.

Queremos crear un estado en el que se pueda elegir

Hasta acá hablamos del lado de quien integra un mapa. Pero eso no es todo lo que MapConductor busca.

Hoy, la elección del SDK de mapas es el primer commit de la implementación. Así, la selección deja de ser “probar y decidir” para volverse “decidir y después construir”, y la comparación queda en el papel. Para el lado elegido tampoco es un buen estado: un buen SDK queda fuera de la lista no por su calidad, sino porque ya se escribió con otro.

Con una API común, ese orden cambia. Lo hacés andar, comparás la misma pantalla de la misma app y después decidís. Lo que define pasa a ser el precio, las regiones cubiertas, la frescura de los datos, la calidad del dibujado: justo aquello en lo que los proveedores compiten de verdad.

Por eso MapConductor está hecho para no tapar las fortalezas de cada uno. Solo unificamos las funciones básicas que todos los proveedores tienen. Con getMapViewHolder() sobre el objeto de estado obtenés la vista de mapa nativa y la instancia del mapa tal cual, así que lo que existe únicamente en ese proveedor lo escribís directo con su API. Un envoltorio que tapara todo borraría los factores de diferenciación; no hacemos eso. Usar “lo común con MapConductor y lo decisivo con la API del proveedor” es perfectamente normal.

Después de que los navegadores emparejaron su implementación con HTML5, dejaron de competir por la compatibilidad en sí y pasaron a competir por velocidad y funciones. Con los SDK de mapas es igual: una vez fijada la interfaz común, lo que se pregunta es cuán rápido, cuán preciso y en cuántas regiones se puede dibujar. La unificación no detiene la evolución de cada SDK: le alinea la dirección.

Hay algo más, que apunta al futuro. Los datos de mapas y el geocoding venían atados al SDK de mapas de quien los provee. Si se pueden separar la visualización y los datos, aparecen más escenarios para proveedores sin medios propios de visualización: los que solo tienen geocoding, o datos de un área específica. Hoy todavía no hay funciones orientadas a ese uso; es una dirección, no una lista de funcionalidades.

Por lo demás, cumplir los términos de uso de los datos y servicios es responsabilidad de quien los integra. Que algo se pueda combinar técnicamente no significa que la combinación esté autorizada.

Cuándo conviene y cuándo no

Conviene en casos así:

  • Querés ofrecer la misma experiencia de mapa en varias plataformas
  • Querés dejar abierta la posibilidad de cambiar de proveedor más adelante
  • El centro son representaciones de mapa estándar: marcadores, formas, cámara
  • Manejás miles o decenas de miles de marcadores
  • Se exige coherencia al mostrar distancias y áreas

En cambio, no conviene en estos casos:

  • El protagonista es una representación avanzada propia de un proveedor (shaders propios, capas exclusivas del fabricante)
  • El objetivo es la función especializada del SDK en sí, como la navegación paso a paso
  • Todo se resuelve con una plataforma y un proveedor, y no hay planes de cambiarlo

De todos modos, no es todo o nada. Siempre tenés a mano la instancia nativa del mapa, así que podés escribir solo las partes especiales con código propio del proveedor.

Cómo empezar

Con MapLibre funciona sin clave de API, así que hasta el primer mapa hay unos cinco minutos.

Publicamos el avance del desarrollo y las versiones en Discord. Los comentarios sobre el diseño y los reportes de errores son bienvenidos. El código está en GitHub.