Location Links
Show a place on DMD2's map or start navigation to it from your own Android app, with one standard VIEW intent — dmdloc:, geo: or google.navigation:.
com.thorkracing.dmd2launcher
com.thorkracing.dmdplayground
Overview
DMD2 registers for three location URI schemes. Any app on the device can hand it a place with a plain Intent.ACTION_VIEW — no library, no permission, no account.
- Show a pin — DMD2 comes to the front, centres the map on the point, drops a pin and opens the Location Info panel (the same panel a rider gets from a long press, with Navigate To, Save Location and Share). The rider decides what to do next.
- Start navigation — DMD2 comes to the front and starts turn-by-turn guidance to the point, with no pin step in between.
The Three Schemes
| URI | What DMD2 does | Name / label |
|---|---|---|
dmdloc://41.1579,-8.6291dmdloc:41.1579;-8.6291 | Pin + Location Info | No |
geo:41.1579,-8.6291 | Pin + Location Info | No |
geo:0,0?q=41.1579,-8.6291(Ribeira) | Pin + Location Info | Yes — the text in brackets |
google.navigation:q=41.1579,-8.6291 | Starts navigation | No |
dmdloc:is DMD's own scheme. Only DMD2 handles it, so Android never shows a chooser of other map apps.geo:is the standard Android place scheme (RFC 5870 plus Android'sq=form). Other map apps also handle it, so set the package (see Targeting DMD2) if you want DMD2 specifically. RFC 5870 parameters such as;u=35and a zoom such as?z=17are accepted and ignored.google.navigation:is the de-facto “guide me there” scheme. Extra parameters such as&mode=dare accepted and ignored; DMD2 routes with the rider's own route types.
Show a Pin
With a name (recommended when you have one):
// Kotlin
val name = Uri.encode("Ribeira")
val uri = Uri.parse("geo:0,0?q=41.1579,-8.6291($name)")
startActivity(Intent(Intent.ACTION_VIEW, uri).setPackage("com.thorkracing.dmd2launcher"))
Coordinates only, DMD's own scheme:
// Java
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("dmdloc://41.1579,-8.6291"));
startActivity(i);
Start Navigation
// Kotlin
val uri = Uri.parse("google.navigation:q=41.1579,-8.6291")
startActivity(Intent(Intent.ACTION_VIEW, uri).setPackage("com.thorkracing.dmd2launcher"))
What the rider sees:
- DMD2 switches to the map and routes to the point, asking for a route type first if the rider's setup asks for one.
- With no GPS fix yet, DMD2 shows “acquiring GPS” and starts as soon as it has one.
- With navigation already running, DMD2 asks whether to start a new route or add the point to the current one.
Targeting DMD2
Without a package, Android shows a chooser when more than one app handles the URI (always the case for geo: and google.navigation:). To send straight to DMD2, set the package:
| App | Package |
|---|---|
| DMD2 | com.thorkracing.dmd2launcher |
| DMD2 beta | com.thorkracing.dmdplayground |
A rider may have either one, or both. Pick the one that is installed and fall back to a plain intent:
// Kotlin
fun openInDmd(context: Context, uri: Uri) {
val packages = listOf("com.thorkracing.dmd2launcher", "com.thorkracing.dmdplayground")
for (pkg in packages) {
val intent = Intent(Intent.ACTION_VIEW, uri).setPackage(pkg)
try {
context.startActivity(intent)
return
} catch (e: ActivityNotFoundException) {
// not installed: try the next one
}
}
context.startActivity(Intent(Intent.ACTION_VIEW, uri)) // let Android choose
}
On Android 11 and newer, if you check for DMD2 with PackageManager before sending (rather than catching the exception as above), declare it in your manifest:
<queries>
<package android:name="com.thorkracing.dmd2launcher" />
<package android:name="com.thorkracing.dmdplayground" />
</queries>
From a service or another non-activity context, add Intent.FLAG_ACTIVITY_NEW_TASK. DMD2 runs as a single task, so the intent reaches the running map rather than opening a second copy.
Testing with adb
# pin, DMD's own scheme
adb shell am start -a android.intent.action.VIEW -d 'dmdloc://41.1579,-8.6291'
# pin with a name
adb shell am start -a android.intent.action.VIEW -p com.thorkracing.dmd2launcher \
-d 'geo:0,0?q=41.1579,-8.6291(Ribeira)'
# start navigation
adb shell am start -a android.intent.action.VIEW -p com.thorkracing.dmd2launcher \
-d 'google.navigation:q=41.1579,-8.6291'
For the beta app, use -p com.thorkracing.dmdplayground.
Rules & Limits
- Coordinates: decimal degrees, a dot as the decimal separator, latitude then longitude.
geo:0,0on its own (noq=) is treated as “no place”. - Addresses are not supported.
geo:0,0?q=Rua das Flores, Portoorgoogle.navigation:q=<address>would need geocoding, and DMD2 will usually answer “No location found”. Geocode in your own app and send coordinates. - Names: only the
geo:q=lat,lon(Name)form carries one. URL-encode it.dmdloc:andgoogle.navigation:take coordinates only. - No result comes back. These are fire-and-forget; use
startActivity, notstartActivityForResult. - Plain text works too. Sharing text (
ACTION_SEND,text/plain) that contains coordinates or a map link (Google Maps, Apple Maps, Waze, OpenStreetMap, OsmAnd…) also shows a pin — see Open With DMD. The URI schemes above are the reliable choice for apps.