Learn how to find a route and directions with the route service.
Routing is the process of finding the path from an origin to a destination in a street network. You can use the Routing service to find routes, get driving directions, calculate drive times, and solve complicated, multiple vehicle routing problems. To create a route, you typically define a set of stops (origin and one or more destinations) and use the service to find a route with directions. You can also use a number of additional parameters such as barriers and mode of travel to refine the results.
In this tutorial, you define an origin and destination by clicking on the map. These values are used to get a route and directions from the route service. The directions are also displayed on the map.
Prerequisites
Before starting this tutorial:
-
You need an ArcGIS Location Platform or ArcGIS Online account.
-
Confirm that your system meets the minimum system requirements.
-
An IDE for Java.
Steps
Get an access token
You need an access token to use the location services used in this tutorial.
-
Go to the Create an API key tutorial to obtain an access token using your ArcGIS Location Platform or ArcGIS Online account.
-
Ensure that the following privileges are enabled: Location services > Basemaps > Basemap styles service and Location services > Routing.
-
Copy the access token as it will be used in the next step.
To learn more about other ways to get an access token, go to Types of authentication.
Open a Java project with Gradle
-
To start this tutorial, complete the Display a map tutorial, or download and unzip the Display a map solution into a new folder.
-
Open the build.gradle file as a project in IntelliJ IDEA.
-
In IntelliJ IDEA's Project tool window, open src/main/java/com.example.app and double-click App.
-
In the
start()
method, set the API key property on theArcGISRuntimeEnvironment
with your access token. Replace YOUR_ACCESS_TOKEN with your copied access token. Be sure to surround your access token with double quotes as it is a string.App.javaUse dark colors for code blocks ArcGISRuntimeEnvironment.setApiKey("YOUR_ACCESS_TOKEN");
Add import statements and variable declarations
Add import statements and variable declarations to reference the packages and classes required for this tutorial.
-
In IntelliJ IDEA's Project tool window, open src/main/java/com.example.app and double-click App.
-
Add the following imports above the existing imports:
App.javaUse dark colors for code blocks 39 40 41 42 43 44 45 46 47 48 49Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. import com.esri.arcgisruntime.concurrent.ListenableFuture; import com.esri.arcgisruntime.geometry.Geometry; import com.esri.arcgisruntime.mapping.view.Graphic; import com.esri.arcgisruntime.mapping.view.GraphicsOverlay; import com.esri.arcgisruntime.symbology.SimpleLineSymbol; import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol; import com.esri.arcgisruntime.tasks.networkanalysis.Route; import com.esri.arcgisruntime.tasks.networkanalysis.RouteParameters; import com.esri.arcgisruntime.tasks.networkanalysis.RouteResult; import com.esri.arcgisruntime.tasks.networkanalysis.RouteTask; import com.esri.arcgisruntime.tasks.networkanalysis.Stop; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.geometry.Point2D; import javafx.geometry.Pos; import javafx.scene.paint.Color; import javafx.scene.control.Alert; import javafx.scene.control.ListView; import javafx.scene.input.MouseButton; import java.util.List; import com.esri.arcgisruntime.ArcGISRuntimeEnvironment; import com.esri.arcgisruntime.mapping.ArcGISMap; import com.esri.arcgisruntime.mapping.view.MapView; import com.esri.arcgisruntime.mapping.BasemapStyle; import com.esri.arcgisruntime.mapping.Viewpoint; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.stage.Stage;
-
Within the
App
class, add the following member variables to easily reference them from other parts of the application:Member variables ensure that objects are not deallocated while asynchronous methods are executing. If an object is deallocated while one of its asynchronous methods is executing, the completion callback closure will never be called.
App.javaUse dark colors for code blocks 53 54Add line. Add line. Add line. Add line. Add line. private MapView mapView; private Graphic routeGraphic; private RouteTask routeTask; private RouteParameters routeParameters; private final ObservableList<Stop> routeStops = FXCollections.observableArrayList(); private final ListView<String> directionsList = new ListView<>();
Update the map
A streets basemap layer is typically used in routing applications. Update the basemap to use the ARCGIS
basemap style, and change the position of the map to center on Los Angeles.
-
Update the
BasemapStyle
fromARCGIS
to_TOPOGRAPHIC ARCGIS
._STREETS -
Update the latitude and longitude coordinates to center on Los Angeles.
App.javaUse dark colors for code blocks 83 84 85 86 88 89 90 91Change line Change line // create a MapView to display the map and add it to the stack pane mapView = new MapView(); stackPane.getChildren().add(mapView); ArcGISMap map = new ArcGISMap(BasemapStyle.ARCGIS_STREETS); // set the map on the map view mapView.setMap(map); mapView.setViewpoint(new Viewpoint(34.05398, -118.24532, 144447.638572));
Add a UI to display driving directions
To display the turn-by-turn directions from the route, a UI element is required.
-
In the
start()
method, set the maximum size of thedirections
(a JavaFXList List
which will display a vertical list of directions), and then add it to theView stack
.Pane App.javaUse dark colors for code blocks 87 88 89 90 91 92 93Add line. Add line. Add line. ArcGISMap map = new ArcGISMap(BasemapStyle.ARCGIS_STREETS); // set the map on the map view mapView.setMap(map); mapView.setViewpoint(new Viewpoint(34.05398, -118.24532, 144447.638572)); directionsList.setMaxSize(400, 250); stackPane.getChildren().add(directionsList); StackPane.setAlignment(directionsList, Pos.TOP_LEFT);
Add a graphics overlay
A graphics overlay is a container for graphics. Graphics will be added later in this tutorial as a visual means to display the route stops and route result on the map.
-
Create a new
GraphicsOverlay
and add it to themap
.View App.javaUse dark colors for code blocks 94 95 96 97Add line. Add line. directionsList.setMaxSize(400, 250); stackPane.getChildren().add(directionsList); StackPane.setAlignment(directionsList, Pos.TOP_LEFT); GraphicsOverlay graphicsOverlay = new GraphicsOverlay(); mapView.getGraphicsOverlays().add(graphicsOverlay);
Create a route task and route parameters
A task makes a request to a service and returns the results. Use the RouteTask
class to access a routing service. A routing service with global coverage is part of ArcGIS location services. You can also publish custom routing services using ArcGIS Enterprise.
-
Create a
RouteTask(java.lang.String)
with a string URL to reference the routing service.App.javaUse dark colors for code blocks 98 99 100 102Add line. GraphicsOverlay graphicsOverlay = new GraphicsOverlay(); mapView.getGraphicsOverlays().add(graphicsOverlay); routeTask = new RouteTask("https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World");
-
Get default
RouteParameters
objects from theroute
and set the return directions property toTask true
. This specifies that the route results should include turn-by-turn directions. Add a UI text prompt.The
createDefaultParametersAsync()
method is asynchronous and you must handle its completion and check for errors.App.javaUse dark colors for code blocks 101 102Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. routeTask = new RouteTask("https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World"); ListenableFuture<RouteParameters> routeParametersFuture = routeTask.createDefaultParametersAsync(); routeParametersFuture.addDoneListener(() -> { try { routeParameters = routeParametersFuture.get(); routeParameters.setReturnDirections(true); directionsList.getItems().add("Click to add two points to the map to find a route."); } catch (Exception e) { Alert alert = new Alert(Alert.AlertType.ERROR, e.toString()); alert.show(); e.printStackTrace(); } });
Create origin and destination stops
A RouteTask
requires at least a single origin and destination stop to find a route. Use a click handler on the map
to add stops and display them as graphics when the map is clicked.
When a user clicks on the map, a stop will be added to a list of route stops. In this tutorial, the first click will create the origin stop and the second will create the destination stop.
-
Create a new
add
method which adds aStops On Mouse Clicked() set
listener to theOn Mouse Clicked() map
. Convert the clicked JavaFXView Point2
to a locationD Point
. Use the point to create a newStop
and add it to theroute
list.Stops App.javaUse dark colors for code blocks 54 55Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. } private void addStopsOnMouseClicked() { mapView.setOnMouseClicked(event -> { if (event.isStillSincePress() && event.getButton() == MouseButton.PRIMARY) { Point2D mapPoint = new Point2D(event.getX(), event.getY()); routeStops.add(new Stop(mapView.screenToLocation(mapPoint))); } }); }
-
Call
add
in theStops On Mouse Clicked() start()
method.App.javaUse dark colors for code blocks 110 111 112 113 114 115 116Add line. } catch (Exception e) { Alert alert = new Alert(Alert.AlertType.ERROR, e.toString()); alert.show(); e.printStackTrace(); } }); addStopsOnMouseClicked();
-
To display the stops on the map as they are added, add a listener to the
route
Stops Observable
and create a newList SimpleMarkerSymbol
for eachStop
. Use thestop
's geometry to create a newGraphic
and add it to thegraphics
.Overlay App.javaUse dark colors for code blocks 117 118Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. addStopsOnMouseClicked(); routeStops.addListener((ListChangeListener<Stop>) e -> { // tracks the number of stops added to the map, and use it to create graphic geometry and symbol text int routeStopsSize = routeStops.size(); // handle user interaction if (routeStopsSize == 0) { return; } else if (routeStopsSize == 1) { graphicsOverlay.getGraphics().clear(); if (!directionsList.getItems().isEmpty()) directionsList.getItems().clear(); directionsList.getItems().add("Click to add two points to the map to find a route."); } // create a blue circle symbol for the stop SimpleMarkerSymbol stopMarker = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, Color.BLUE, 20); // get the stop's geometry Geometry routeStopGeometry = routeStops.get(routeStopsSize-1).getGeometry(); graphicsOverlay.getGraphics().add(new Graphic(routeStopGeometry, stopMarker)); });
Find and display the route
To find the route between the origin and destination, set the stops on the route parameters and solve the route using the RouteTask
. Display the route result on the map as a graphic.
-
When an origin and destination stop have been created, set them on the
route
.Parameters App.javaUse dark colors for code blocks 136 137Add line. Add line. Add line. Add line. Add line. Add line. graphicsOverlay.getGraphics().add(new Graphic(routeStopGeometry, stopMarker)); if (routeStopsSize == 2) { // remove the mouse clicked event if two stops have been added mapView.setOnMouseClicked(null); routeParameters.setStops(routeStops); }
-
Solve (find) the route based on the provided route parameters to obtain a
RouteResult
. The result is a collection of computed routes. Then, get the list ofRoute
objects from the result. Each element represents an independent route with its own driving directions. The routing service only returns the optimal route.The
solveRouteAsync()
method is asynchronous and you must handle its completion, check for errors, and confirm that a populated list ofRoute
objects has been returned.App.javaUse dark colors for code blocks 138 139 140 141 142 149 142 143Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. if (routeStopsSize == 2) { // remove the mouse clicked event if two stops have been added mapView.setOnMouseClicked(null); routeParameters.setStops(routeStops); // get the route and display it ListenableFuture<RouteResult> routeResultFuture = routeTask.solveRouteAsync(routeParameters); routeResultFuture.addDoneListener(() -> { try { RouteResult result = routeResultFuture.get(); List<Route> routes = result.getRoutes(); } catch (Exception ex) { ex.printStackTrace(); } }); }
-
Check that a route was returned, and retrieve the first one. Display this route to the map by creating a new
Graphic
using the route'sGeometry
and aSimpleLineSymbol
, and add it to thegraphics
.Overlay App.javaUse dark colors for code blocks 143 144 145 146 147 148 149Add line. Add line. Add line. Add line. Add line. Add line. Add line. // get the route and display it ListenableFuture<RouteResult> routeResultFuture = routeTask.solveRouteAsync(routeParameters); routeResultFuture.addDoneListener(() -> { try { RouteResult result = routeResultFuture.get(); List<Route> routes = result.getRoutes(); if (!routes.isEmpty()) { Route route = routes.get(0); Geometry shape = route.getRouteGeometry(); routeGraphic = new Graphic(shape, new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLUE, 2)); graphicsOverlay.getGraphics().add(routeGraphic); }
Get directions
You can get driving directions from the route service with the setReturnDirections()
method on RouteParameters
. This property was set to true in the Create a route task and route parameters section of this tutorial.
-
To display the driving directions, get each
DirectionManeuver
from theroute
, and add them to thedirections
.List App.javaUse dark colors for code blocks 150 151 152 153 154 155Add line. Add line. Add line. Add line. Add line. if (!routes.isEmpty()) { Route route = routes.get(0); Geometry shape = route.getRouteGeometry(); routeGraphic = new Graphic(shape, new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLUE, 2)); graphicsOverlay.getGraphics().add(routeGraphic); // get the direction text for each maneuver and display it as a list in the UI route.getDirectionManeuvers().forEach(step -> directionsList.getItems().add(step.getDirectionText())); // reset stops and re-enable mapview interactions once the route task has completed routeStops.clear(); addStopsOnMouseClicked();
-
Run the app. Ensure to run the app as a Gradle task and not as an application in your IDE. In the Gradle tool window, under Tasks > application, double-click run.
The map should support two clicks to create an origin and destination point and then use the route service to display the resulting route and turn-by-turn directions.
What's next?
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: