Public Transit Routing API do not render correctly when combining with Android SDK
Products and versions
HERE Public Transit Routing API v8
HERE SDK for Android
The original sample uses legacy HERE Mobile SDK for Android Premium-style classes such as GeoCoordinate, MapPolyline, GeoPolyline, MapLabeledMarker, and IconCategory. Current HERE SDK for Android 4.x uses different map item, geometry, and rendering classes.
Symptoms
Public transit route sections are returned by the REST API, but no transit line appears on the Android map.
Bus, subway, train, or pedestrian sections appear with the same styling instead of mode-specific colors.
Intermediate stops are missing, duplicated, or shown without names or departure times.
The app crashes while reading polyline, transport, intermediateStops, departure, place, or location from the JSON response.
Flexible polyline values from the API response are not decoded into valid map coordinates.
Code copied from an older mSDK sample does not compile in HERE SDK 4.x because map object classes have changed.
Answer
Use HERE Public Transit Routing API v8 to request route sections with return=polyline,intermediate,actions,travelSummary, decode each section’s HERE flexible polyline, and render the resulting coordinates with the map objects available in the Android SDK version used by the application. If the application uses HERE SDK 4.x, do not copy legacy mSDK rendering classes directly; adapt the rendering step to HERE SDK 4.x map polylines, map markers, metadata, and image icons.
Root cause
HERE Public Transit Routing API v8 is a REST API that returns a JSON route model. The Android SDK renders map content, but it does not automatically convert the transit API response into route lines, transit-mode styling, stop markers, labels, or departure-time callouts. The application must parse the API response, decode each section polyline, select styling based on transport.mode, and create map objects manually. Older examples may also assume legacy Mobile SDK classes and synchronous object models that are not compatible with current HERE SDK for Android 4.x.
Impact
The route calculation can succeed while the map still appears incomplete or incorrect. You may see missing public transit lines, incorrect colors, absent intermediate stops, no stop labels, or crashes caused by optional fields that are not present in every response. This commonly occurs when only the first route is handled, when intermediateStops is assumed to exist for all section types, or when the application does not check the section transport mode before parsing transit-specific fields.
Recommended actions
1. Build the Public Transit Routing API v8 request with the required fields:
* origin
* destination
* return=polyline,intermediate,actions,travelSummary
* a securely stored API key or token
2. Do not hard-code or publish API keys in source code, logs, screenshots, repositories, or KB samples. Store credentials securely and rotate any key that was exposed.
3. Parse the response defensively:
* Read routes and select the desired route.
* Iterate through sections.
* Check whether transport.mode exists before applying style logic.
* Check whether polyline exists before decoding.
* Check whether intermediateStops exists before iterating.
* Use optional-field handling for stop names, departure times, and place locations.
4. Decode the section polyline using the HERE flexible polyline decoder:
* Reference: HERE flexible polyline GitHub repository
* Reference: HERE flexible polyline documentation
5. Render each section using mode-specific styling. A common approach is:
* BUS: yellow or service-line color from the response when available
* SUBWAY or METRO: red or agency/service-line color when available
* RAIL or TRAIN: green, purple, or service-line color when available
* TRAM: orange or service-line color when available
* PEDESTRIAN: blue or gray dashed line
6. Render intermediate stops only for section types that contain stop data. For each stop, extract:
* departure.place.location.lat
* departure.place.location.lng
* departure.place.name
* departure.time, when available
7. Attach stop metadata to the marker so the application can display stop name and departure time in a tap handler, custom callout, bottom sheet, or info panel.
8. For HERE SDK for Android 4.x, replace legacy map classes with the equivalent SDK 4.x classes. The API response parsing and flexible polyline decoding logic can remain conceptually the same, but the map rendering layer must use the SDK 4.x map item APIs.
Expected behavior
A successful integration displays one or more route sections on the map. Each transit mode can be styled separately, and intermediate stops can be shown with icons representing bus stops, metro stations, rail stations, tram stops, or walking segments. When a user selects a stop marker, the application can show the stop name and live or scheduled departure time if that information is present in the Public Transit Routing API response.
Unexpected behavior
It is not expected that the Android SDK automatically renders a Public Transit Routing API v8 REST response. It is also not expected that every section contains intermediateStops, every stop contains a departure time, or every transport.mode maps directly to only BUS, SUBWAY, or PEDESTRIAN. Applications must handle additional modes and missing optional fields gracefully.
Implementation guidance
Use a networking library such as Volley, OkHttp, Retrofit, or the platform HTTP client to call the Public Transit Routing API v8 endpoint. After receiving the JSON response, decode the flexible polyline for each route section and convert the decoded latitude and longitude values into the coordinate type required by the SDK version in use. Add the route line to the map with the desired color and width. Then add stop markers for available intermediate stops and store the stop JSON or a structured stop object as marker metadata.
Legacy Android mSDK-style pseudocode<br />JSONArray routes = response.getJSONArray("routes");JSONObject route = routes.getJSONObject(0);JSONArray sections = route.getJSONArray("sections");for (int i = 0; i < sections.length(); i++) { JSONObject section = sections.getJSONObject(i); if (!section.has("polyline")) { continue; } JSONObject transport = section.optJSONObject("transport"); String mode = transport != null ? transport.optString("mode", "UNKNOWN").toUpperCase() : "UNKNOWN"; String flexiblePolyline = section.getString("polyline"); List decoded = flexiblePolylineEncoderDecoder.decode(flexiblePolyline); List coordinates = new ArrayList<>(); for (FlexiblePolylineEncoderDecoder.LatLngZ point : decoded) { coordinates.add(new GeoCoordinate(point.lat, point.lng)); } MapPolyline mapPolyline = new MapPolyline(new GeoPolyline(coordinates)); switch (mode) { case "BUS": mapPolyline.setLineColor(-256); break; case "SUBWAY": case "METRO": mapPolyline.setLineColor(-65536); break; case "RAIL": case "TRAIN": mapPolyline.setLineColor(-16711936); break; case "PEDESTRIAN": mapPolyline.setLineColor(-16776961); break; default: mapPolyline.setLineColor(-7829368); break; } mapPolyline.setLineWidth(13); mapPolylineList.add(mapPolyline); JSONArray intermediateStops = section.optJSONArray("intermediateStops"); if (intermediateStops == null) { continue; } for (int j = 0; j < intermediateStops.length(); j++) { JSONObject stop = intermediateStops.getJSONObject(j); JSONObject departure = stop.optJSONObject("departure"); if (departure == null) { continue; } JSONObject place = departure.optJSONObject("place"); if (place == null) { continue; } JSONObject location = place.optJSONObject("location"); if (location == null) { continue; } double lat = location.optDouble("lat"); double lng = location.optDouble("lng"); String name = place.optString("name", "Transit stop"); String departureTime = departure.optString("time", ""); MapLabeledMarker marker = new MapLabeledMarker(new GeoCoordinate(lat, lng)); if ("BUS".equals(mode)) { marker.setIcon(IconCategory.BUS_STATION); } else if ("SUBWAY".equals(mode) || "METRO".equals(mode)) { marker.setIcon(IconCategory.METRO_STATION); } marker.setTag(stop); mapLabeledMarkerList.add(marker); }}`m_map.addMapObjects(mapPolylineList);m_map.addMapObjects(mapLabeledMarkerList);<br />
Notes
This pseudocode reflects the legacy Android mSDK-style rendering model. For HERE SDK for Android 4.x, use the SDK 4.x map polyline and marker APIs instead.
Do not include the API key directly in the URL sample. Use a placeholder such as {API_KEY} in documentation and store the real value securely in the application.
The first returned route is not always the preferred customer-facing route. If the application exposes multiple itinerary choices, iterate through all objects in routes.
If live departure information is unavailable, display the scheduled time or omit the time label instead of showing an empty value.
Public transit availability, stop metadata, route geometry, and live departure content depend on regional transit coverage and provider data.
References
HERE Public Transit Routing API v8 documentation
HERE flexible polyline GitHub repository
HERE flexible polyline documentation
* Sample repository referenced by the original article
Search keywords
HERE Public Transit Routing API v8, HERE SDK Android, HERE Mobile SDK, mSDK, transit route polyline, flexible polyline, intermediate stops, bus stop marker, metro station marker, subway route rendering, transit departure time, transport mode, route sections, Android map polyline, public transit REST API
Updated 3 days ago