Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@
android:value=".UIActivity"/>
</activity>

<activity android:name=".core.MultipleStopsActivity"
android:label="@string/title_replay_navigation_kotlin"
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".CoreActivity"/>
</activity>

<activity android:name=".core.ReplayActivity"
android:label="@string/title_replay_navigation_kotlin"
android:screenOrientation="portrait">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.mapbox.navigation.examples.core.GuidanceViewActivity
import com.mapbox.navigation.examples.core.HybridRouterActivityJava
import com.mapbox.navigation.examples.core.HybridRouterActivityKt
import com.mapbox.navigation.examples.core.InstructionViewActivity
import com.mapbox.navigation.examples.core.MultipleStopsActivity
import com.mapbox.navigation.examples.core.OffboardRouterActivityJava
import com.mapbox.navigation.examples.core.OffboardRouterActivityKt
import com.mapbox.navigation.examples.core.OnboardRouterActivityJava
Expand Down Expand Up @@ -129,6 +130,11 @@ class CoreActivity : AppCompatActivity() {
getString(R.string.description_faster_route),
FasterRouteActivity::class.java
),
SampleItem(
getString(R.string.title_multiple_stops),
getString(R.string.description_multiple_stops),
MultipleStopsActivity::class.java
),
SampleItem(
getString(R.string.title_instruction_view),
getString(R.string.description_instruction_view),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package com.mapbox.navigation.examples.core

import android.annotation.SuppressLint
import android.location.Location
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_SHORT
import com.mapbox.android.core.location.LocationEngine
import com.mapbox.android.core.location.LocationEngineCallback
import com.mapbox.android.core.location.LocationEngineProvider
import com.mapbox.android.core.location.LocationEngineRequest
import com.mapbox.android.core.location.LocationEngineResult
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.Point
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.geometry.LatLng
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.navigation.base.extensions.applyDefaultParams
import com.mapbox.navigation.core.MapboxNavigation
import com.mapbox.navigation.core.directions.session.RoutesRequestCallback
import com.mapbox.navigation.core.replay.route.ReplayRouteLocationEngine
import com.mapbox.navigation.examples.R
import com.mapbox.navigation.examples.utils.Utils
import com.mapbox.navigation.examples.utils.extensions.toPoint
import com.mapbox.navigation.ui.camera.NavigationCamera
import com.mapbox.navigation.ui.map.NavigationMapboxMap
import com.mapbox.navigation.ui.map.NavigationMapboxMapInstanceState
import java.lang.ref.WeakReference
import kotlinx.android.synthetic.main.replay_engine_example_activity_layout.*
import timber.log.Timber

/**
* To ensure proper functioning of this example make sure your Location is turned on.
*/
class MultipleStopsActivity : AppCompatActivity(), OnMapReadyCallback {

companion object {
const val DEFAULT_INTERVAL_IN_MILLISECONDS = 1000L
const val DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS * 5
}

private var mapboxMap: MapboxMap? = null
private var locationEngine: LocationEngine? = null
private var mapboxNavigation: MapboxNavigation? = null
private var navigationMapboxMap: NavigationMapboxMap? = null
private var mapInstanceState: NavigationMapboxMapInstanceState? = null
private val replayRouteLocationEngine = ReplayRouteLocationEngine()
private val stopsController = StopsController()

@SuppressLint("MissingPermission")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.replay_engine_example_activity_layout)
mapView.onCreate(savedInstanceState)

val mapboxNavigationOptions = MapboxNavigation.defaultNavigationOptions(
this,
Utils.getMapboxAccessToken(this)
)

mapboxNavigation = MapboxNavigation(
applicationContext,
Utils.getMapboxAccessToken(this),
mapboxNavigationOptions,
locationEngine = replayRouteLocationEngine
)
initListeners()
mapView.getMapAsync(this)
Snackbar.make(container, R.string.msg_long_press_map_to_place_waypoint, LENGTH_SHORT)
.show()
}

override fun onMapReady(mapboxMap: MapboxMap) {
this.mapboxMap = mapboxMap
mapboxMap.setStyle(Style.MAPBOX_STREETS) { style ->
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(15.0))
navigationMapboxMap = NavigationMapboxMap(mapView, mapboxMap)
mapInstanceState?.let { state ->
navigationMapboxMap?.restoreFrom(state)
}
initLocationEngine()
}
mapboxMap.addOnMapLongClickListener { latLng ->
stopsController.add(latLng)

mapboxMap.locationComponent.lastKnownLocation?.let { originLocation ->
requestRoute(originLocation)
}
true
}
}

private fun requestRoute(originLocation: Location) {
mapboxNavigation?.requestRoutes(
RouteOptions.builder().applyDefaultParams()
.accessToken(Utils.getMapboxAccessToken(applicationContext))
.coordinates(stopsController.coordinates(originLocation))
.alternatives(true)
.profile(DirectionsCriteria.PROFILE_DRIVING)
.build(),
routesReqCallback
)
}

fun initLocationEngine() {
val requestLocationUpdateRequest =
LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_NO_POWER)
.setMaxWaitTime(DEFAULT_MAX_WAIT_TIME)
.build()

locationEngine?.requestLocationUpdates(
requestLocationUpdateRequest,
locationListenerCallback,
mainLooper
)
// Center the map at current location. Using LocationEngineProvider because the
// replay engine won't have your last location.
LocationEngineProvider.getBestLocationEngine(this).getLastLocation(locationListenerCallback)
}

private val routesReqCallback = object : RoutesRequestCallback {
override fun onRoutesReady(routes: List<DirectionsRoute>) {
Timber.d("route request success %s", routes.toString())
if (routes.isNotEmpty()) {
navigationMapboxMap?.drawRoute(routes[0])
replayRouteLocationEngine.assign(routes[0])
startNavigation.visibility = View.VISIBLE
} else {
startNavigation.visibility = View.GONE
}
}

override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
Timber.e("route request failure %s", throwable.toString())
}

override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
Timber.d("route request canceled")
}
}

@SuppressLint("MissingPermission")
fun initListeners() {
startNavigation.setOnClickListener {
navigationMapboxMap?.updateCameraTrackingMode(NavigationCamera.NAVIGATION_TRACKING_MODE_GPS)
navigationMapboxMap?.updateLocationLayerRenderMode(RenderMode.GPS)
navigationMapboxMap?.addProgressChangeListener(mapboxNavigation!!)
if (mapboxNavigation?.getRoutes()?.isNotEmpty() == true) {
navigationMapboxMap?.startCamera(mapboxNavigation?.getRoutes()!![0])
}
mapboxNavigation?.startTripSession()
startNavigation.visibility = View.GONE
}
}

override fun onStart() {
super.onStart()
mapView.onStart()
navigationMapboxMap?.onStart()
}

public override fun onResume() {
super.onResume()
mapView.onResume()
}

public override fun onPause() {
super.onPause()
mapView.onPause()
}

override fun onStop() {
super.onStop()
stopLocationUpdates()
navigationMapboxMap?.onStop()
mapView.onStop()
}

override fun onDestroy() {
super.onDestroy()
mapboxNavigation?.stopTripSession()
mapboxNavigation?.onDestroy()
mapView.onDestroy()
}

override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}

private val locationListenerCallback = MyLocationEngineCallback(this)

private class MyLocationEngineCallback(activity: MultipleStopsActivity) :
LocationEngineCallback<LocationEngineResult> {

private val activityRef = WeakReference(activity)

override fun onSuccess(result: LocationEngineResult?) {
result?.locations?.firstOrNull()?.let {
activityRef.get()?.mapboxMap?.locationComponent?.forceLocationUpdate(it)
}
}

override fun onFailure(exception: Exception) {
}
}

private fun stopLocationUpdates() {
mapboxNavigation?.locationEngine?.removeLocationUpdates(locationListenerCallback)
}
}

private class StopsController {
private val stops = mutableListOf<Point>()

fun add(latLng: LatLng) {
stops.add(latLng.toPoint())
}

fun coordinates(originLocation: Location): List<Point> {
val coordinates = mutableListOf<Point>()
coordinates.add(originLocation.toPoint())
coordinates.addAll(stops)
return coordinates
}
}
3 changes: 3 additions & 0 deletions examples/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
<string name="title_faster_route" translatable="false">FasterRouteActivity</string>
<string name="description_faster_route" translatable="false">Demonstrate how to use MapboxNavigation to listen for faster route</string>

<string name="title_multiple_stops" translatable="false">MultipleStopsActivity</string>
<string name="description_multiple_stops" translatable="false">Demonstrate how to use MultipleStops</string>

<string name="title_summary_bottom_sheet" translatable="false">SummaryBottomSheet</string>
<string name="description_summary_bottom_sheet" translatable="false">Shows how to integrate SummaryBottomSheet, Recenter button with core SDK.</string>

Expand Down