Google’s Map, My Cameras, One App

I wanted one thing on the car screen. Google’s map, Google’s traffic and Google’s turn-by-turn, with my own speed camera data on top, alerting me only for cameras that are actually pointing at my side of the road.

I could not find anything on Android Auto that did that. Google Maps has the map and the routing, but there is no way to load your own camera database into it. So I am building it.

It is called AutoNavAlerts. It is an Android Auto navigation app built on Google’s Navigation SDK, with a camera and point-of-interest alert system written on top. The first camera source is PocketGPSWorld, using my own paid subscription. The code is public under the Apache License 2.01 at github.com/damo2929/AutoNavAlerts.

This is part one of a series. It covers what the app does, what Google will and will not let a third-party app do on a car screen, and how it was built, because nearly every line of it was written by Claude, Anthropic’s AI model, with me setting the rules, testing it and owning the result. That last part is a story in itself.

It is version 0.1.0. It is sideloaded, not on the Play Store, and it has had one real drive. Read it as a build log, not a product launch.

What It Does Today

Here is what is in the test build, and what each part is for:

AreaWhat it does
NavigationGoogle map with traffic, place search, route preview with the ETA, turn-by-turn on the car screen, the rail and the driver’s display
Drive to a contactSay or type a name and the contact’s saved addresses come up above the Places results. Only the address you pick goes to Google
Lives with your musicNavigation templates only, so music keeps its card in split screen. Alert speech lowers the music, it never pauses it
Camera alertsThree stages per camera, only for cameras facing your direction of travel, on the road you are on
Average speed zonesA zone starts only when another camera with the same limit is ahead of you, and ends at the last camera
Speed panelYour speed and the road’s limit, always side by side, bottom right
Speed limits offlineOne download of OpenStreetMap limits for the UK: 1,326,619 roads in 29 MB on the phone. Nothing looked up while driving
Electric car routesThe fastest route and Google’s energy-efficient route side by side, and you pick
Camera dataYour own PocketGPSWorld subscription, checked daily, never swapped in while you are navigating. Or import iGO, KML, GPX, OV2 or CSV files
Report a cameraOne tap in the car saves position, heading and limit, with an optional spoken comment. Review and send happen on the phone, never while driving

The camera alerts are the reason the app exists, so they get the next section.

A Camera Only Counts If It Faces You

A speed camera alert that fires for the other carriageway is worse than no alert. It trains you to ignore the thing. So the first hard rule in the design is that a camera alerts only when it faces your direction of travel, and that rule is never loosened, never defaulted around and never dropped when the data is awkward.

How a position fix becomes a camera alertInFour checks, every fixOutcar speed and GPSwhen the car shares themphone GPS10 fixes a secondyour own camera setson the phone1. close enough2. ahead of you3. facing your way4. on your roadbanner on thecar mapspoken alert,music loweredcamera highlightedon the mapfail any check: no alert; facing away is drawn dimmed with its arrow
How a fix becomes an alert. Up to ten positions a second go through four checks; only a camera that passes all four is spoken and raised as an alert.

The engine runs on every position fix, up to ten a second. For each camera nearby it asks four questions, in order:

CheckPasses whenWhy it is there
Close enoughinside the trigger distance plus 200 m, capped at 3 kmno work spent on cameras miles away
Ahead of youbearing to the camera within 45° of your headinga camera behind you is history
Facing your waythe camera’s bearing within 45° of your heading, or of the bearing to the camera on a bendthe other carriageway stays silent
On your roadwithin 50 m of the route ahead, or a 40 m corridor that widens with distance in free drivethe parallel road stays silent

The 45° is not generous. PocketGPSWorld’s TomTom files give a camera’s direction in eight compass points, so 22.5° of it is gone to the data before anything else. A GPS heading costs a few more degrees, and the curve of the road a few more again. That is why nothing else is allowed to eat into it.

A camera that fails the direction check is still drawn on the map, dimmed, with an arrow showing the way it faces. You can see it. It just does not talk to you.

Three alert stages at 70 mphDefault lead: 15 seconds at your speed, here 70 mphyou, 70 mphcamerafacing youother carriageway, facing away: dimmed, silent1st alert469 m out, 15 s2nd alert235 m out, 7.5 spassing100 yd (91 m)not to scale; floors of 242 m and 142 m keep the first two apart at low speed
The three stages at 70 mph with the default 15-second lead. The first two are timed from your speed; the passing alert is fixed at 100 yards and cannot be turned off while sound is on.

The stages are timed, not fixed distances. The first alert comes 15 seconds out at your current speed and the second at half that, both with a floor so they never crowd the third. The third is fixed at 100 yards, and it is compulsory whenever sound is on. The trigger distance only ever grows on an approach, so braking hard does not shorten the warning you were already owed.

What Google Lets An App Do On The Car Screen

This is where it gets interesting, because a third-party app on Android Auto is not Google Maps. It runs inside rules set by Android Auto’s Car App Library, which gives apps “a set of visual templates approved for driver safety”2, and inside what the Navigation SDK chooses to expose.

Three gaps shaped the app more than anything I chose to build:

WhatGoogle Maps on the carAn app on the Navigation SDK
Reporting a crash, police or roadworksbuilt innot offered. Google’s own documentation: “real-time disruptions are not available on Android Auto”3
The road’s speed limitshownonly the percentage you are over it, and only while you are speeding4
Touch on the SDK’s own map controlsn/anone. Android Auto “limits screen surface interaction to a series of SurfaceCallback methods”2

Take the speed limit. Google knows it. Google will tell an app how far over it you are, as a percentage and a severity, and nothing at all while you are under it. Can I ask why a driver is allowed to know the limit only once they are already breaking it? I am not going to get an answer to that, so the app works around it. While you are over, it works the limit back out from your speed and the percentage. Below it, it uses the camera you are approaching, then the OpenStreetMap download, and it shows a dash rather than nothing when it has no limit at all.

Incident reporting is the same shape. The reporting APIs exist on the phone’s navigation view and not on the car’s. Somebody has already asked Google for it5, and it is still open. The app checks for the APIs at run time, so if a later SDK adds them, Google’s report button appears with no change to my code. A GitHub Actions job checks every quarter and opens an issue the day it happens.

The touch rule caught me out properly. The SDK’s car map draws its own arrival card, header, re-centre button, speedometer and trip bar. None of them can take a tap, because no touch reaches the SDK’s view. They look like buttons and do nowt. So they are all switched off, and the app draws its own controls where a tap actually lands.

Bring Your Own Key, Bring Your Own Data

Two decisions keep this app honest about money and licences, and both are deliberate.

There is no built-in Maps key. Google Maps Platform needs “a billing-enabled Cloud project”6, and the Navigation SDK needs a project with it enabled7. If I shipped a key, everyone’s driving would be billed to me, or the key would leak and be billed to me anyway. So every user brings their own key, in their own Google Cloud account. The phone app can create one with your own Google account, or you paste one in. It is stored encrypted on the phone. There is no fallback of any kind, and the app will not make a single SDK call until your key is in.

There is no camera data in the app. PocketGPSWorld licenses its database for individual use, watermarks every download to the member, and forbids putting it anywhere anyone but the purchaser can reach it. So the app never ships it, never hosts it and never syncs it between phones. You log in with your own subscription, and the phone downloads your own watermarked copy into private storage that is excluded from backups. On the bench that was 19,826 cameras in 33 sets, one set per file, never merged.

The automatic sync is polite about it. It reads PocketGPSWorld’s public RSS feed once a day8 and only logs in when there is a new release. It never swaps the cameras over while you are navigating.

One clause in their licence is not fully settled by this, the one about incorporating the data into an application. For my own use I accept that. Before the app goes to anyone else, PocketGPSWorld gets an email asking.

Two Days, 87 Commits, And A Design Document First

Now the part people will argue about. I did not type this code. Claude did, through Claude Code, using two models, Claude Fable and Claude Opus. I wrote the requirements, made every decision, ran the bench, drove the car and reviewed what came back. Every commit with AI-written changes in it carries a trailer that says so, and so does the README.

These are the numbers, read off the repository:

MeasureValue
Commits87, from 22:10 on 11th October to 12:44 on 13th October 2026
Commits carrying a Claude co-author line83 (56 Fable, 27 Opus)
Kotlin in the app and its core library15,334 lines
Unit tests211, in 3,464 lines
DESIGN.md, the specification1,763 lines, written before any code

The design document came first, and that is the most useful thing I can tell anyone doing this. Its opening line says no code is written until it is approved, and any later change is made there first. Every class has a job written down against it. Every threshold has a reason. Every rule I set is marked as mine, with the date.

That matters because a model forgets. A long session gets summarised, and the summary keeps the gist and drops the detail, and the detail is where the bugs are. The repository’s own AGENTS.md says it plainly: do not rely on a summary of these files from memory or from an earlier session. The agent goes back to the document. Every time.

Two agents also worked in parallel on the second phase, one on guidance, the map and screens, the other on location, alerts, speech and map markers. Each owned a written list of files, and the interfaces between them were fixed in advance: add, don’t rename. They merged cleanly because the boundary was decided before either started, not discovered afterwards.

Every Hard Rule Came From Something I Saw

The design has a list of hard rules, and not one of them came from a whiteboard. Each came from watching the thing run on the Desktop Head Unit9, Google’s car-screen emulator on the PC, or in the car, and seeing it do something wrong.

Hard ruleWhat I saw that made it a rule
A camera alerts only when it faces your wayalerts for the other carriageway are noise that teaches you to ignore alerts
Nothing on the car screen that does not worktwo stop buttons on screen, one of them dead
No function shown twicethat same pair, plus two re-centre buttons, two speed displays
One cancel, Google’sthe card in the corner with the X is Android Auto’s own, drawn from the trip the app publishes, so the app’s own stop button went
No shake on the car screenthe More screen juddering while the car was parked, because it re-sent an identical screen every second and Android Auto animates every refresh
Every button on the right-hand sidethe map buttons sat top left until the car screen reported its size; now one column down the right edge from the start, nothing of ours on the left
No built-in Maps key, evernobody’s driving gets billed to anyone else

The shake is my favourite, because it is so small and it would have shipped. A live GPS row ticked once a second. Each tick re-sent the whole screen, unchanged, and the host animated it, so every row below jiggled while the car sat still. The fix is one comparison: only redraw when a line has changed. The rule is bigger than the fix. A screen that is holding still must look still, and it is checked with a burst of screenshots that must be identical.

That is the real job when an AI writes the code. It does not get tired and it does not mind rewriting, but it cannot see the car screen. You can. Writing what you saw down as a rule, with the date, is what stops it coming back three sessions later.

What The Code Got Wrong, And How It Was Caught

Plenty. None of it was exotic, and every one was caught by running it rather than reading it:

FaultWhat it didHow it was caught
Route matched to the wrong legGoogle’s route from a parked car went north, U-turned at a roundabout and came back south on the same road. The matcher pinned the car to the northbound leg 10 m away, so every southbound camera was “off road” by over a kilometre. Nothing alerteda scripted drive on the bench; the alert log said offRoad lateral=1204 for every camera
Speech watchdog too shortit allowed 1.5 s plus 70 ms per character. Numbers take longer to say than that, so every second-stage alert was cut off mid-sentencethe speech records from a bench run
A rate limit in the enginewith a three-second window, of two cameras at one junction, one was lost for goodtracing the alerts that went silent on the first real drive
A stale headingthe emulator reports a bearing of 0° whatever you do, so on a southbound road every camera failed the direction checka simulated run down the A61
Limit changes spoken as camera alertsa change of limit ahead was queued as a first-stage camera alertthe speech log on the bench

The second one is worth a pause. Every individual test passed. The code was correct by its own measure. It just had a timeout chosen by somebody who had never heard a phone read a distance out loud. The test that catches that is a real voice, timed, on a real run.

The First Real Drive

On 12th October I put a release build on my phone and took it out in the XPENG G6 over wireless Android Auto. Two things went wrong. A route set while parked cleared itself within seconds of moving off. And some alerts were spoken and some were not, in no pattern I could see.

Then the worse problem. Nothing was left to read. My phone’s ColorOS throws away the app’s log lines, so the drive left no evidence at all. Was it the app, Google’s SDK or Android Auto itself? I could not say.

So the fix for the first drive was not a code change. It was evidence. The app now writes two logs on the phone all the time, one for routing and the map and one for every alert decision, in 15-second batches, plus an optional drive recorder that saves every position so a drive can be replayed on the bench. Then the guesses got fixed, each one written to do less and log that it did. Every way guidance can end now records who ended it.

On the bench since, Android Auto called stop once, 2 minutes 35 seconds into a guided drive. I was clicking round the head unit at the time, so it was most likely the X on its own card. It has not happened with nobody touching the screen. The next drive will settle it, because this time the drive leaves a trail.

What Comes Next

The bench list is still long. The next drives check the cancel button, the bend and wrong-way scenarios, the hand-over between the car’s GPS and the phone’s, and whether the driver’s display in the G6 shows turn cards from a third-party app at all.

Later parts of this series go into the alert engine’s maths properly, the speed limit workarounds, the PocketGPSWorld formats, and the bench itself: how you test an Android Auto app with no car, a scripted GPS and an emulator that thinks every road runs north.

The Machine Types, The Standard Is Yours

I have watched a lot of talk about AI writing code, most of it from people selling it or people frightened of it. What I found is duller than both, and more useful.

It types quickly and it does not get bored. It will rewrite a screen for the fourth time without a sigh. What it will not do is notice that the More screen shakes, or that a sentence was cut off, or that a dead button sits next to a live one. It cannot see the car. Those were mine to see, and the only reason they are fixed is that I wrote each one down as a rule it has to read before it touches anything.

As such, the responsibility does not move. The code is mine because I set the standard it is held to and I am the one in the car. None of what kept it honest is an AI method. Writing the spec before the code, writing down what you learn, and keeping evidence instead of guessing is how proper engineering has always been done. The tool does not change that. It makes it quicker to find out who was skipping it.


  1. Apache License, Version 2.0 — the licence the AutoNavAlerts code is published under. ↩︎

  2. Google — Navigation SDK for Android: Android Auto — the Car App Library provides “a set of visual templates approved for driver safety”, and “Android Auto limits screen surface interaction to a series of SurfaceCallback methods”. ↩︎ ↩︎

  3. Google — Navigation SDK for Android: real-time disruptions — “real-time disruptions are not available on Android Auto”. ↩︎

  4. Google — Navigation SDK for Android: speed alerts — onSpeedingUpdated(float percentageAboveLimit, SpeedAlertSeverity speedAlertSeverity): the percentage over the limit and a severity, not the limit itself. ↩︎

  5. googlemaps/flutter-navigation-sdk issue #726 — “Incident reporting on Android Auto & CarPlay”, opened 17th June 2026, still open. ↩︎

  6. Google Maps Platform — Get started — “you must create a billing-enabled Cloud project and enable the desired APIs or SDKs”. ↩︎

  7. Google — Navigation SDK for Android: set up your project — “A Google Cloud console project with the Navigation SDK enabled.” ↩︎

  8. PocketGPSWorld — the UK speed camera database the app syncs from, with each user’s own subscription. ↩︎

  9. Android Developers — Test using the Desktop Head Unit — Google’s emulator for the Android Auto car screen. ↩︎