advanced
Java
Build a navigation app for Android
Prerequisite
Familiarity with Android Studio and Java.

The Mapbox Navigation SDK for Android gives you all the tools that you need to add turn-by-turn navigation to your apps. Get up and running in a few minutes with our drop-in turn-by-turn navigation, or build a more custom navigation experience with our navigation UI components.

animated gif of a navigation application where the user's location is shown on the map, the user clicks on the map, a route appears between the user's location and the clicked point, the user clicks start navigation to initiate a navigation sequence with turn-by-turn instructions

Getting started

The Mapbox Navigation SDK for Android runs on API 15 and above. The demo in this guide was built using API 26. Here are the resources you’ll need before getting started:

  • A Mapbox account and access token. Sign up for an account at mapbox.com/signup. You can find your access tokens on your Account page. You will add your access token to your strings.xml file.
  • An application including the Mapbox Maps SDK for Android. This guide assumes that you have already begun building an Android application that uses the Mapbox Maps SDK for Android. If you’re new to the Mapbox Maps SDK for Android, check out the First steps with the Mapbox Maps SDK for Android guide to set up a simple map view first.

Install the Navigation SDK

Before developing your app with the Mapbox Navigation SDK, you’ll need to add the SDK as a dependency. Android Studio uses a toolkit called Gradle to compile resources and source code into an APK. The build.gradle file is used to configure the build and list dependencies, including the Mapbox Maps SDK for Android. In the module-level build.gradle file, add the following dependencies:

// in addition to the rest of your build.gradle contents
// you should include the following repository and dependencies

repositories {
  mavenCentral()
}

dependencies {
    implementation ('com.mapbox.mapboxsdk:mapbox-android-sdk:6.1.2@aar') {
        transitive=true
    }
    implementation 'com.mapbox.mapboxsdk:mapbox-android-navigation:0.13.0'
    implementation ('com.mapbox.mapboxsdk:mapbox-android-navigation-ui:0.13.0') {
        transitive = true
    }
}

Initialize a map

Start by creating a new project in Android Studio and initializing a MapView.

In addition to the build.gradle file where you installed the Navigation SDK, there are four files you’ll use in Android Studio to set up a Mapbox map. The four files you’ll be starting with include:

  • AndroidManifest.xml (app/manifests/AndroidManifest.xml): This file is where you’ll describe components of the application, including Mapbox-related permissions.
  • activity_main.xml (app/res/layout/activity_main.xml): This is where you’ll set the properties for your MapView including the map center, the zoom level, and the map style that will be used when the application is initialized.
  • strings.xml (app/res/values/strings.xml): You’ll update the name of the application and store your access token in this file.
  • NavigationActivity.java (app/java/yourcompany.yourproject/NavigationActivity.java): In this Java file, you’ll specify Mapbox-related interactions, starting by initializing your map.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mapbox.buildanavigationappforandroid"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".NavigationActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mapbox.mapboxsdk.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mapbox:mapbox_cameraTargetLat="38.9098"
        mapbox:mapbox_cameraTargetLng="-77.0295"
        mapbox:mapbox_styleUrl="mapbox://styles/mapbox/streets-v10"
        mapbox:mapbox_cameraZoom="12" />
</RelativeLayout>
<resources>
    <string name="app_name">Navigation map</string>
    <string name="access_token" translatable="false"><your access token here></string>
</resources>

import java.util.List;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

// classes needed to initialize map
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;

// classes needed to add location layer
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;

import android.location.Location;

import com.mapbox.mapboxsdk.geometry.LatLng;

import android.support.annotation.NonNull;

import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncherOptions;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineListener;
import com.mapbox.android.core.location.LocationEnginePriority;
import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.android.core.permissions.PermissionsListener;
import com.mapbox.android.core.permissions.PermissionsManager;

// classes needed to add a marker
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;

// classes to calculate a route
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import android.util.Log;

// classes needed to launch navigation UI
import android.view.View;
import android.widget.Button;

import com.mapbox.services.android.navigation.ui.v5.NavigationLauncher;


public class NavigationActivity extends AppCompatActivity implements LocationEngineListener, PermissionsListener {


private MapView mapView;


@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  Mapbox.getInstance(this, getString(R.string.access_token));
  setContentView(R.layout.activity_draw_navigation);
  mapView = (MapView) findViewById(R.id.mapView);
  mapView.onCreate(savedInstanceState);


}


    // Add the mapView's own lifecycle methods to the activity's lifecycle methods
    @Override
    public void onStart() {
        super.onStart();
        mapView.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
        mapView.onStop();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }
}

More details about setting up an Android Studio project to be used with the Mapbox Maps SDK for Android can be found in the First steps with the Mapbox Maps SDK for Android guide.

Run your application, and you should see a map centered on Washington DC.

initialized map on an Android device

Display user location

If you haven’t configured location permissions already, you can use the Mapbox Location Layer plugin to display the user’s location on the map.

Showing a user’s location requires importing several classes related both specifically to Mapbox and generally to location. Import the following classes below the classes you’ve already imported to your NavigationActivity file.

NavigationActivity.java

// classes needed to add location layer
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;

import android.location.Location;

import com.mapbox.mapboxsdk.geometry.LatLng;

import android.support.annotation.NonNull;

import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncherOptions;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineListener;
import com.mapbox.android.core.location.LocationEnginePriority;
import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.android.core.permissions.PermissionsListener;
import com.mapbox.android.core.permissions.PermissionsManager;

You’ll also be using several variables throughout the process of adding a user’s location to the map. Declare the following variables inside the NavigationActivity class just below the existing variable, private MapView mapView;.

NavigationActivity.java

// variables for adding location layer
private MapboxMap map;
private PermissionsManager permissionsManager;
private LocationLayerPlugin locationPlugin;
private LocationEngine locationEngine;
private Location originLocation;

Now you are ready to enable the location layer plugin, initialize the location engine, and add the user’s location to the map as a location layer. Two things to note:

  • You will also need to add two implementations to the NavigationActivity class: LocationEngineListener and PermissionsListener.
  • Notice the updates to the onStart, onStop, and onDestroy methods.
NavigationActivity.java

@SuppressWarnings( {"MissingPermission"})
private void enableLocationPlugin() {
  // Check if permissions are enabled and if not request
  if (PermissionsManager.areLocationPermissionsGranted(this)) {
    // Create an instance of LOST location engine
    initializeLocationEngine();

    locationPlugin = new LocationLayerPlugin(mapView, map, locationEngine);
    locationPlugin.setRenderMode(RenderMode.COMPASS);
  } else {
    permissionsManager = new PermissionsManager(this);
    permissionsManager.requestLocationPermissions(this);
  }
}

@SuppressWarnings( {"MissingPermission"})
private void initializeLocationEngine() {
  LocationEngineProvider locationEngineProvider = new LocationEngineProvider(this);
  locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
  locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
  locationEngine.activate();

  Location lastLocation = locationEngine.getLastLocation();
  if (lastLocation != null) {
    originLocation = lastLocation;
    setCameraPosition(lastLocation);
  } else {
    locationEngine.addLocationEngineListener(this);
  }
}

private void setCameraPosition(Location location) {
  map.animateCamera(CameraUpdateFactory.newLatLngZoom(
    new LatLng(location.getLatitude(), location.getLongitude()), 13));
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
public void onExplanationNeeded(List<String> permissionsToExplain) {

}

@Override
public void onPermissionResult(boolean granted) {
  if (granted) {
    enableLocationPlugin();
  } else {
    finish();
  }
}

@Override
@SuppressWarnings( {"MissingPermission"})
public void onConnected() {
  locationEngine.requestLocationUpdates();
}

@Override
public void onLocationChanged(Location location) {
  if (location != null) {
    originLocation = location;
    setCameraPosition(location);
    locationEngine.removeLocationEngineListener(this);
  }
}

@Override
@SuppressWarnings( {"MissingPermission"})
protected void onStart() {
  super.onStart();
  if (locationEngine != null) {
    locationEngine.requestLocationUpdates();
  }
  if (locationPlugin != null) {
    locationPlugin.onStart();
  }
  mapView.onStart();
}

@Override
protected void onStop() {
  super.onStop();
  if (locationEngine != null) {
    locationEngine.removeLocationUpdates();
  }
  if (locationPlugin != null) {
    locationPlugin.onStop();
  }
  mapView.onStop();
}

@Override
protected void onDestroy() {
  super.onDestroy();
  mapView.onDestroy();
  if (locationEngine != null) {
    locationEngine.deactivate();
  }
}

@Override
public void onLowMemory() {
  super.onLowMemory();
  mapView.onLowMemory();
}

@Override
protected void onResume() {
  super.onResume();
  mapView.onResume();
}

@Override
protected void onPause() {
  super.onPause();
  mapView.onPause();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  mapView.onSaveInstanceState(outState);
}

Next, you’ll call the enableLocationPlugin() method when the map is finished loading. Add the following code after the code used to initialize the map.

NavigationActivity.java

mapView.getMapAsync(new OnMapReadyCallback() {
  @Override
  public void onMapReady(final MapboxMap mapboxMap) {


map = mapboxMap;
enableLocationPlugin();


}

  ;
});

Run your application and you will see a circle representing the user’s location on the map.

an Android device displaying a map with a user's location

Add a marker on click

In this application, the user will be able to retrieve a route between their current location and any point that they select on the map. Next, you’ll create the ability to add a marker to the map when the user taps on the map.

Start by importing the necessary classes for adding a marker to the map.

NavigationActivity.java

// classes needed to add a marker
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;

Then, add a few new variables that you will use to define the origin and destination based on the user’s location and the selected point, respectively.

NavigationActivity.java

// variables for adding a marker
private Marker destinationMarker;
private LatLng originCoord;
private LatLng destinationCoord;

Now you are ready to add the code that will listen for when a user clicks on the map and then add a marker to the map.

NavigationActivity.java

originCoord = new LatLng(originLocation.getLatitude(), originLocation.getLongitude());
mapboxMap.addOnMapClickListener(new MapboxMap.OnMapClickListener() {
  @Override
  public void onMapClick(@NonNull LatLng point) {
    if (destinationMarker != null) {
      mapboxMap.removeMarker(destinationMarker);
    }
    destinationCoord = point;
    destinationMarker = mapboxMap.addMarker(new MarkerOptions()
      .position(destinationCoord)
    );


}

  ;
});

Run the application again. Click on the map, and you will see a marker added to the map.

an Android device displaying a user's location and marker on a map

Calculate and draw route

Next, you’ll calculate and draw a route between the user’s location and the newly added marker. First, import a set of classes required to calculate and draw a route on the map using the Mapbox Navigation SDK and the Mapbox Android Services Directions API wrapper.

NavigationActivity.java

// classes to calculate a route
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import android.util.Log;

Next, add a few more variables that you’ll use while calculating and drawing the route.

NavigationActivity.java

// variables for calculating and drawing a route
private Point originPosition;
private Point destinationPosition;
private DirectionsRoute currentRoute;
private static final String TAG = "DirectionsActivity";
private NavigationMapRoute navigationMapRoute;

Now you’re ready to write a new getRoute method. This method will require a origin and destination to build a NavigationRoute. After passing an origin and destination to the method, you will make a request to the Mapbox Directions API. Once you’ve received a response, that response will be stored as the currentRoute. Then, you’ll add currrentRoute to your map. Start by checking if a route already exists on the map. If it does, remove it. Then, add the currentRoute to the map as a NavigationMapRoute.

NavigationActivity.java

private void getRoute(Point origin, Point destination) {
  NavigationRoute.builder()
    .accessToken(Mapbox.getAccessToken())
    .origin(origin)
    .destination(destination)
    .build()
    .getRoute(new Callback<DirectionsResponse>() {
      @Override
      public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
        // You can get the generic HTTP info about the response
        Log.d(TAG, "Response code: " + response.code());
        if (response.body() == null) {
          Log.e(TAG, "No routes found, make sure you set the right user and access token.");
          return;
        } else if (response.body().routes().size() < 1) {
          Log.e(TAG, "No routes found");
          return;
        }

        currentRoute = response.body().routes().get(0);

        // Draw the route on the map
        if (navigationMapRoute != null) {
          navigationMapRoute.removeRoute();
        } else {
          navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);
        }
        navigationMapRoute.addRoute(currentRoute);
      }

      @Override
      public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
        Log.e(TAG, "Error: " + throwable.getMessage());
      }
    });
}

Now you’ve written the getRoute method, but it still need to be called when the user adds a marker to the map. Call the getRoute method inside the mapboxMap.addOnMapClickListener(new MapboxMap.OnMapClickListener() { ... }); method.

NavigationActivity.java

destinationPosition = Point.fromLngLat(destinationCoord.getLongitude(), destinationCoord.getLatitude());
originPosition = Point.fromLngLat(originCoord.getLongitude(), originCoord.getLatitude());
getRoute(originPosition, destinationPosition);

Run the application, click the map, and you will see a marker added to the map and a line displaying a route between the user’s location and the clicked point.

an Android device displaying a map with a user's location, a marker, and a route between the two

Add a button to start navigation

Finally, you’ll add a button and specify that when that button is clicked, a navigation interface should be displayed. Start by defining a few styles for the button. In the colors.xml file, add three new colors.

colors.xml
<color name="mapboxWhite">#ffffff</color>
<color name="mapboxBlue">#4264fb</color>
<color name="mapboxGrayLight">#c6d2e1</color>

Then, create a button in the activity_main.xml file. Use the colors you specified to set the background and textColor. Notice that when the application is first opened, the button will not be enabled (android:enabled="false") and the button will be the mapboxGrayLight color.

activity_main.xml
<Button
    android:id="@+id/startButton"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:padding="5px"
    android:layout_margin="20px"
    android:text="Start navigation"
    android:background="@color/mapboxGrayLight"
    android:textColor="@color/mapboxWhite"
    android:enabled="false"/>

Back in the NavigationActivity file, import the necessary classes for adding a button and opening a new navigation view.

NavigationActivity.java

// classes needed to launch navigation UI
import android.view.View;
import android.widget.Button;

import com.mapbox.services.android.navigation.ui.v5.NavigationLauncher;

Add a new variable for the button.

NavigationActivity.java

private Button button;

Then, add a button with a click listener. When the button is clicked, initiate the NavigationLauncher.

NavigationActivity.java

button = findViewById(R.id.startButton);
button.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
    Point origin = originPosition;
    Point destination = destinationPosition;

    boolean simulateRoute = true;
    NavigationLauncherOptions options = NavigationLauncherOptions.builder()
      .origin(origin)
      .destination(destination)
      .shouldSimulateRoute(simulateRoute)
      .build();

    // Call this method with Context from within an Activity
    NavigationLauncher.startNavigation(NavigationActivity.this, options);
  }
});

Finally, you’ll need to specify that the button should change to be enabled after a marker is added to the map (when the destination is defined). You can accomplish this by setting the button to enabled and setting the background to the mapboxBlue color defined in the colors.xml file.

NavigationActivity.java

button.setEnabled(true);
button.setBackgroundResource(R.color.mapboxBlue);

Run the application again. You should see a full width button at the top of the screen. Click a point on the map to add a marker and see an overview of the route. Then, click the Start navigation button to pull up the navigation view.

an Android device displaying a map, a user's location, and a button that is not enabled
Before selecting a destination
an Android device displaying a map, a user's location, a marker, a route between the two, and an enabled button that says 'Start navigation'
After selecting a destination
an Android device displaying a navigation application with turn-by-turn instructions
After clicking Start navigation

Customize the style

There are many ways to customize the appearance and functionality included in your navigation app. In this guide, you’ll customize the colors to fit the Mapbox brand.

Style the navigation view

First, change the style of the navigation view by changing colors to match Mapbox’s brand. Define the following colors in the colors.xml file.

colors.xml
<color name="mapboxPink">#ee4e8b</color>
<color name="mapboxYellow">#d9d838</color>
<color name="mapboxRed">#b43b71</color>

Then, specify the colors in the styles.xml file. The NavigationMapRoute style allows you change the appearance of the route on the map and the NavigationView style allows you to change the colors of the turn-by-turn instructions and progress bar.

styles.xml
<style name="NavigationMapRoute">
    <!-- Colors -->
    <item name="routeColor">@color/mapboxBlue</item>
    <item name="routeModerateCongestionColor">@color/mapboxYellow</item>
    <item name="routeSevereCongestionColor">@color/mapboxPink</item>
    <item name="routeShieldColor">@color/mapboxWhite</item>
    <!-- Scales -->
    <item name="routeScale">1.0</item>
</style>

<style name="NavigationView" parent="Theme.AppCompat.NoActionBar">
    <item name="navigationViewPrimary">@color/mapboxWhite</item>
    <item name="navigationViewSecondary">@color/mapboxBlue</item>
    <item name="navigationViewAccent">@color/mapboxPink</item>
</style>

Style the route overview

Next, change the color of the route overview that is drawn on the map when you click the map and add a marker. Find the code that is used to set the variable navigationMapRoute and replace it with the code below so the route will inherit the colors of the route in the navigation view.

NavigationActivity.java
navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);

Run the application, and you will see these changes applied to your app.

an Android device displaying a map, a user's location, a marker, a pink route between the two, and an enabled button that says 'Start navigation'
Custom route overview style
an Android device displaying a navigation application with turn-by-turn instructions in Mapbox branded colors
Custom navigation view style

Final product

Congratulations! You just built a small navigation app with the Mapbox Navigation SDK for Android.

animated gif of a navigation application where the user's location is shown on the map, the user clicks on the map, a route appears between the user's location and the clicked point, the user clicks start navigation to initiate a navigation sequence with turn-by-turn instructions

Here’s the code for the final NavigationActivity.java file:

NavigationActivity.java

import java.util.List;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

// classes needed to initialize map
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;

// classes needed to add location layer
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;

import android.location.Location;

import com.mapbox.mapboxsdk.geometry.LatLng;

import android.support.annotation.NonNull;

import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncherOptions;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineListener;
import com.mapbox.android.core.location.LocationEnginePriority;
import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.android.core.permissions.PermissionsListener;
import com.mapbox.android.core.permissions.PermissionsManager;

// classes needed to add a marker
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;

// classes to calculate a route
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import android.util.Log;

// classes needed to launch navigation UI
import android.view.View;
import android.widget.Button;

import com.mapbox.services.android.navigation.ui.v5.NavigationLauncher;


// classes needed to add location layer
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;

import android.location.Location;

import com.mapbox.mapboxsdk.geometry.LatLng;

import android.support.annotation.NonNull;

import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.services.android.navigation.ui.v5.NavigationLauncherOptions;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineListener;
import com.mapbox.android.core.location.LocationEnginePriority;
import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.android.core.permissions.PermissionsListener;
import com.mapbox.android.core.permissions.PermissionsManager;


// classes needed to add a marker
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;


// classes to calculate a route
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import android.util.Log;


// classes needed to launch navigation UI
import android.view.View;
import android.widget.Button;

import com.mapbox.services.android.navigation.ui.v5.NavigationLauncher;


public class NavigationActivity extends AppCompatActivity implements LocationEngineListener, PermissionsListener {


private MapView mapView;


// variables for adding location layer
private MapboxMap map;
private PermissionsManager permissionsManager;
private LocationLayerPlugin locationPlugin;
private LocationEngine locationEngine;
private Location originLocation;


// variables for adding a marker
private Marker destinationMarker;
private LatLng originCoord;
private LatLng destinationCoord;


// variables for calculating and drawing a route
private Point originPosition;
private Point destinationPosition;
private DirectionsRoute currentRoute;
private static final String TAG = "DirectionsActivity";
private NavigationMapRoute navigationMapRoute;


private Button button;


@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  Mapbox.getInstance(this, getString(R.string.access_token));
  setContentView(R.layout.activity_draw_navigation);
  mapView = (MapView) findViewById(R.id.mapView);
  mapView.onCreate(savedInstanceState);


mapView.getMapAsync(new OnMapReadyCallback() {
  @Override
  public void onMapReady(final MapboxMap mapboxMap) {


map = mapboxMap;
enableLocationPlugin();


originCoord = new LatLng(originLocation.getLatitude(), originLocation.getLongitude());
mapboxMap.addOnMapClickListener(new MapboxMap.OnMapClickListener() {
  @Override
  public void onMapClick(@NonNull LatLng point) {
    if (destinationMarker != null) {
      mapboxMap.removeMarker(destinationMarker);
    }
    destinationCoord = point;
    destinationMarker = mapboxMap.addMarker(new MarkerOptions()
      .position(destinationCoord)
    );


destinationPosition = Point.fromLngLat(destinationCoord.getLongitude(), destinationCoord.getLatitude());
originPosition = Point.fromLngLat(originCoord.getLongitude(), originCoord.getLatitude());
getRoute(originPosition, destinationPosition);


button.setEnabled(true);
button.setBackgroundResource(R.color.mapboxBlue);


}

  ;
});


button = findViewById(R.id.startButton);
button.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
    Point origin = originPosition;
    Point destination = destinationPosition;

    boolean simulateRoute = true;
    NavigationLauncherOptions options = NavigationLauncherOptions.builder()
      .origin(origin)
      .destination(destination)
      .shouldSimulateRoute(simulateRoute)
      .build();

    // Call this method with Context from within an Activity
    NavigationLauncher.startNavigation(NavigationActivity.this, options);
  }
});


}

  ;
});


}


private void getRoute(Point origin, Point destination) {
  NavigationRoute.builder()
    .accessToken(Mapbox.getAccessToken())
    .origin(origin)
    .destination(destination)
    .build()
    .getRoute(new Callback<DirectionsResponse>() {
      @Override
      public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
        // You can get the generic HTTP info about the response
        Log.d(TAG, "Response code: " + response.code());
        if (response.body() == null) {
          Log.e(TAG, "No routes found, make sure you set the right user and access token.");
          return;
        } else if (response.body().routes().size() < 1) {
          Log.e(TAG, "No routes found");
          return;
        }

        currentRoute = response.body().routes().get(0);

        // Draw the route on the map
        if (navigationMapRoute != null) {
          navigationMapRoute.removeRoute();
        } else {
          navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);
        }
        navigationMapRoute.addRoute(currentRoute);
      }

      @Override
      public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
        Log.e(TAG, "Error: " + throwable.getMessage());
      }
    });
}


@SuppressWarnings( {"MissingPermission"})
private void enableLocationPlugin() {
  // Check if permissions are enabled and if not request
  if (PermissionsManager.areLocationPermissionsGranted(this)) {
    // Create an instance of LOST location engine
    initializeLocationEngine();

    locationPlugin = new LocationLayerPlugin(mapView, map, locationEngine);
    locationPlugin.setRenderMode(RenderMode.COMPASS);
  } else {
    permissionsManager = new PermissionsManager(this);
    permissionsManager.requestLocationPermissions(this);
  }
}

@SuppressWarnings( {"MissingPermission"})
private void initializeLocationEngine() {
  LocationEngineProvider locationEngineProvider = new LocationEngineProvider(this);
  locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
  locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
  locationEngine.activate();

  Location lastLocation = locationEngine.getLastLocation();
  if (lastLocation != null) {
    originLocation = lastLocation;
    setCameraPosition(lastLocation);
  } else {
    locationEngine.addLocationEngineListener(this);
  }
}

private void setCameraPosition(Location location) {
  map.animateCamera(CameraUpdateFactory.newLatLngZoom(
    new LatLng(location.getLatitude(), location.getLongitude()), 13));
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
public void onExplanationNeeded(List<String> permissionsToExplain) {

}

@Override
public void onPermissionResult(boolean granted) {
  if (granted) {
    enableLocationPlugin();
  } else {
    finish();
  }
}

@Override
@SuppressWarnings( {"MissingPermission"})
public void onConnected() {
  locationEngine.requestLocationUpdates();
}

@Override
public void onLocationChanged(Location location) {
  if (location != null) {
    originLocation = location;
    setCameraPosition(location);
    locationEngine.removeLocationEngineListener(this);
  }
}

@Override
@SuppressWarnings( {"MissingPermission"})
protected void onStart() {
  super.onStart();
  if (locationEngine != null) {
    locationEngine.requestLocationUpdates();
  }
  if (locationPlugin != null) {
    locationPlugin.onStart();
  }
  mapView.onStart();
}

@Override
protected void onStop() {
  super.onStop();
  if (locationEngine != null) {
    locationEngine.removeLocationUpdates();
  }
  if (locationPlugin != null) {
    locationPlugin.onStop();
  }
  mapView.onStop();
}

@Override
protected void onDestroy() {
  super.onDestroy();
  mapView.onDestroy();
  if (locationEngine != null) {
    locationEngine.deactivate();
  }
}

@Override
public void onLowMemory() {
  super.onLowMemory();
  mapView.onLowMemory();
}

@Override
protected void onResume() {
  super.onResume();
  mapView.onResume();
}

@Override
protected void onPause() {
  super.onPause();
  mapView.onPause();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  mapView.onSaveInstanceState(outState);
}


}

Next steps

There are many other ways you can customize the Mapbox Navigation SDK beyond what you’ve done in this tutorial. For a complete reference of customization options see the Mapbox Navigation SDK for Android documentation.