Show optimized directions on map
NOTE
This example is a part of the Mapbox Android Demo app. You can find the values for all referenced resources in the res
directory. For example, see res/values/activity_strings.xml
for R.string.*
references used in this example.
Optimization API pricing
Products used within the Mapbox Java SDK, including the Optimization API, are individually billed. For pricing information, see the documentation for the Optimization API.
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:mapbox="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".examples.javaservices.DirectionsActivity"> <com.mapbox.mapboxsdk.maps.MapViewandroid:id="@+id/mapView"android:layout_width="match_parent"android:layout_height="match_parent"mapbox:mapbox_cameraTargetLat="59.9342802"mapbox:mapbox_cameraTargetLng="30.335098600000038"mapbox:mapbox_cameraZoom="11"/> </FrameLayout>
package com.mapbox.mapboxandroiddemo.examples.javaservices; import android.graphics.BitmapFactory;import android.graphics.Color;import android.os.Bundle;import android.widget.Toast; import com.mapbox.api.directions.v5.DirectionsCriteria;import com.mapbox.api.directions.v5.models.DirectionsRoute;import com.mapbox.api.optimization.v1.MapboxOptimization;import com.mapbox.api.optimization.v1.models.OptimizationResponse;import com.mapbox.geojson.Feature;import com.mapbox.geojson.FeatureCollection;import com.mapbox.geojson.LineString;import com.mapbox.geojson.Point;import com.mapbox.mapboxandroiddemo.R;import com.mapbox.mapboxsdk.Mapbox;import com.mapbox.mapboxsdk.geometry.LatLng;import com.mapbox.mapboxsdk.maps.MapView;import com.mapbox.mapboxsdk.maps.MapboxMap;import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;import com.mapbox.mapboxsdk.maps.Style;import com.mapbox.mapboxsdk.style.layers.LineLayer;import com.mapbox.mapboxsdk.style.layers.SymbolLayer;import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; import java.util.ArrayList;import java.util.List; import androidx.annotation.NonNull;import androidx.appcompat.app.AppCompatActivity;import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;import timber.log.Timber; import static com.mapbox.core.constants.Constants.PRECISION_6;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth; /*** Use Mapbox Java Services to request and compare normal directions with time optimized directions.*/public class OptimizationActivity extends AppCompatActivity implements OnMapReadyCallback,MapboxMap.OnMapClickListener, MapboxMap.OnMapLongClickListener { private static final String ICON_GEOJSON_SOURCE_ID = "icon-source-id";private static final String FIRST = "first";private static final String ANY = "any";private static final String TEAL_COLOR = "#23D2BE";private static final float POLYLINE_WIDTH = 5;private MapView mapView;private MapboxMap mapboxMap;private DirectionsRoute optimizedRoute;private MapboxOptimization optimizedClient;private List<Point> stops = new ArrayList<>();private Point origin; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); // Mapbox access token is configured here. This needs to be called either in your application// object or in the same activity which contains the mapview.Mapbox.getInstance(this, getString(R.string.access_token)); // This contains the MapView in XML and needs to be called after the access token is configured.setContentView(R.layout.activity_javaservices_optimization); // Add the origin Point to the listaddFirstStopToStopsList(); // Setup the MapViewmapView = findViewById(R.id.mapView);mapView.onCreate(savedInstanceState);mapView.getMapAsync(this);} @Overridepublic void onMapReady(@NonNull final MapboxMap mapboxMap) {this.mapboxMap = mapboxMap;mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) {// Add origin and destination to the mapboxMapinitMarkerIconSymbolLayer(style);initOptimizedRouteLineLayer(style);Toast.makeText(OptimizationActivity.this, R.string.click_instructions, Toast.LENGTH_SHORT).show();mapboxMap.addOnMapClickListener(OptimizationActivity.this);mapboxMap.addOnMapLongClickListener(OptimizationActivity.this);}});} private void initMarkerIconSymbolLayer(@NonNull Style loadedMapStyle) {// Add the marker image to maploadedMapStyle.addImage("icon-image", BitmapFactory.decodeResource(this.getResources(), R.drawable.red_marker)); // Add the source to the map loadedMapStyle.addSource(new GeoJsonSource(ICON_GEOJSON_SOURCE_ID,Feature.fromGeometry(Point.fromLngLat(origin.longitude(), origin.latitude())))); loadedMapStyle.addLayer(new SymbolLayer("icon-layer-id", ICON_GEOJSON_SOURCE_ID).withProperties(iconImage("icon-image"),iconSize(1f),iconAllowOverlap(true),iconIgnorePlacement(true),iconOffset(new Float[] {0f, -7f})));} private void initOptimizedRouteLineLayer(@NonNull Style loadedMapStyle) {loadedMapStyle.addSource(new GeoJsonSource("optimized-route-source-id"));loadedMapStyle.addLayerBelow(new LineLayer("optimized-route-layer-id", "optimized-route-source-id").withProperties(lineColor(Color.parseColor(TEAL_COLOR)),lineWidth(POLYLINE_WIDTH)), "icon-layer-id");} @Overridepublic boolean onMapClick(@NonNull LatLng point) {// Optimization API is limited to 12 coordinate setsif (alreadyTwelveMarkersOnMap()) {Toast.makeText(OptimizationActivity.this, R.string.only_twelve_stops_allowed, Toast.LENGTH_LONG).show();} else {Style style = mapboxMap.getStyle();if (style != null) {addDestinationMarker(style, point);addPointToStopsList(point);getOptimizedRoute(style, stops);}}return true;} @Overridepublic boolean onMapLongClick(@NonNull LatLng point) {stops.clear();if (mapboxMap != null) {Style style = mapboxMap.getStyle();if (style != null) {resetDestinationMarkers(style);removeOptimizedRoute(style);addFirstStopToStopsList();return true;}}return false;} private void resetDestinationMarkers(@NonNull Style style) {GeoJsonSource optimizedLineSource = style.getSourceAs(ICON_GEOJSON_SOURCE_ID);if (optimizedLineSource != null) {optimizedLineSource.setGeoJson(Point.fromLngLat(origin.longitude(), origin.latitude()));}} private void removeOptimizedRoute(@NonNull Style style) {GeoJsonSource optimizedLineSource = style.getSourceAs("optimized-route-source-id");if (optimizedLineSource != null) {optimizedLineSource.setGeoJson(FeatureCollection.fromFeatures(new Feature[] {}));}} private boolean alreadyTwelveMarkersOnMap() {return stops.size() == 12;} private void addDestinationMarker(@NonNull Style style, LatLng point) {List<Feature> destinationMarkerList = new ArrayList<>();for (Point singlePoint : stops) {destinationMarkerList.add(Feature.fromGeometry(Point.fromLngLat(singlePoint.longitude(), singlePoint.latitude())));}destinationMarkerList.add(Feature.fromGeometry(Point.fromLngLat(point.getLongitude(), point.getLatitude())));GeoJsonSource iconSource = style.getSourceAs(ICON_GEOJSON_SOURCE_ID);if (iconSource != null) {iconSource.setGeoJson(FeatureCollection.fromFeatures(destinationMarkerList));}} private void addPointToStopsList(LatLng point) {stops.add(Point.fromLngLat(point.getLongitude(), point.getLatitude()));} private void addFirstStopToStopsList() {// Set first stoporigin = Point.fromLngLat(30.335098600000038, 59.9342802);stops.add(origin);} private void getOptimizedRoute(@NonNull final Style style, List<Point> coordinates) {optimizedClient = MapboxOptimization.builder().source(FIRST).destination(ANY).coordinates(coordinates).overview(DirectionsCriteria.OVERVIEW_FULL).profile(DirectionsCriteria.PROFILE_DRIVING).accessToken(Mapbox.getAccessToken() != null ? Mapbox.getAccessToken() : getString(R.string.access_token)).build(); optimizedClient.enqueueCall(new Callback<OptimizationResponse>() {@Overridepublic void onResponse(Call<OptimizationResponse> call, Response<OptimizationResponse> response) {if (!response.isSuccessful()) {Timber.d(getString(R.string.no_success));Toast.makeText(OptimizationActivity.this, R.string.no_success, Toast.LENGTH_SHORT).show();} else {if (response.body() != null) {List<DirectionsRoute> routes = response.body().trips();if (routes != null) {if (routes.isEmpty()) {Timber.d("%s size = %s", getString(R.string.successful_but_no_routes), routes.size());Toast.makeText(OptimizationActivity.this, R.string.successful_but_no_routes,Toast.LENGTH_SHORT).show();} else {// Get most optimized route from API responseoptimizedRoute = routes.get(0);drawOptimizedRoute(style, optimizedRoute);}} else {Timber.d("list of routes in the response is null");Toast.makeText(OptimizationActivity.this, String.format(getString(R.string.null_in_response),"The Optimization API response's list of routes"), Toast.LENGTH_SHORT).show();}} else {Timber.d("response.body() is null");Toast.makeText(OptimizationActivity.this, String.format(getString(R.string.null_in_response),"The Optimization API response's body"), Toast.LENGTH_SHORT).show();}}} @Overridepublic void onFailure(Call<OptimizationResponse> call, Throwable throwable) {Timber.d("Error: %s", throwable.getMessage());}});} private void drawOptimizedRoute(@NonNull Style style, DirectionsRoute route) {GeoJsonSource optimizedLineSource = style.getSourceAs("optimized-route-source-id");if (optimizedLineSource != null) {optimizedLineSource.setGeoJson(FeatureCollection.fromFeature(Feature.fromGeometry(LineString.fromPolyline(route.geometry(), PRECISION_6))));}} @Overridepublic void onResume() {super.onResume();mapView.onResume();} @Overrideprotected void onStart() {super.onStart();mapView.onStart();} @Overrideprotected void onStop() {super.onStop();mapView.onStop();} @Overridepublic void onPause() {super.onPause();mapView.onPause();} @Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);mapView.onSaveInstanceState(outState);} @Overrideprotected void onDestroy() {super.onDestroy();// Cancel the directions API requestif (optimizedClient != null) {optimizedClient.cancelCall();}if (mapboxMap != null) {mapboxMap.removeOnMapClickListener(this);}mapView.onDestroy();} @Overridepublic void onLowMemory() {super.onLowMemory();mapView.onLowMemory();}}
Was this example helpful?