Googles Karte, meine Blitzer, eine App
Ich wollte eine Sache auf dem Autobildschirm. Googles Karte, Googles Verkehrslage und Googles Abbiegehinweise, mit meinen eigenen Blitzerdaten obendrauf, und Warnungen nur für Blitzer, die tatsächlich auf meine Straßenseite zeigen.
Ich habe nichts für Android Auto gefunden, das das kann. Google Maps hat die Karte und das Routing, aber man kann keine eigene Blitzerdatenbank hineinladen. Also baue ich es selbst.
Es heißt AutoNavAlerts. Es ist eine Navigations-App für Android Auto auf Basis von Googles Navigation SDK, mit einem Warnsystem für Blitzer und Points of Interest obendrauf. Die erste Blitzerquelle ist PocketGPSWorld, mit meinem eigenen bezahlten Abo. Der Code ist öffentlich, unter der Apache License 2.01, auf github.com/damo2929/AutoNavAlerts.
Das ist Teil eins einer Serie. Er behandelt, was die App kann, was Google einer Drittanbieter-App auf einem Autobildschirm erlaubt und was nicht, und wie sie gebaut wurde, denn fast jede Zeile wurde von Claude geschrieben, dem KI-Modell von Anthropic. Ich habe die Regeln gesetzt, getestet und stehe für das Ergebnis gerade. Dieser letzte Teil ist eine Geschichte für sich.
Es ist Version 0.1.0. Sie ist per Sideload installiert, nicht im Play Store, und hatte eine echte Fahrt. Lies es als Baulog, nicht als Produktvorstellung.
Was es heute kann
Das steckt im Testbuild, und dafür ist jeder Teil da:
| Bereich | Was es tut |
|---|---|
| Navigation | Google-Karte mit Verkehrslage, Ortssuche, Routenvorschau mit Ankunftszeit, Abbiegehinweise auf dem Autobildschirm, der Seitenleiste und dem Fahrerdisplay |
| Zu einem Kontakt fahren | Sag oder tipp einen Namen, und die gespeicherten Adressen des Kontakts erscheinen über den Places-Ergebnissen. Nur die Adresse, die du auswählst, geht an Google |
| Verträgt sich mit deiner Musik | Nur Navigationsvorlagen, also behält die Musik ihre Karte im geteilten Bildschirm. Die Sprachwarnung macht die Musik leiser, pausiert sie aber nie |
| Blitzerwarnungen | Drei Stufen pro Blitzer, nur für Blitzer in deiner Fahrtrichtung, auf der Straße, auf der du fährst |
| Abschnittskontrollen | Eine Zone beginnt nur, wenn ein weiterer Blitzer mit demselben Limit vor dir liegt, und endet am letzten Blitzer |
| Tempo-Anzeige | Deine Geschwindigkeit und das Limit der Straße, immer nebeneinander, unten rechts |
| Tempolimits offline | Ein Download der OpenStreetMap-Limits für Großbritannien: 1.326.619 Straßen in 29 MB auf dem Handy. Während der Fahrt wird nichts nachgeschlagen |
| Routen fürs Elektroauto | Die schnellste Route und Googles energieeffiziente Route nebeneinander, und du wählst |
| Blitzerdaten | Dein eigenes PocketGPSWorld-Abo, täglich geprüft, nie während der Navigation ausgetauscht. Oder Import von iGO-, KML-, GPX-, OV2- oder CSV-Dateien |
| Blitzer melden | Ein Tipp im Auto speichert Position, Richtung und Limit, mit einem optionalen gesprochenen Kommentar. Prüfen und Absenden passieren auf dem Handy, nie während der Fahrt |
Die Blitzerwarnungen sind der Grund, warum es die App gibt, also bekommen sie den nächsten Abschnitt.
Ein Blitzer zählt nur, wenn er auf dich zeigt
Eine Blitzerwarnung, die für die Gegenfahrbahn auslöst, ist schlimmer als gar keine. Sie bringt dir bei, die Warnung zu ignorieren. Deshalb ist die erste harte Regel im Design, dass ein Blitzer nur warnt, wenn er in deine Fahrtrichtung zeigt, und diese Regel wird nie gelockert, nie per Voreinstellung umgangen und nie fallen gelassen, wenn die Daten unbequem sind.
Die Logik läuft bei jeder Positionsbestimmung, bis zu zehnmal pro Sekunde. Für jeden Blitzer in der Nähe stellt sie vier Fragen, in dieser Reihenfolge:
| Prüfung | Besteht, wenn | Warum sie da ist |
|---|---|---|
| Nah genug | innerhalb der Auslösedistanz plus 200 m, höchstens 3 km | keine Arbeit an Blitzern, die meilenweit weg sind |
| Vor dir | Peilung zum Blitzer innerhalb von 45° deiner Fahrtrichtung | ein Blitzer hinter dir ist Geschichte |
| Zeigt auf dich | die Richtung des Blitzers innerhalb von 45° deiner Fahrtrichtung, oder der Peilung zum Blitzer in einer Kurve | die Gegenfahrbahn bleibt still |
| Auf deiner Straße | innerhalb von 50 m der Route vor dir, oder ein 40-m-Korridor, der im freien Fahren mit der Entfernung breiter wird | die Parallelstraße bleibt still |
Die 45° sind nicht großzügig. Die TomTom-Dateien von PocketGPSWorld geben die Richtung eines Blitzers in acht Himmelsrichtungen an, also gehen 22,5° davon an die Daten, bevor irgendetwas anderes passiert. Eine GPS-Richtung kostet ein paar Grad mehr, und die Krümmung der Straße noch ein paar. Deshalb darf nichts anderes daran knabbern.
Ein Blitzer, der die Richtungsprüfung nicht besteht, wird trotzdem auf der Karte gezeichnet, abgeblendet, mit einem Pfeil, der zeigt, wohin er schaut. Du kannst ihn sehen. Er redet nur nicht mit dir.
Die Stufen sind zeitbasiert, keine festen Entfernungen. Die erste Warnung kommt 15 Sekunden vorher bei deiner aktuellen Geschwindigkeit, die zweite bei der Hälfte davon, beide mit einer Untergrenze, damit sie der dritten nie zu nahe kommen. Die dritte liegt fest bei 100 Yards und ist Pflicht, solange der Ton an ist. Die Auslösedistanz wächst während einer Annäherung nur, also verkürzt starkes Bremsen nicht die Warnung, die dir schon zustand.
Was Google einer App auf dem Autobildschirm erlaubt
Hier wird es interessant, denn eine Drittanbieter-App auf Android Auto ist nicht Google Maps. Sie läuft innerhalb der Regeln der Car App Library von Android Auto, die Apps „a set of visual templates approved for driver safety“2 gibt, und innerhalb dessen, was das Navigation SDK freigibt.
Drei Lücken haben die App mehr geprägt als alles, was ich selbst bauen wollte:
| Was | Google Maps im Auto | Eine App auf dem Navigation SDK |
|---|---|---|
| Unfall, Polizei oder Baustelle melden | eingebaut | nicht angeboten. Googles eigene Dokumentation: „real-time disruptions are not available on Android Auto“3 |
| Das Tempolimit der Straße | angezeigt | nur der Prozentsatz, um den du drüber bist, und nur, während du zu schnell fährst4 |
| Touch auf den SDK-eigenen Kartenbedienelementen | entfällt | keiner. Android Auto „limits screen surface interaction to a series of SurfaceCallback methods“2 |
Nimm das Tempolimit. Google kennt es. Google sagt einer App, wie weit du drüber bist, als Prozentsatz und Schweregrad, und gar nichts, solange du drunter bist. Darf ich fragen, warum ein Fahrer das Limit erst erfahren darf, wenn er es schon überschreitet? Darauf werde ich keine Antwort bekommen, also umgeht die App es. Solange du drüber bist, rechnet sie das Limit aus deiner Geschwindigkeit und dem Prozentsatz zurück. Darunter nimmt sie den Blitzer, auf den du zufährst, dann den OpenStreetMap-Download, und sie zeigt einen Strich statt gar nichts, wenn sie überhaupt kein Limit hat.
Störungsmeldungen haben dieselbe Form. Die Melde-APIs gibt es in der Navigationsansicht auf dem Handy, aber nicht in der im Auto. Jemand hat Google schon darum gebeten5, und die Anfrage ist noch offen. Die App prüft zur Laufzeit, ob es die APIs gibt, also erscheint Googles Melde-Knopf ohne Änderung an meinem Code, falls ein späteres SDK sie nachliefert. Ein GitHub-Actions-Job prüft das jedes Quartal und eröffnet ein Issue an dem Tag, an dem es passiert.
Die Touch-Regel hat mich richtig erwischt. Die Autokarte des SDK zeichnet ihre eigene Ankunftskarte, Kopfzeile, Zentrieren-Knopf, Tacho und Fahrtleiste. Keins davon nimmt einen Tipp an, weil keine Berührung die Ansicht des SDK erreicht. Sie sehen aus wie Knöpfe und tun gar nichts. Also sind sie alle abgeschaltet, und die App zeichnet ihre eigenen Bedienelemente dort, wo ein Tipp tatsächlich ankommt.
Bring deinen eigenen Schlüssel mit, bring deine eigenen Daten mit
Zwei Entscheidungen halten diese App ehrlich in Sachen Geld und Lizenzen, und beide sind Absicht.
Es gibt keinen eingebauten Maps-Schlüssel. Die Google Maps Platform braucht „a billing-enabled Cloud project“6, und das Navigation SDK braucht ein Projekt, in dem es aktiviert ist7. Würde ich einen Schlüssel mitliefern, würde das Fahren aller Nutzer mir in Rechnung gestellt, oder der Schlüssel würde durchsickern und mir trotzdem in Rechnung gestellt. Also bringt jeder Nutzer seinen eigenen Schlüssel mit, in seinem eigenen Google-Cloud-Konto. Die Handy-App kann einen mit deinem eigenen Google-Konto anlegen, oder du fügst einen ein. Er wird verschlüsselt auf dem Handy gespeichert. Es gibt keinerlei Rückfallebene, und die App macht keinen einzigen SDK-Aufruf, bevor dein Schlüssel drin ist.
Es gibt keine Blitzerdaten in der App. PocketGPSWorld lizenziert seine Datenbank zur persönlichen Nutzung, versieht jeden Download mit einem Wasserzeichen für das Mitglied und verbietet, sie irgendwo abzulegen, wo jemand anderes als der Käufer drankommt. Also liefert die App sie nie mit, hostet sie nie und synchronisiert sie nie zwischen Handys. Du meldest dich mit deinem eigenen Abo an, und das Handy lädt deine eigene, mit Wasserzeichen versehene Kopie in privaten Speicher, der von Backups ausgenommen ist. Auf dem Prüfstand waren das 19.826 Blitzer in 33 Sätzen, ein Satz pro Datei, nie zusammengeführt.
Die automatische Synchronisierung ist höflich dabei. Sie liest einmal am Tag den öffentlichen RSS-Feed von PocketGPSWorld8 und meldet sich nur an, wenn es eine neue Veröffentlichung gibt. Sie tauscht die Blitzer nie aus, während du navigierst.
Eine Klausel in deren Lizenz ist damit nicht ganz geklärt, die über das Einbinden der Daten in eine Anwendung. Für meinen eigenen Gebrauch nehme ich das hin. Bevor die App an irgendjemand anderen geht, bekommt PocketGPSWorld eine E-Mail mit der Frage.
Zwei Tage, 87 Commits, und zuerst ein Designdokument
Jetzt der Teil, über den die Leute streiten werden. Ich habe diesen Code nicht getippt. Claude hat es getan, über Claude Code, mit zwei Modellen, Claude Fable und Claude Opus. Ich habe die Anforderungen geschrieben, jede Entscheidung getroffen, den Prüfstand betrieben, das Auto gefahren und geprüft, was zurückkam. Jeder Commit mit KI-geschriebenen Änderungen trägt einen Trailer, der das sagt, und die README auch.
Das sind die Zahlen, direkt aus dem Repository abgelesen:
| Messgröße | Wert |
|---|---|
| Commits | 87, von 22:10 am 11. Oktober bis 12:44 am 13. Oktober 2026 |
| Commits mit einer Claude-Co-Autor-Zeile | 83 (56 Fable, 27 Opus) |
| Kotlin in der App und ihrer Kernbibliothek | 15.334 Zeilen |
| Unit-Tests | 211, in 3.464 Zeilen |
DESIGN.md, die Spezifikation | 1.763 Zeilen, geschrieben vor jeder Zeile Code |
Das Designdokument kam zuerst, und das ist das Nützlichste, was ich jedem sagen kann, der so etwas macht. Seine erste Zeile sagt, dass kein Code geschrieben wird, bevor es abgenommen ist, und dass jede spätere Änderung zuerst dort gemacht wird. Jede Klasse hat eine aufgeschriebene Aufgabe. Jeder Schwellenwert hat einen Grund. Jede Regel, die ich gesetzt habe, ist als meine markiert, mit Datum.
Das zählt, weil ein Modell vergisst. Eine lange Sitzung wird zusammengefasst, und die Zusammenfassung behält das Wesentliche und lässt die Details weg, und in den Details stecken die Fehler. Die eigene AGENTS.md des Repositorys sagt es klar: Verlass dich nicht auf eine Zusammenfassung dieser Dateien aus dem Gedächtnis oder aus einer früheren Sitzung. Der Agent geht zurück zum Dokument. Jedes Mal.
In der zweiten Phase arbeiteten außerdem zwei Agenten parallel, einer an Zielführung, Karte und Bildschirmen, der andere an Ortung, Warnungen, Sprache und Kartenmarkierungen. Jeder besaß eine schriftliche Liste von Dateien, und die Schnittstellen zwischen ihnen waren vorab festgelegt: hinzufügen, nicht umbenennen. Sie ließen sich sauber zusammenführen, weil die Grenze gezogen war, bevor einer von beiden anfing, und nicht erst hinterher entdeckt wurde.
Jede harte Regel kam von etwas, das ich gesehen habe
Das Design hat eine Liste harter Regeln, und keine davon kam von einem Whiteboard. Jede kam daher, dass ich das Ding auf der Desktop Head Unit9, Googles Autobildschirm-Emulator auf dem PC, oder im Auto habe laufen sehen und es etwas falsch gemacht hat.
| Harte Regel | Was ich gesehen habe, das sie zur Regel gemacht hat |
|---|---|
| Ein Blitzer warnt nur, wenn er auf dich zeigt | Warnungen für die Gegenfahrbahn sind Rauschen, das dir beibringt, Warnungen zu ignorieren |
| Nichts auf dem Autobildschirm, das nicht funktioniert | zwei Stopp-Knöpfe auf dem Bildschirm, einer davon tot |
| Keine Funktion doppelt | dasselbe Paar, dazu zwei Zentrieren-Knöpfe, zwei Tempo-Anzeigen |
| Ein Abbrechen, das von Google | die Karte in der Ecke mit dem X ist Android Autos eigene, gezeichnet aus der Fahrt, die die App veröffentlicht, also flog der eigene Stopp-Knopf der App raus |
| Kein Wackeln auf dem Autobildschirm | der Mehr-Bildschirm ruckelte, während das Auto stand, weil er jede Sekunde einen identischen Bildschirm neu schickte und Android Auto jede Aktualisierung animiert |
| Jeder Knopf auf der rechten Seite | die Kartenknöpfe saßen oben links, bis der Autobildschirm seine Größe meldete; jetzt von Anfang an eine Spalte am rechten Rand, nichts von uns links |
| Nie ein eingebauter Maps-Schlüssel | niemandes Fahren wird jemand anderem in Rechnung gestellt |
Das Wackeln ist mein Liebling, weil es so klein ist und es ausgeliefert worden wäre. Eine Live-GPS-Zeile tickte einmal pro Sekunde. Jeder Tick schickte den ganzen Bildschirm neu, unverändert, und der Host animierte ihn, also zitterte jede Zeile darunter, während das Auto stillstand. Der Fix ist ein einziger Vergleich: nur neu zeichnen, wenn sich eine Zeile geändert hat. Die Regel ist größer als der Fix. Ein Bildschirm, der stillhält, muss auch still aussehen, und das wird mit einer Serie von Screenshots geprüft, die identisch sein müssen.
Das ist die eigentliche Arbeit, wenn eine KI den Code schreibt. Sie wird nicht müde und hat nichts gegen Umschreiben, aber sie kann den Autobildschirm nicht sehen. Du schon. Was du gesehen hast, als Regel aufzuschreiben, mit Datum, verhindert, dass es drei Sitzungen später zurückkommt.
Was der Code falsch gemacht hat, und wie es gefunden wurde
Reichlich. Nichts davon war exotisch, und jeder Fehler wurde gefunden, indem es lief, nicht indem man es las:
| Fehler | Was er tat | Wie er gefunden wurde |
|---|---|---|
| Route dem falschen Abschnitt zugeordnet | Googles Route von einem geparkten Auto ging nach Norden, wendete in einem Kreisverkehr und kam auf derselben Straße nach Süden zurück. Der Abgleich heftete das Auto an den nördlichen Abschnitt 10 m daneben, also war jeder Blitzer in Richtung Süden um über einen Kilometer „neben der Straße“. Nichts warnte | eine geskriptete Fahrt auf dem Prüfstand; das Warnungslog meldete offRoad lateral=1204 für jeden Blitzer |
| Sprach-Watchdog zu kurz | er erlaubte 1,5 s plus 70 ms pro Zeichen. Zahlen auszusprechen dauert länger, also wurde jede Warnung der zweiten Stufe mitten im Satz abgeschnitten | die Sprachaufzeichnungen eines Prüfstandlaufs |
| Ein Ratenlimit in der Logik | ein Drei-Sekunden-Fenster bedeutete, dass von zwei Blitzern an einer Kreuzung einer für immer verloren ging | die Warnungen nachverfolgen, die auf der ersten echten Fahrt stumm blieben |
| Eine veraltete Richtung | der Emulator meldet eine Peilung von 0°, egal was du tust, also fiel auf einer Straße nach Süden jeder Blitzer durch die Richtungsprüfung | ein simulierter Lauf die A61 hinunter |
| Limitwechsel als Blitzerwarnung angesagt | ein Limitwechsel voraus wurde als Blitzerwarnung der ersten Stufe eingereiht | das Sprachlog auf dem Prüfstand |
Beim zweiten lohnt sich eine Pause. Jeder einzelne Test war grün. Der Code war nach seinem eigenen Maßstab korrekt. Er hatte nur einen Timeout, gewählt von jemandem, der nie ein Handy eine Entfernung laut vorlesen gehört hat. Der Test, der das findet, ist eine echte Stimme, mit Zeitmessung, auf einer echten Fahrt.
Die erste echte Fahrt
Am 12. Oktober habe ich einen Release-Build aufs Handy gespielt und ihn im XPENG G6 über kabelloses Android Auto ausgefahren. Zwei Dinge gingen schief. Eine im Stand gesetzte Route löschte sich innerhalb von Sekunden nach dem Losfahren. Und manche Warnungen wurden angesagt und manche nicht, ohne ein Muster, das ich erkennen konnte.
Dann das schlimmere Problem. Es gab nichts mehr zu lesen. Das ColorOS auf meinem Handy wirft die Logzeilen der App weg, also hinterließ die Fahrt überhaupt keine Beweise. War es die App, Googles SDK oder Android Auto selbst? Ich konnte es nicht sagen.
Also war die Lösung für die erste Fahrt keine Codeänderung. Es waren Beweise. Die App schreibt jetzt ständig zwei Logs auf dem Handy, eins für Routing und Karte und eins für jede Warnungsentscheidung, in 15-Sekunden-Paketen, dazu einen optionalen Fahrtenschreiber, der jede Position speichert, damit sich eine Fahrt auf dem Prüfstand nachspielen lässt. Dann wurden die Vermutungen behoben, jede so geschrieben, dass sie weniger tut und protokolliert, dass sie es getan hat. Jeder Weg, auf dem die Zielführung enden kann, hält jetzt fest, wer sie beendet hat.
Auf dem Prüfstand hat Android Auto seitdem einmal Stopp ausgelöst, 2 Minuten 35 Sekunden in eine geführte Fahrt hinein. Ich habe zu dem Zeitpunkt auf der Head Unit herumgeklickt, also war es höchstwahrscheinlich das X auf seiner eigenen Karte. Ohne dass jemand den Bildschirm berührt, ist es nicht passiert. Die nächste Fahrt wird es klären, denn diesmal hinterlässt die Fahrt eine Spur.
Wie es weitergeht
Die Liste für den Prüfstand ist noch lang. Die nächsten Fahrten prüfen den Abbrechen-Knopf, die Szenarien für Kurven und falsche Richtung, die Übergabe zwischen dem GPS des Autos und dem des Handys, und ob das Fahrerdisplay im G6 überhaupt Abbiegekarten von einer Drittanbieter-App anzeigt.
Spätere Teile dieser Serie gehen richtig auf die Mathematik der Warnlogik ein, die Umgehungen beim Tempolimit, die PocketGPSWorld-Formate und den Prüfstand selbst: wie man eine Android-Auto-App ohne Auto testet, mit einem geskripteten GPS und einem Emulator, der glaubt, jede Straße führe nach Norden.
Die Maschine tippt, der Maßstab ist deiner
Ich habe viel Gerede über KI, die Code schreibt, mitbekommen, das meiste von Leuten, die sie verkaufen, oder von Leuten, die Angst davor haben. Was ich gefunden habe, ist langweiliger als beides, und nützlicher.
Sie tippt schnell und langweilt sich nicht. Sie schreibt einen Bildschirm zum vierten Mal um, ohne zu seufzen. Was sie nicht tut, ist bemerken, dass der Mehr-Bildschirm wackelt, oder dass ein Satz abgeschnitten wurde, oder dass ein toter Knopf neben einem lebendigen sitzt. Sie kann das Auto nicht sehen. Das zu sehen war meine Sache, und der einzige Grund, warum es behoben ist, ist, dass ich jedes davon als Regel aufgeschrieben habe, die sie lesen muss, bevor sie irgendetwas anfasst.
Insofern wandert die Verantwortung nicht. Der Code ist meiner, weil ich den Maßstab setze, an dem er gemessen wird, und weil ich derjenige im Auto bin. Nichts von dem, was ihn ehrlich gehalten hat, ist eine KI-Methode. Die Spezifikation vor dem Code schreiben, aufschreiben, was man lernt, und Beweise sichern statt zu raten, so wurde ordentliche Ingenieursarbeit schon immer gemacht. Das Werkzeug ändert daran nichts. Es macht nur schneller sichtbar, wer es übersprungen hat.
Apache License, Version 2.0 — die Lizenz, unter der der AutoNavAlerts-Code veröffentlicht ist. ↩︎
Google — Navigation SDK for Android: Android Auto — die Car App Library stellt „a set of visual templates approved for driver safety“ bereit, und „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): der Prozentsatz über dem Limit und ein Schweregrad, nicht das Limit selbst. ↩︎googlemaps/flutter-navigation-sdk issue #726 — „Incident reporting on Android Auto & CarPlay“, eröffnet am 17. Juni 2026, noch offen. ↩︎
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 — die britische Blitzerdatenbank, aus der die App synchronisiert, mit dem eigenen Abo jedes Nutzers. ↩︎
Android Developers — Test using the Desktop Head Unit — Googles Emulator für den Android-Auto-Autobildschirm. ↩︎