Directions route profiles
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.
Directions API pricing
Products used within the Mapbox Java SDK, including the Directions API, are individually billed. For pricing information, see the documentation for the Directions API.
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout 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.DirectionsProfileToggleActivity"> <com.mapbox.mapboxsdk.maps.MapViewandroid:id="@+id/mapView"android:layout_width="match_parent"android:layout_height="match_parent"mapbox:mapbox_cameraTargetLat="19.42777430539"mapbox:mapbox_cameraTargetLng="-99.1523793414"mapbox:mapbox_cameraZoom="11.7" /> <Buttonandroid:id="@+id/driving_profile_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="32dp"android:background="@color/mapboxPurple"android:padding="8dp"android:textAllCaps="false"android:textStyle="normal"mapbox:layout_constraintBottom_toBottomOf="parent"mapbox:layout_constraintEnd_toStartOf="@+id/walking_profile_button"mapbox:layout_constraintHorizontal_bias="0.5"mapbox:layout_constraintStart_toStartOf="parent" /> <Buttonandroid:id="@+id/walking_profile_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/mapboxPurple"android:padding="8dp"android:textAllCaps="false"android:textStyle="normal"mapbox:layout_constraintBottom_toBottomOf="@+id/driving_profile_button"mapbox:layout_constraintEnd_toStartOf="@+id/cycling_profile_button"mapbox:layout_constraintHorizontal_bias="0.5"mapbox:layout_constraintStart_toEndOf="@+id/driving_profile_button" /> <Buttonandroid:id="@+id/cycling_profile_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/mapboxPurple"android:padding="8dp"android:textAllCaps="false"android:textStyle="normal"mapbox:layout_constraintBottom_toBottomOf="@+id/driving_profile_button"mapbox:layout_constraintEnd_toEndOf="parent"mapbox:layout_constraintHorizontal_bias="0.5"mapbox:layout_constraintStart_toEndOf="@+id/walking_profile_button" /> </androidx.constraintlayout.widget.ConstraintLayout>
package com.mapbox.mapboxandroiddemo.examples.javaservices; import android.graphics.Color;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast; import com.mapbox.api.directions.v5.DirectionsCriteria;import com.mapbox.api.directions.v5.MapboxDirections;import com.mapbox.api.directions.v5.models.DirectionsResponse;import com.mapbox.api.directions.v5.models.DirectionsRoute;import com.mapbox.geojson.Feature;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.Property;import com.mapbox.mapboxsdk.style.layers.SymbolLayer;import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;import com.mapbox.mapboxsdk.utils.BitmapUtils; import java.util.concurrent.TimeUnit; 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.lineCap;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth; /*** Use the Mapbox Java SDK to request directions from the Mapbox Directions API* and show the various directions profile.*/public class DirectionsProfileToggleActivity extends AppCompatActivityimplements MapboxMap.OnMapClickListener { private static final String TAG = "DirectionsProfileToggleActivity";private static final String ROUTE_LAYER_ID = "route-layer-id";private static final String ROUTE_SOURCE_ID = "route-source-id";private static final String ICON_LAYER_ID = "icon-layer-id";private static final String ICON_SOURCE_ID = "icon-source-id";private static final String RED_PIN_ICON_ID = "red-pin-icon-id";private MapView mapView;private MapboxMap mapboxMap;private DirectionsRoute drivingRoute;private DirectionsRoute walkingRoute;private DirectionsRoute cyclingRoute;private MapboxDirections client;private Point origin = Point.fromLngLat(-99.13037323366, 19.40488375253);private Point destination = Point.fromLngLat(-99.167663574, 19.426984786987);private String lastSelectedDirectionsProfile = DirectionsCriteria.PROFILE_DRIVING;private Button drivingButton;private Button walkingButton;private Button cyclingButton;private boolean firstRouteDrawn = false;private String[] profiles = new String[]{DirectionsCriteria.PROFILE_DRIVING,DirectionsCriteria.PROFILE_CYCLING,DirectionsCriteria.PROFILE_WALKING}; @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_directions_profile_toggle); drivingButton = findViewById(R.id.driving_profile_button);drivingButton.setTextColor(Color.WHITE);walkingButton = findViewById(R.id.walking_profile_button);cyclingButton = findViewById(R.id.cycling_profile_button); // Setup the MapViewmapView = findViewById(R.id.mapView);mapView.onCreate(savedInstanceState);mapView.getMapAsync(new OnMapReadyCallback() {@Overridepublic void onMapReady(@NonNull MapboxMap mapboxMap) {mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) { DirectionsProfileToggleActivity.this.mapboxMap = mapboxMap; initSource(style); initLayers(style); getAllRoutes(false); initButtonClickListeners(); mapboxMap.addOnMapClickListener(DirectionsProfileToggleActivity.this); Toast.makeText(DirectionsProfileToggleActivity.this,R.string.instruction, Toast.LENGTH_SHORT).show();}});}});} /*** Load route info for each Directions API profile.** @param fromMapClick whether the route loading is being triggered from tapping* on the map*/private void getAllRoutes(boolean fromMapClick) {for (String profile : profiles) {getSingleRoute(profile, fromMapClick);}} @Overridepublic boolean onMapClick(@NonNull LatLng point) {destination = Point.fromLngLat(point.getLongitude(), point.getLatitude());moveDestinationMarkerToNewLocation(point);getAllRoutes(true);return true;} /*** Move the destination marker to wherever the map was tapped on.** @param pointToMoveMarkerTo where the map was tapped on*/private void moveDestinationMarkerToNewLocation(LatLng pointToMoveMarkerTo) {mapboxMap.getStyle(new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) {GeoJsonSource destinationIconGeoJsonSource = style.getSourceAs(ICON_SOURCE_ID);if (destinationIconGeoJsonSource != null) {destinationIconGeoJsonSource.setGeoJson(Feature.fromGeometry(Point.fromLngLat(pointToMoveMarkerTo.getLongitude(), pointToMoveMarkerTo.getLatitude())));}}});} /*** Add the source for the Directions API route line LineLayer.*/private void initSource(@NonNull Style loadedMapStyle) {loadedMapStyle.addSource(new GeoJsonSource(ROUTE_SOURCE_ID));GeoJsonSource iconGeoJsonSource = new GeoJsonSource(ICON_SOURCE_ID,Feature.fromGeometry(Point.fromLngLat(destination.longitude(),destination.latitude())));loadedMapStyle.addSource(iconGeoJsonSource);} /*** Set up the click listeners on the buttons for each Directions API profile.*/private void initButtonClickListeners() {drivingButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {drivingButton.setTextColor(Color.WHITE);walkingButton.setTextColor(Color.BLACK);cyclingButton.setTextColor(Color.BLACK);lastSelectedDirectionsProfile = DirectionsCriteria.PROFILE_DRIVING;showRouteLine();}});walkingButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {drivingButton.setTextColor(Color.BLACK);walkingButton.setTextColor(Color.WHITE);cyclingButton.setTextColor(Color.BLACK);lastSelectedDirectionsProfile = DirectionsCriteria.PROFILE_WALKING;showRouteLine();}});cyclingButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {drivingButton.setTextColor(Color.BLACK);walkingButton.setTextColor(Color.BLACK);cyclingButton.setTextColor(Color.WHITE);lastSelectedDirectionsProfile = DirectionsCriteria.PROFILE_CYCLING;showRouteLine();}});} /*** Display the Directions API route line depending on which profile was last* selected.*/private void showRouteLine() {if (mapboxMap != null) {mapboxMap.getStyle(new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) { // Retrieve and update the source designated for showing the directions routeGeoJsonSource routeLineSource = style.getSourceAs(ROUTE_SOURCE_ID); // Create a LineString with the directions route's geometry and// reset the GeoJSON source for the route LineLayer sourceif (routeLineSource != null) {switch (lastSelectedDirectionsProfile) {case DirectionsCriteria.PROFILE_DRIVING:routeLineSource.setGeoJson(LineString.fromPolyline(drivingRoute.geometry(),PRECISION_6));break;case DirectionsCriteria.PROFILE_WALKING:routeLineSource.setGeoJson(LineString.fromPolyline(walkingRoute.geometry(),PRECISION_6));break;case DirectionsCriteria.PROFILE_CYCLING:routeLineSource.setGeoJson(LineString.fromPolyline(cyclingRoute.geometry(),PRECISION_6));break;default:break;}}}});}} /*** Add the route and icon layers to the map*/private void initLayers(@NonNull Style loadedMapStyle) {LineLayer routeLayer = new LineLayer(ROUTE_LAYER_ID, ROUTE_SOURCE_ID); // Add the LineLayer to the map. This layer will display the directions route.routeLayer.setProperties(lineCap(Property.LINE_CAP_ROUND),lineJoin(Property.LINE_JOIN_ROUND),lineWidth(5f),lineColor(Color.parseColor("#006eff")));loadedMapStyle.addLayer(routeLayer); // Add the red marker icon image to the maploadedMapStyle.addImage(RED_PIN_ICON_ID, BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.red_marker))); // Add the red marker icon SymbolLayer to the maploadedMapStyle.addLayer(new SymbolLayer(ICON_LAYER_ID, ICON_SOURCE_ID).withProperties(iconImage(RED_PIN_ICON_ID),iconIgnorePlacement(true),iconAllowOverlap(true),iconOffset(new Float[]{0f, -9f})));} /*** Make a request to the Mapbox Directions API. Once successful, pass the route to the* route layer.** @param profile the directions profile to use in the Directions API request*/private void getSingleRoute(String profile, boolean fromMapClick) {client = MapboxDirections.builder().origin(origin).destination(destination).overview(DirectionsCriteria.OVERVIEW_FULL).profile(profile).accessToken(getString(R.string.access_token)).build(); client.enqueueCall(new Callback<DirectionsResponse>() {@Overridepublic void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {// You can get the generic HTTP info about the responseTimber.d("Response code: " + response.code());if (response.body() == null) {Timber.e("No routes found, make sure you set the right user and access token.");return;} else if (response.body().routes().size() < 1) {Timber.e("No routes found");return;} switch (profile) {case DirectionsCriteria.PROFILE_DRIVING:drivingRoute = response.body().routes().get(0);drivingButton.setText(String.format(getString(R.string.driving_profile),String.valueOf(TimeUnit.SECONDS.toMinutes(drivingRoute.duration().longValue()))));if (!firstRouteDrawn) {showRouteLine();firstRouteDrawn = true;}break;case DirectionsCriteria.PROFILE_WALKING:walkingRoute = response.body().routes().get(0);walkingButton.setText(String.format(getString(R.string.walking_profile),String.valueOf(TimeUnit.SECONDS.toMinutes(walkingRoute.duration().longValue()))));break;case DirectionsCriteria.PROFILE_CYCLING:cyclingRoute = response.body().routes().get(0);cyclingButton.setText(String.format(getString(R.string.cycling_profile),String.valueOf(TimeUnit.SECONDS.toMinutes(cyclingRoute.duration().longValue()))));break;default:break;}if (fromMapClick) {showRouteLine();}} @Overridepublic void onFailure(Call<DirectionsResponse> call, Throwable throwable) {Timber.e("Error: " + throwable.getMessage());Toast.makeText(DirectionsProfileToggleActivity.this,"Error: " + throwable.getMessage(),Toast.LENGTH_SHORT).show();}});} @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 (client != null) {client.cancelCall();}if (mapboxMap != null) {mapboxMap.removeOnMapClickListener(this);}mapView.onDestroy();} @Overridepublic void onLowMemory() {super.onLowMemory();mapView.onLowMemory();}}
Was this example helpful?