I’m using the Google Navigation SDK for Android together with the Routes API - directions/v2:computeRoutes. From computeRoutes I get two routes: the default one and an alternate. I want to navigate using the alternate (not the fastest), so I take its routeToken and pass it to the navigator.
However, even when I redeem the token and start guidance, the SDK still navigates along what looks like the fastest route (highway) instead of the alternate route I picked.
Minimal code (simplified):
@SuppressLint("MissingPermission")
private fun startNavigationWithRouteToken(originLat: Double, originLng: Double) {
val token = routeTokenArg ?: return toast("Missing route token")
if (!::navigator.isInitialized) return toast("Navigator not ready yet")
if (!mLocationPermissionGranted) return toast("Location permission required")
val destLat = destLatArg ?: return toast("Missing destination lat")
val destLng = destLngArg ?: return toast("Missing destination lng")
val currentLatLng = getCurrentDeviceLatLng()
val isNearOrigin = currentLatLng != null && metersBetween(
currentLatLng.latitude, currentLatLng.longitude,
originLat, originLng
) < 100 // Example threshold: 100 meters
if (isNearOrigin) {
// User is close to the route's original start. Redeem the token.
Log.d(TAG, "User is near origin. Attempting to redeem route token.")
val originWp = Waypoint.Builder().setLatLng(originLat, originLng).build()
val destWp = Waypoint.Builder().setLatLng(destLat, destLng).build()
val custom = CustomRoutesOptions.builder()
.setRouteToken(token)
.setTravelMode(CustomRoutesOptions.TravelMode.DRIVING)
.build()
navigator.setDestinations(listOf(originWp, destWp), custom)
.setOnResultListener { code ->
if (code == Navigator.RouteStatus.OK) {
Log.d(TAG, "Token redemption successful. Starting guidance.")
navigator.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE)
navigator.startGuidance()
} else {
Log.e(TAG, "Token redemption failed ($code). Falling back to live route.")
toast("Failed to use preferred route. Starting live navigation.")
}
}
} else {
// User is NOT near the origin. Don't use the token;
Log.d(TAG, "User is not near origin. Starting live navigation without token.")
toast("Starting live navigation from current location.")
}
}
What I expect: The Navigator follows the route described by the routeToken from the alternate route I selected.
What actually happens: Guidance starts, but the SDK appears to choose the fastest route instead of the alternative one.
Logs I see:
User is near origin. Attempting to redeem route token.
Token redemption successful. Starting guidance.
Difference between routes:
1st distance 79 kilometers, duration 52 min 34 sec
2nd (Alernate) distance 57 kilometers, duration 1 hour
What I’ve tried:
Using the routeToken from the alternate route with setDestinations(..., CustomRoutesOptions).
(Alternative approach) Converting the entire chosen polyline into many stopover waypoints and calling setDestinations(waypoints, RoutingOptions). This roughly forces the path, but I don’t like this solution—it's brittle, hits waypoint limits, and defeats the purpose of using route tokens.
Questions:
1.) Is setDestinations(listOf(origin, dest), CustomRoutesOptions(routeToken)) the correct way to redeem a token for a route that starts at that origin? Or should I pass only the destination waypoint when using a routeToken (i.e., origin comes from current GPS and must not be supplied as a waypoint)?
2.) Does the routeToken guarantee that the Navigator will follow the exact path, or is it only a plan/objective that the SDK can adjust (e.g., due to traffic, incidents, or slight start-location differences)?
3.) If I want to force the alternate route I picked (not the fastest), what is the supported way to do that with Navigation SDK?
Any guidance or official docs clarifying how to make the Navigator respect the selected route (vs. re-choosing the fastest) would be greatly appreciated.