MapConductor ist ein quelloffenes SDK, mit dem sich Karten-SDKs über eine einzige gemeinsame API ansprechen lassen. Es gibt es für Android (Jetpack Compose), iOS (SwiftUI) und React (TypeScript), und derzeit werden 15 Anbieter unterstützt. Die Lizenz ist Apache-2.0.
Weil dies der erste Beitrag ist, schreiben wir noch einmal auf, was das Ganze tut und wann es hilft.
Karten-SDKs sind alle gut gemacht
Google Maps, Mapbox, HERE, ArcGIS, MapLibre, MapTiler, TomTom, Longdo, Mappls — jedes dieser SDKs ist über lange Zeit gereift, und jedes hat seine Stärken: Detailtiefe bei Straßen und Adressen, Navigation, Anbindung an GIS-Bestände, gestalterische Freiheit, abgedeckte Regionen. Auf die Frage „welches ist das beste“ gibt es keine allgemeine Antwort; sie hängt davon ab, was gebaut wird und für welche Region.
Und doch steht diese Wahl aus Sicht der Umsetzung schon nach den ersten Zeilen fest. Der Code, der eine Karte zeichnet, verwächst tief mit den Typen und Begriffen eines bestimmten SDK — wenn man später vergleichen möchte, fehlt einem genau das Mittel zum Vergleich.
Das ist kein Vorwurf an den Entwurf der Anbieter. Es ist eher die Folge davon, dass jeder sorgfältig auf sein eigenes Stärkefeld hin entworfen hat: Begriffe und Benennungen sind eben nicht deckungsgleich. Das anzugleichen, was nicht deckungsgleich ist, bleibt Arbeit derer, die darauf schreiben — nicht derer, die das SDK liefern. MapConductor übernimmt diese eine Schicht.
Was es tut
Ihre Anwendung hängt allein an der einheitlichen API von MapConductor. Die Unterschiede zwischen Anbietern fangen Treiber auf, sodass beim Wechsel nur drei Dinge angefasst werden: das eingebundene Modul, der Typ der Kartenansicht und der Typ des Statusobjekts. Wie Sie Marker, Formen, Kamerabewegungen und Ereignisse schreiben, bleibt gleich.
// Die Overlays außerhalb der Verzweigung deklarieren — beim Anbieterwechsel bleibt das stehen
val overlays: @Composable MapViewScope.() -> Unit = {
Marker(markerState)
Polyline(routeState)
}
if (useMapLibre) {
MapLibreMapView(state = maplibre, content = overlays)
} else {
GoogleMapView(state = googlemaps, content = overlays)
}Sie können auch zwei Karten nebeneinander stellen und zur Laufzeit umschalten. Reicht man der Gegenseite die letzte Kameraposition mit, springt dabei nicht einmal das Bild.
Angeglichen wird nicht nur die Schreibweise
Die größte Sorge bei einer „gemeinsamen API“ ist wohl, dass zwar die Schreibweise passt, aber die Ergebnisse auseinandergehen. Zoom 14 sieht je nach Umgebung anders aus; die Entfernung zwischen zwei Punkten stimmt zwischen Android und iOS nicht überein — das passiert tatsächlich.
MapConductor hält diesen Teil selbst.
| Was wir selbst mitbringen | Was dadurch zusammenpasst |
|---|---|
| Geoberechnung | Entfernung, Peilung, Fläche und Interpolation sind in Kotlin, Swift und TypeScript nach derselben Formel umgesetzt. Da wir nicht von den Hilfsfunktionen der SDKs abhängen, weichen die angezeigten Zahlen zwischen Plattformen nicht ab |
| Kamera | Zoom und Kamerahöhe werden ineinander umgerechnet und anhand von Messungen kalibriert. Zoom 14 zeigt bei jedem Anbieter denselben Ausschnitt |
| Marker-Rendering | Bei wenigen Markern native Marker; jenseits von 2.000 schaltet es intern auf Rasterkacheln um. Auch bei Zehntausenden bleibt die Kamera flüssig, und am Code der Anwendung ändert sich keine Zeile |
| Formen | Wo einem Anbieter die Funktion fehlt — Polygone mit Löchern, Großkreise —, zeichnen wir sie als Rasterkacheln und kommen auf dasselbe Bild |
| Quellenangaben | Die Regel, nach der sich Quellenangaben mit Zoom und Ausschnitt ändern, gehört bei uns zum Kartendesign |
Ein Wrapper, der nur die Methoden der einzelnen SDKs durchreicht, kann am Ende nur das, was das schwächste SDK kann. Deshalb füllen wir Lücken lieber selbst, indem wir sie zeichnen.
Wofür das gut ist
Man lernt nur eine API
Weil Begriffe und Benennungen je Anbieter verschieden sind, beginnt das Lernen bei jedem Anbieterwechsel und bei jedem Plattformwechsel von vorn. Mit MapConductor lernen Sie eine API, und sie heißt und bedeutet auf Android, iOS und React dasselbe. Was Sie auf Android gelernt haben, gilt auf iOS weiter, und wer neu ins Team kommt, muss nicht so viele Dinge lesen, wie es Anbieter gibt.
Man kann Code schreiben, in dem kein Karten-SDK vorkommt
GeoPoint und MarkerState gehören keinem Karten-SDK. Eine Route bauen, prüfen, ob etwas in einem Bereich liegt, entscheiden, was angezeigt wird — solche Logik lässt sich von den Typen eines SDK lösen. Gemeinsame Kartenbausteine können Sie als Bibliothek herausziehen, statt sie je Anbieter noch einmal zu bauen.
Über die Spezifikation wird einmal gesprochen
Wenn auf Android, iOS und Web je ein anderes Karten-SDK läuft, stimmen weder das Verhalten der Marker noch die Bedeutung der Kamerazahlen überein, und dieselbe Funktion wird dreimal besprochen. Mit einem gemeinsamen Modell wird aus dreimal einmal.
Wir wollen einen Zustand herstellen, in dem man wählen kann
Bis hierher ging es um die Seite, die eine Karte einbaut. Damit ist aber nicht alles gesagt, was MapConductor erreichen will.
Heute ist die Wahl des Karten-SDK der erste Commit der Umsetzung. Damit wird aus „ausprobieren und entscheiden“ ein „entscheiden und dann bauen“, und der Vergleich bleibt auf dem Papier. Auch für die Gewählten ist das kein guter Zustand: Ein gutes SDK fällt aus der Auswahl, nicht wegen seiner Qualität, sondern weil schon mit einem anderen geschrieben wurde.
Mit einer gemeinsamen API dreht sich diese Reihenfolge. Man lässt es laufen, vergleicht dieselbe Ansicht derselben App und entscheidet danach. Ausschlaggebend werden Preis, abgedeckte Regionen, Aktualität der Daten, Qualität der Darstellung — also genau das, worin die Anbieter eigentlich konkurrieren.
Deshalb ist MapConductor so gebaut, dass es die Stärken der einzelnen Anbieter nicht verdeckt. Vereinheitlicht ist nur, was jeder Anbieter grundsätzlich hat. Über getMapViewHolder() am Statusobjekt bekommen Sie die native Kartenansicht und die Karteninstanz unverändert heraus, sodass Sie alles, was es nur bei diesem einen Anbieter gibt, direkt mit dessen API schreiben können. Ein Wrapper, der alles verdeckt, würde Unterscheidungsmerkmale auslöschen; das tun wir nicht. „Gemeinsames über MapConductor, Entscheidendes über die API des Anbieters“ ist ein ganz normales Nebeneinander.
Nachdem die Browser ihre Umsetzung mit HTML5 angeglichen hatten, konkurrierten sie nicht mehr über die Kompatibilität selbst, sondern über Geschwindigkeit und Funktionen. Bei Karten-SDKs ist es dasselbe: Steht eine gemeinsame Schnittstelle fest, geht es darum, wie schnell, wie genau und für wie viele Regionen darauf gezeichnet werden kann. Vereinheitlichung hält die Entwicklung der einzelnen SDKs nicht auf — sie richtet ihre Richtung aus.
Und noch etwas, das eher die Zukunft betrifft. Kartendaten und Geocoding waren bisher an das Karten-SDK desjenigen gebunden, der sie anbietet. Lassen sich Darstellung und Daten trennen, entstehen mehr Gelegenheiten für Anbieter ohne eigene Darstellung — solche, die nur Geocoding oder nur Daten eines Fachgebiets haben. Funktionen für diesen Zweck gibt es derzeit noch nicht; das ist eine Richtung, keine Funktionsliste.
Übrigens liegt es in der Verantwortung der Entwicklerinnen und Entwickler, die Nutzungsbedingungen der Daten und Dienste einzuhalten. Dass sich etwas technisch kombinieren lässt, heißt nicht, dass die Kombination erlaubt ist.
Wann es passt und wann nicht
Es passt in Fällen wie diesen:
- Sie wollen auf mehreren Plattformen dasselbe Kartenerlebnis bieten
- Sie wollen sich die Möglichkeit offenhalten, den Anbieter später zu wechseln
- Im Mittelpunkt stehen übliche Kartendarstellungen: Marker, Formen, Kamera
- Sie arbeiten mit Tausenden bis Zehntausenden Markern
- Entfernungen und Flächen müssen einheitlich angezeigt werden
Umgekehrt passt es in diesen Fällen nicht:
- Im Mittelpunkt stehen fortgeschrittene Darstellungen genau eines Anbieters (eigene Shader, herstellereigene Ebenen)
- Es geht um die Spezialfunktionen des SDK selbst, etwa Turn-by-Turn-Navigation
- Alles bleibt bei einer Plattform und einem Anbieter, und daran soll sich nichts ändern
Es ist aber kein Alles-oder-nichts. An die native Karteninstanz kommen Sie jederzeit heran, sodass Sie nur die besonderen Stellen mit anbieterspezifischem Code schreiben können.
Wie Sie anfangen
Mit MapLibre läuft es ohne API-Schlüssel; bis zur ersten Karte sind es etwa fünf Minuten.
- Loslegen — Ihre erste Karte, mit MapLibre
- Warum MapConductor — die Überlegungen, aus denen dieser Beitrag entstanden ist
- Architektur — wie sich einheitliche API, Core und Treiber aufteilen
- Unterstützte Anbieter und Einrichtung — die Schritte je Plattform
Entwicklungsstand und Releases veröffentlichen wir auf Discord. Rückmeldungen zum Entwurf und Fehlerberichte sind willkommen. Der Code liegt auf GitHub.
