diff --git a/examples/src/main/AndroidManifest.xml b/examples/src/main/AndroidManifest.xml
index 3d7351ee38b..71237d365ae 100644
--- a/examples/src/main/AndroidManifest.xml
+++ b/examples/src/main/AndroidManifest.xml
@@ -182,6 +182,14 @@
android:value=".CoreActivity"/>
+
+
+
+
diff --git a/examples/src/main/java/com/mapbox/navigation/examples/CoreActivity.kt b/examples/src/main/java/com/mapbox/navigation/examples/CoreActivity.kt
index 6c8719f49b8..d5a3e097d9b 100644
--- a/examples/src/main/java/com/mapbox/navigation/examples/CoreActivity.kt
+++ b/examples/src/main/java/com/mapbox/navigation/examples/CoreActivity.kt
@@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
+import com.mapbox.navigation.examples.core.BasicNavSdkOnlyActivity
import com.mapbox.navigation.examples.core.BasicNavigationActivity
import com.mapbox.navigation.examples.core.DebugMapboxNavigationKt
import com.mapbox.navigation.examples.core.FasterRouteActivity
@@ -110,6 +111,11 @@ class CoreActivity : AppCompatActivity() {
getString(R.string.description_basic_navigation_kotlin),
BasicNavigationActivity::class.java
),
+ SampleItem(
+ getString(R.string.title_basic_navigation_sdk_only_kotlin),
+ getString(R.string.description_basic_navigation_sdk_only_kotlin),
+ BasicNavSdkOnlyActivity::class.java
+ ),
SampleItem(
getString(R.string.title_free_drive_kotlin),
getString(R.string.description_free_drive_kotlin),
diff --git a/examples/src/main/java/com/mapbox/navigation/examples/core/BasicNavSdkOnlyActivity.kt b/examples/src/main/java/com/mapbox/navigation/examples/core/BasicNavSdkOnlyActivity.kt
new file mode 100644
index 00000000000..4ce1d36057f
--- /dev/null
+++ b/examples/src/main/java/com/mapbox/navigation/examples/core/BasicNavSdkOnlyActivity.kt
@@ -0,0 +1,228 @@
+package com.mapbox.navigation.examples.core
+
+import android.annotation.SuppressLint
+import android.graphics.Color.parseColor
+import android.os.Bundle
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import com.google.android.material.snackbar.Snackbar
+import com.google.android.material.snackbar.Snackbar.LENGTH_SHORT
+import com.mapbox.android.core.location.LocationEngineProvider
+import com.mapbox.api.directions.v5.DirectionsCriteria
+import com.mapbox.api.directions.v5.models.DirectionsRoute
+import com.mapbox.api.directions.v5.models.RouteOptions
+import com.mapbox.geojson.LineString
+import com.mapbox.geojson.Point
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions
+import com.mapbox.mapboxsdk.location.modes.CameraMode
+import com.mapbox.mapboxsdk.location.modes.RenderMode
+import com.mapbox.mapboxsdk.maps.MapboxMap
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.style.expressions.Expression.color
+import com.mapbox.mapboxsdk.style.expressions.Expression.interpolate
+import com.mapbox.mapboxsdk.style.expressions.Expression.lineProgress
+import com.mapbox.mapboxsdk.style.expressions.Expression.linear
+import com.mapbox.mapboxsdk.style.expressions.Expression.stop
+import com.mapbox.mapboxsdk.style.layers.LineLayer
+import com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_ROUND
+import com.mapbox.mapboxsdk.style.layers.Property.LINE_JOIN_ROUND
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineGradient
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer
+import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
+import com.mapbox.mapboxsdk.utils.BitmapUtils
+import com.mapbox.navigation.base.extensions.applyDefaultParams
+import com.mapbox.navigation.base.extensions.coordinates
+import com.mapbox.navigation.core.MapboxNavigation
+import com.mapbox.navigation.core.directions.session.RoutesRequestCallback
+import com.mapbox.navigation.examples.R
+import com.mapbox.navigation.examples.utils.Utils
+import com.mapbox.navigation.examples.utils.extensions.toPoint
+import kotlinx.android.synthetic.main.activity_basic_navigation_sdk_only_layout.*
+import timber.log.Timber
+
+/**
+ * This example demonstrates how to combine Maps SDK with ONLY the
+ * Navigation SDK. There is no Navigation UI SDK code of any kind in this example.
+ */
+class BasicNavSdkOnlyActivity : AppCompatActivity(), OnMapReadyCallback, MapboxMap.OnMapLongClickListener {
+
+ private var mapboxNavigation: MapboxNavigation? = null
+ private var mapboxMap: MapboxMap? = null
+ private val ORIGIN_COLOR = "#32a852" // Green
+ private val DESTINATION_COLOR = "#F84D4D" // Red
+
+ @SuppressLint("MissingPermission")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_basic_navigation_sdk_only_layout)
+ mapView.onCreate(savedInstanceState)
+ mapView.getMapAsync(this)
+
+ val mapboxNavigationOptions = MapboxNavigation.defaultNavigationOptions(
+ this,
+ Utils.getMapboxAccessToken(this)
+ )
+
+ mapboxNavigation = MapboxNavigation(
+ applicationContext,
+ Utils.getMapboxAccessToken(this),
+ mapboxNavigationOptions,
+ LocationEngineProvider.getBestLocationEngine(this)
+ )
+ Snackbar.make(container, R.string.msg_long_press_map_to_place_waypoint, LENGTH_SHORT).show()
+ }
+
+ override fun onMapReady(mapboxMap: MapboxMap) {
+ mapboxMap.setStyle(Style.LIGHT) {
+ this.mapboxMap = mapboxMap
+
+ enableLocationComponent()
+
+ // Add the click and route sources
+ it.addSource(GeoJsonSource("CLICK_SOURCE"))
+ it.addSource(GeoJsonSource("ROUTE_LINE_SOURCE_ID", GeoJsonOptions().withLineMetrics(true)))
+
+ // Add the destination marker image
+ it.addImage("ICON_ID", BitmapUtils.getBitmapFromDrawable(
+ ContextCompat.getDrawable(this,
+ R.drawable.mapbox_marker_icon_default))!!)
+
+ // Add the LineLayer below the LocationComponent's bottom layer, which is the
+ // circular accuracy layer. The LineLayer will display the directions route.
+ it.addLayerBelow(LineLayer("ROUTE_LAYER_ID", "ROUTE_LINE_SOURCE_ID")
+ .withProperties(
+ lineCap(LINE_CAP_ROUND),
+ lineJoin(LINE_JOIN_ROUND),
+ lineWidth(6f),
+ lineGradient(interpolate(
+ linear(), lineProgress(),
+ stop(0f, color(parseColor(ORIGIN_COLOR))),
+ stop(1f, color(parseColor(DESTINATION_COLOR)))
+ ))), "mapbox-location-shadow-layer")
+
+ // Add the SymbolLayer to show the destination marker
+ it.addLayerAbove(SymbolLayer("CLICK_LAYER", "CLICK_SOURCE")
+ .withProperties(
+ iconImage("ICON_ID")
+ ), "ROUTE_LAYER_ID")
+
+ mapboxMap.addOnMapLongClickListener(this)
+ Snackbar.make(container, R.string.msg_long_press_map_to_place_waypoint, LENGTH_SHORT)
+ .show()
+ }
+ }
+
+ override fun onMapLongClick(latLng: LatLng): Boolean {
+ route_retrieval_progress_spinner.visibility = VISIBLE
+ // Place the destination marker at the map long click location
+ mapboxMap?.getStyle {
+ val clickPointSource = it.getSourceAs("CLICK_SOURCE")
+ clickPointSource?.setGeoJson(Point.fromLngLat(latLng.longitude, latLng.latitude))
+ }
+ mapboxMap?.locationComponent?.lastKnownLocation?.let { originLocation ->
+ mapboxNavigation?.requestRoutes(
+ RouteOptions.builder().applyDefaultParams()
+ .accessToken(Utils.getMapboxAccessToken(applicationContext))
+ .coordinates(originLocation.toPoint(), null, latLng.toPoint())
+ .alternatives(true)
+ .profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
+ .build(),
+ routesReqCallback
+ )
+ }
+ return true
+ }
+
+ private val routesReqCallback = object : RoutesRequestCallback {
+ override fun onRoutesReady(routes: List) {
+ if (routes.isNotEmpty()) {
+ Snackbar.make(container, String.format(getString(R.string.steps_in_route),
+ routes[0].legs()?.get(0)?.steps()?.size), LENGTH_SHORT).show()
+
+ // Update a gradient route LineLayer's source with the Maps SDK. This will
+ // visually add/update the line on the map. All of this is being done
+ // directly with Maps SDK code and NOT the Navigation UI SDK.
+ mapboxMap?.getStyle {
+ val clickPointSource = it.getSourceAs("ROUTE_LINE_SOURCE_ID")
+ val routeLineString = LineString.fromPolyline(routes[0].geometry()!!,
+ 6)
+ clickPointSource?.setGeoJson(routeLineString)
+ }
+ route_retrieval_progress_spinner.visibility = INVISIBLE
+ } else {
+ Snackbar.make(container, R.string.no_routes, LENGTH_SHORT).show()
+ }
+ }
+
+ override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
+ Timber.e("route request failure %s", throwable.toString())
+ Snackbar.make(container, R.string.route_request_failed, LENGTH_SHORT).show()
+ }
+
+ override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
+ Timber.d("route request canceled")
+ }
+ }
+
+ /**
+ * Enable the Maps SDK's LocationComponent
+ */
+ private fun enableLocationComponent() {
+ mapboxMap?.getStyle {
+ mapboxMap?.locationComponent?.apply {
+ activateLocationComponent(
+ LocationComponentActivationOptions.builder(
+ this@BasicNavSdkOnlyActivity, it)
+ .build())
+ isLocationComponentEnabled = true
+ cameraMode = CameraMode.TRACKING
+ renderMode = RenderMode.COMPASS
+ }
+ }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ mapView.onStart()
+ }
+
+ public override fun onResume() {
+ super.onResume()
+ mapView.onResume()
+ }
+
+ public override fun onPause() {
+ super.onPause()
+ mapView.onPause()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ mapView.onStop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mapboxNavigation?.onDestroy()
+ mapView.onDestroy()
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ mapView.onLowMemory()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ mapView.onSaveInstanceState(outState)
+ }
+}
diff --git a/examples/src/main/res/layout/activity_basic_navigation_sdk_only_layout.xml b/examples/src/main/res/layout/activity_basic_navigation_sdk_only_layout.xml
new file mode 100644
index 00000000000..892cfd1f0a0
--- /dev/null
+++ b/examples/src/main/res/layout/activity_basic_navigation_sdk_only_layout.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/examples/src/main/res/values/strings.xml b/examples/src/main/res/values/strings.xml
index d98df6003ef..55f78ff60eb 100644
--- a/examples/src/main/res/values/strings.xml
+++ b/examples/src/main/res/values/strings.xml
@@ -65,6 +65,9 @@
BasicNavigationActivity
Demonstrates how to navigate from source to destination using Mapbox Navigation.
+ BasicNavSdkOnlyActivity
+ Demonstrates how to combine Maps SDK with only the Navigation SDK and no Navigation UI SDK code of any kind.
+
FreeDriveNavigationActivity
Demonstrates how to navigate in a free drive scenario using Mapbox Navigation.
@@ -114,6 +117,9 @@
Long press on the map to place a waypoint
Tap on the map to place a waypoint
Only two waypoints are supported for this example
+ No available routes to that destination
+ There are %1$d steps in the route
+ The route request failed
Offline
Offline routing enabled
Choose offline version