-
-
Platform Overview Platform Overview
High-precision data and advanced tooling in one place
-
Maps & Data Maps & Data
Build high-quality maps using fresh location data
Maps & Data-
Map Data Map Data
Create fresh, accurate maps and layer global information
-
Dynamic Map Content Dynamic Map Content
Explore industry-leading map content
-
Maps for ADAS & HAD Maps for ADAS & HAD
Help vehicles see beyond sensors with location data sources
-
-
Services Services
Browse our extensive range of services and APIs
Services-
Routing Routing
Make journey planning easier with our routing portfolio
-
Geocoding & Search Geocoding & Search
Translate addresses into accurate geocoordinates
-
Map Rendering Map Rendering
Highly customizable graphics and real-time map data
-
Positioning Positioning
Pinpoint devices and assets locations with precision
-
-
Tools Tools
Build solutions with our flexible developer tools and applications
Tools-
HERE Studio HERE Studio
Visualize, style and edit location data
-
HERE Workspace HERE Workspace
Create location-centric products and services in one space
-
HERE Marketplace HERE Marketplace
Source, buy, sell and trade location assets
-
HERE SDK HERE SDK
Build advanced location-enabled applications
-
HERE Live Sense SDK HERE Live Sense SDK
Enhance driver awareness by using AI
-
HERE Anonymizer HERE Anonymizer
Maximize location data while supporting regulatory compliance
-
-
Capabilities Capabilities
Everything you need for your location-related use case
Capabilities-
Visualize Data Visualize Data
Identify complex trends and patterns
-
Generate Insights Generate Insights
Transform location data into compelling stories
-
Build Applications Build Applications
Create feature-rich products designed for business
-
Develop Services Develop Services
Produce tailored service experiences
-
Make Maps Make Maps
Create and use custom digital maps
-
-
-
-
By Market By MarketBy Market
-
Automated Driving Automated Driving
-
Connected Driving Connected Driving
-
Fleet Management Fleet Management
-
Supply Chain Supply Chain
-
Urban Mobility Urban Mobility
-
Infrastructure Planning Infrastructure Planning
-
Public Safety Public Safety
-
-
By Applications By ApplicationsBy Applications
-
HERE Last Mile HERE Last Mile
Optimize your last mile deliveries
-
HERE Asset Tracking HERE Asset Tracking
Track assets in real-time with our end-to-end solution
-
HERE Navigation HERE Navigation
Use our off-the shelf navigation system
-
HERE WeGo HERE WeGo
Enjoy your journey with our new navigation app
-
-
-
-
Partner with HERE Partner with HERE
-
Partner Network Partner Network
-
-
Pricing Pricing
-
-
Documentation Documentation
-
Tutorials Tutorials
-
Code Examples Code Examples
-
Knowledge Base Knowledge Base
-
Developer Blog Developer Blog
-
-
-
About us About us
-
Events Events
-
News News
-
Press Releases Press Releases
-
Careers Careers
-
Sustainability Sustainability
-
Leadership Leadership
-
Investors Investors
-
HERE360 Blog HERE360 Blog
-
Electric Vehicle Features in the HERE SDKs for Android, iOS, and Flutter

It’s been over a year now since we released the latest version of the HERE SDKs for iOS, Android, and Flutter. Since then, we’ve added even more cool new features and capabilities. Today I want to highlight some of those features, specifically those focused on use cases for electric vehicles.
In this blog post we will look at how to:
- Using the routing feature for electric vehicles
- Determine the reachable area of an electric vehicle given a remaining range or battery charge
- Search for charging stations along a route
Before we get started, I want to point out that you can see all of these features in action in our “EVRouting” example in on GitHub. Go ahead and grab this for a running demo plus full code of everything we will be talking about below.
Electric Vehicle Routing
Let’s get started with the Routing API. A call to the Routing API in EV mode is fundamentally the same as any other call to the Routing API, except that we are using an EVCarOptions object to define the vehicle parameters. This does turn out to be a little more involved than usually, as there are quite a few parameters we can set.
Here’s an example for setting the parameters in EVCarOptions. (Note that this example is for Android, but all the features discussed here are also available on the HERE SDKs for Flutter and iOS.)
EVCarOptions evCarOptions = new EVCarOptions();
evCarOptions.consumptionModel.ascentConsumptionInWattHoursPerMeter = 9;
evCarOptions.consumptionModel.descentRecoveryInWattHoursPerMeter = 4.3;
evCarOptions.consumptionModel.freeFlowSpeedTable = new HashMap<Integer, Double>() {{
put(0, 0.239);
put(27, 0.239);
put(60, 0.196);
put(90, 0.238);
}};
evCarOptions.ensureReachability = true;
evCarOptions.routeOptions.optimizationMode = OptimizationMode.FASTEST;
evCarOptions.routeOptions.alternatives = 0;
evCarOptions.batterySpecifications.connectorTypes =
new ArrayList<ChargingConnectorType>(Arrays.asList(ChargingConnectorType.TESLA,
ChargingConnectorType.IEC_62196_TYPE_1_COMBO, ChargingConnectorType.IEC_62196_TYPE_2_COMBO));
evCarOptions.batterySpecifications.totalCapacityInKilowattHours = 80.0;
evCarOptions.batterySpecifications.initialChargeInKilowattHours = 10.0;
evCarOptions.batterySpecifications.targetChargeInKilowattHours = 72.0;
evCarOptions.batterySpecifications.chargingCurve = new HashMap<Double, Double>() {{
put(0.0, 239.0);
put(64.0, 111.0);
put(72.0, 1.0);
}};
The first three parameters are required to make any EV routing call. The free flow table defines the energy consumption of the vehicle as a curve using pairs of speed (km/h) and consumption (Wh/m) values. In addition, the ascent consumption and descent recovery values indicate what effect inclines have on the battery (in Wh/m).
By default, the Routing API will assume that you have enough charge to reach any given destination. Given that range anxiety and charging infrastructure are still issues, we may also want to take the vehicles battery charge and the location of compatible charging points into account. That why thingsget interesting when you turn on ensureReachability. With this parameter, the Routing API will automatically route you to charging points where necessary and even take the charging time into account when calculating arrival time. Neat!
However, when using this feature, you must provide some additional parameters. These include the total capacity of the battery (in kWh), the charging connector types available on the vehicle, and a battery charging curve. This curve is provided as a list of charging rate (in kW), charge level (in kWh) pairs. In addition, you must provide an initial charge level and a target charge level. These are the respective battery charge levels at the first and last waypoints. (Providing a target charge level ensures you don’t strand your users at their destination with an empty battery.)
Check out the SDK documentation for full details on these parameters. The API Reference of the underlying Routing REST API can also be helpful.
EV Reachability
The range of EVs remains a major concern, both when purchasing and using electric vehicles. The Isoline Routing feature of the SDKs allows you to calculate the area an EV can reach given a current battery level.
Let’s say you are in the city center Berlin and you want to calculate which area you can potentially reach with an energy budget of 400 Wh. Once again, using Isoline Routing based on battery charge is very similar to making a standard Isoline Routing call. In fact, you can check out my recent blog post on Isoline Routing with Android for details on how to do this. The only thing we need to change is the range type in the calculation options and provide an appropriate value for battery charge. Here’s a complete example of how to call the Isoline Routing feature with a consumption-based range type.
List<Integer> rangeValues = Collections.singletonList(400);
Integer maxPoints = null;
IsolineOptions.Calculation calculationOptions =
new IsolineOptions.Calculation(IsolineRangeType.CONSUMPTION_IN_WATT_HOURS, rangeValues, IsolineCalculationMode.BALANCED, maxPoints);
IsolineOptions isolineOptions = new IsolineOptions(calculationOptions, getEVCarOptions());
routingEngine.calculateIsoline(new Waypoint(startGeoCoordinates), isolineOptions, new CalculateIsolineCallback() {
@Override
public void onIsolineCalculated(RoutingError routingError, List<Isoline> list) {
if (routingError != null) {
showDialog("Error while calculating reachable area:", routingError.toString());
return;
}
Isoline isoline = list.get(0);
for (GeoPolygon geoPolygon : isoline.getPolygons()) {
Color fillColor = Color.valueOf(0, 0.56f, 0.54f, 0.5f); // RGBA
MapPolygon mapPolygon = new MapPolygon(geoPolygon, fillColor);
mapView.getMapScene().addMapPolygon(mapPolygon);
mapPolygons.add(mapPolygon);
}
}
});
Note that this example shows how to visualize the reachable area on the map, however you can also use the result to match the area against a list of possible customers in a delivery use case, to find charging stations inside the area, and much more.
Charging Stations Along a Route
As we’ve seen above, the Routing API will automatically search for charging points along a route and even integrate them into the route for you if necessary. However, what if we have a given route and want to search for charging points manually? That is where the Search feature of the SDK comes in handy. In addition to searching near a given location, or within a bounding box, it also allows us to search along a GeoCorridor. This corridor can be defined by a GeoPolyline and a radius (in meters). Of course, this is useful for everything from gas stations to restaurants, but in the example below we will search for charging points.
int radiusInMeters = 200;
GeoCorridor routeCorridor = new GeoCorridor(route.getPolyline(), radiusInMeters);
TextQuery textQuery = new TextQuery("charging station", routeCorridor,
mapView.getCamera().getState().targetCoordinates);
int maxItems = 30;
SearchOptions searchOptions = new SearchOptions(LanguageCode.EN_US, maxItems);
searchEngine.search(textQuery, searchOptions, new SearchCallback() {
@Override
public void onSearchCompleted(SearchError searchError, List<Place> items) {
if (searchError != null) {
if (searchError == SearchError.POLYLINE_TOO_LONG) {
Log.d("Search", "Route too long or route corridor radius too small.");
} else {
Log.d("Search", "No charging stations found along the route. Error: " + searchError);
}
return;
}
Log.d("Search","Search along route found " + items.size() + " charging stations:");
for (Place place : items) {
if (chargingStationsIDs.contains(place.getId())) {
Log.d("Search", "Skipping: This charging station was already required to reach the destination.");
} else {
addCircleMapMarker(place.getGeoCoordinates(), R.drawable.charging);
Log.d("Search", place.getAddress().addressText);
}
}
}
});
First, we define a GeoCorridor by providing our route as a polyline (which we could get from the Routing API or any other data source) and the search radius of 200m. This means that we will only search for results which are no more than 200 meters away from our route. Then we simply provide this corridor as a search area for a TextQuery and make a normal search request using this query.
I’ll close with another reminder to check out the “EVRouting” example on GitHub. Also check out our Routing API Demo Client. While this uses the underlying REST API and not the SDK directly, it is a great way to experiment with the various charge and battery parameters, visualize the curves, and see how they affect the routing results.
Have your say
Sign up for our newsletter
Why sign up:
- Latest offers and discounts
- Tailored content delivered weekly
- Exclusive events
- One click to unsubscribe