OsmAnd is an open-source offline map and navigation app for Android, based on OpenStreetMap data.

In my experience, OsmAnd's voice navigation is the most polished of all open-source Android navigation apps. However, it has a frustrating habit of always announcing street names in conjunction with their associated route numbers (highway numbers) – e.g. ‘Turn right onto Route 23, Main Street’.

In Australia, particularly in metropolitan areas, this makes little sense, as route numbers are very infrequently referred to in common speech.1 I can think of very few counterexamples, e.g. the M1 in Melbourne (but ‘Monash Freeway’ would be equally understood) or Highway 1 (but the street name would arguably still be more helpful for navigation purposes).

Worse yet, route numbers in Australia are frequently coded in OpenStreetMap only using numbers, with no prefix as to type. This results, for example, in the bizarre direction ‘Turn right onto 23 Clayton Road’, rather than the more correct (but wordier!) ‘Turn right onto State Route 23, Clayton Road’.

Thankfully, OsmAnd's voice navigation is highly extensible, and it is easy to remedy this issue.

How to

The OsmAnd technical help page helpfully provides details on how to modify TTS (text-to-speech) voice guidance configurations.

On the Android phone, we navigate to /sdcard/Android/data and access the OsmAnd data folder (in my case, net.osmand.plus). We then navigate to files/voice, where we locate the definitions for the various TTS voices, for example, en-gb-tts for English (UK) voice (or en-tts for the English (US) voice).

Per my suggestion here, we can copy the en-gb-tts/en-gb_tts.js file to a new directory, en-gb–noref-tts/en-gb–noref_tts.js (for English (US) TTS, we would use en—noref-tts/en—noref_tts.js. noref is an arbitrary identifier to differentiate this from the stock voice, and the extra hyphens are to prevent it from being parsed as part of the TTS language code.

We now locate the function assemble_street_name. For example:

function assemble_street_name(streetName) {
// ...
	if (streetName["toDest"] === "") {
		return streetName["toRef"] + " " + streetName["toStreetName"];
	} else if (streetName["toRef"] === "") {
		return streetName["toStreetName"] + " " + dictionary["toward"] + " " + streetName["toDest"];
	} else if (streetName["toRef"] != "") {
		return streetName["toRef"] + " " + dictionary["toward"] + " " + streetName["toDest"];
	}
}

As we can see, this function is responsible for stringing together the route number (toRef) and street name (toStreetName). We can easily modify the function to omit the route number if there is a valid street name:

function assemble_street_name(streetName) {
// ...
	if (streetName["toDest"] === "") {
		return (streetName["toStreetName"] !== "" ? streetName["toStreetName"] : streetName["toRef"]);
	} else {
		return (streetName["toStreetName"] !== "" ? streetName["toStreetName"] : streetName["toRef"]) + " " + dictionary["toward"] + " " + streetName["toDest"];
	}
}

Now we can simply activate the en-gb–noref-tts voice from Navigation settingsVoice prompts in the Driving profile of OsmAnd, and OsmAnd will no longer pester us with unnecessary route numbers.

Footnotes

  1. At the time of writing, the top result on Google for "state route" numbers melbourne reddit is ‘Who uses State Route numbers??’