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
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class MultipleStopsActivity : AppCompatActivity(), OnMapReadyCallback {
.build()
override fun arrivalOptions(): ArrivalOptions = arrivalOptions

override fun onStopArrival(routeLegProgress: RouteLegProgress): Boolean {
override fun navigateNextRouteLeg(routeLegProgress: RouteLegProgress): Boolean {
// This example shows you can use both time and distance.
// Move to the next step when the distance is small
Timber.i("arrival_debug legIndex=${routeLegProgress.legIndex()} distanceRemaining=${routeLegProgress.distanceRemaining()}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.mapbox.navigation.core.internal.accounts.MapboxNavigationAccounts
import com.mapbox.navigation.core.internal.trip.service.TripService
import com.mapbox.navigation.core.routerefresh.RouteRefreshController
import com.mapbox.navigation.core.stops.ArrivalController
import com.mapbox.navigation.core.stops.ArrivalObserver
import com.mapbox.navigation.core.stops.ArrivalProgressObserver
import com.mapbox.navigation.core.stops.AutoArrivalController
import com.mapbox.navigation.core.telemetry.MapboxNavigationTelemetry
Expand Down Expand Up @@ -459,9 +460,9 @@ constructor(
/**
* Attach your own controller to determine when drivers arrived at stops via [ArrivalController]
* Use [navigateNextRouteLeg] to manually move navigator to the next stop. To reset to the
* automatic arrival controller, call attachArrivalController()
* automatic arrival controller, call [attachArrivalController].
*
* @param arrivalController ArrivalObserver
* @param arrivalController [ArrivalController]
*/
@JvmOverloads fun attachArrivalController(arrivalController: ArrivalController = AutoArrivalController()) {
arrivalProgressObserver.attach(arrivalController)
Expand All @@ -476,10 +477,29 @@ constructor(
tripSession.unregisterRouteProgressObserver(arrivalProgressObserver)
}

/**
* Registers [ArrivalObserver]. Monitor arrival at stops and destinations. For more control
* of arrival at stops, see [attachArrivalController].
*
* @see [unregisterArrivalObserver]
*/
fun registerArrivalObserver(arrivalObserver: ArrivalObserver) {
arrivalProgressObserver.registerObserver(arrivalObserver)
}

/**
* Unregisters [ArrivalObserver].
*
* @see [registerArrivalObserver]
*/
fun unregisterArrivalObserver(arrivalObserver: ArrivalObserver) {
arrivalProgressObserver.unregisterObserver(arrivalObserver)
}

/**
* After arriving at a stop, this can be used to manually decide when to start
* navigating to the next stop. Use the [ArrivalController] to control when to
* call navigateNextRouteLeg.
* call [navigateNextRouteLeg].
*
* @return true if navigation to next stop could be started, false otherwise
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.mapbox.navigation.core.stops

import com.mapbox.navigation.base.trip.model.RouteLegProgress
import com.mapbox.navigation.base.trip.model.RouteProgress
import com.mapbox.navigation.base.trip.model.RouteProgressState
import com.mapbox.navigation.core.MapboxNavigation

/**
* When navigating to points of interest, you may want to control the arrival
* experience. This interface gives you options to change arrival via [MapboxNavigation.attachArrivalController]
* When navigating to points of interest, you may want to control the arrival experience.
* This interface gives you options to control arrival via [MapboxNavigation.attachArrivalController].
*
* To observe arrival, see [ArrivalObserver]
*/
interface ArrivalController {

Expand All @@ -18,17 +18,11 @@ interface ArrivalController {

/**
* Based on your [ArrivalOptions], this will be called as the next stop is approached.
* To manually navigate the next leg, return false and call [MapboxNavigation.navigateNextRouteLeg]
* To manually navigate to the next leg, return false and call [MapboxNavigation.navigateNextRouteLeg].
*
* @return true to automatically move to the next step, false to do it manually
* @return true to automatically call [MapboxNavigation.navigateNextRouteLeg], false to do it manually
*/
fun onStopArrival(routeLegProgress: RouteLegProgress): Boolean

/**
* Once the [RouteProgress.currentState] has reached [RouteProgressState.ROUTE_ARRIVED]
* for the last stop, this will be called once.
*/
fun onRouteArrival(routeProgress: RouteProgress) {}
fun navigateNextRouteLeg(routeLegProgress: RouteLegProgress): Boolean
Comment thread
kmadsen marked this conversation as resolved.
}

/**
Expand All @@ -38,14 +32,14 @@ interface ArrivalController {
class AutoArrivalController : ArrivalController {

/**
* Default arrival options
* Default arrival options.
*/
override fun arrivalOptions(): ArrivalOptions = ArrivalOptions.Builder().build()

/**
* By default this will move onto the next step.
*/
override fun onStopArrival(routeLegProgress: RouteLegProgress): Boolean {
override fun navigateNextRouteLeg(routeLegProgress: RouteLegProgress): Boolean {
return true
}
}
Expand All @@ -57,13 +51,13 @@ data class ArrivalOptions(

/**
* While the next stop is less than [arrivalInSeconds] away,
* [ArrivalController.onStopArrival] will be called
* [ArrivalController.navigateNextRouteLeg] will be called.
*/
val arrivalInSeconds: Double?,

/**
* While the next stop is less than [arrivalInMeters] away,
* [ArrivalController.onStopArrival] will be called
* [ArrivalController.navigateNextRouteLeg] will be called.
*/
val arrivalInMeters: Double?
) {
Expand All @@ -77,23 +71,23 @@ data class ArrivalOptions(

/**
* (Recommended) Use time estimation for arrival, arrival is influenced by traffic conditions.
* Arrive when the estimated time to a stop is less than or equal to this threshold
* Arrive when the estimated time to a stop is less than or equal to this threshold.
*/
fun arriveInSeconds(arriveInSeconds: Double?): Builder {
this.arrivalInSeconds = arriveInSeconds
return this
}

/**
* Arrive when the estimated distance to a stop is less than or equal to this threshold
* Arrive when the estimated distance to a stop is less than or equal to this threshold.
*/
fun arriveInMeters(arriveInMeters: Double?): Builder {
this.arrivalInMeters = arriveInMeters
return this
}

/**
* Build the object. If you want to disable this feature use [MapboxNavigation.removeArrivalController]
* Build the object. If you want to disable this feature use [MapboxNavigation.removeArrivalController].
*/
fun build(): ArrivalOptions {
check(arrivalInSeconds != null || arrivalInSeconds != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.mapbox.navigation.core.stops

import com.mapbox.navigation.base.trip.model.RouteLegProgress
import com.mapbox.navigation.base.trip.model.RouteProgress
import com.mapbox.navigation.base.trip.model.RouteProgressState
import com.mapbox.navigation.core.MapboxNavigation

/**
* This gives many observers the ability to monitor the progress of arrival.
* To control the behavior of arrival, see [ArrivalController]
*/
interface ArrivalObserver {

/**
* Once [MapboxNavigation.navigateNextRouteLeg] has been called and returns true,
* this observer will be notified of a stop arrival.
*/
fun onStopArrival(routeLegProgress: RouteLegProgress) {}

/**
* Once the [RouteProgress.currentState] has reached [RouteProgressState.ROUTE_ARRIVED]
* for the last stop, this will be called once.
*/
fun onRouteArrival(routeProgress: RouteProgress) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,46 @@ import com.mapbox.navigation.base.trip.model.RouteProgress
import com.mapbox.navigation.base.trip.model.RouteProgressState
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
import com.mapbox.navigation.core.trip.session.TripSession
import java.util.concurrent.CopyOnWriteArraySet

internal class ArrivalProgressObserver(
private val tripSession: TripSession
) : RouteProgressObserver {

private var arrivalController: ArrivalController = AutoArrivalController()
private val arrivalObservers = CopyOnWriteArraySet<ArrivalObserver>()
private var arrivedForRoute = false
Comment thread
kmadsen marked this conversation as resolved.

fun attach(arrivalController: ArrivalController) {
this.arrivalController = arrivalController
}

fun registerObserver(arrivalObserver: ArrivalObserver) {
arrivalObservers.add(arrivalObserver)
}

fun unregisterObserver(arrivalObserver: ArrivalObserver) {
arrivalObservers.remove(arrivalObserver)
}

fun navigateNextRouteLeg(): Boolean {
val numberOfLegs = tripSession.getRouteProgress()?.route()?.legs()?.size
val routeProgress = tripSession.getRouteProgress()
val numberOfLegs = routeProgress?.route()?.legs()?.size
?: return false
val legIndex = tripSession.getRouteProgress()?.currentLegProgress()?.legIndex()
val legProgress = routeProgress.currentLegProgress()
val legIndex = legProgress?.legIndex()
?: return false
val nextLegIndex = legIndex + 1
return if (nextLegIndex < numberOfLegs) {
val nextLegStarted = if (nextLegIndex < numberOfLegs) {
val navigationStatus = tripSession.updateLegIndex(nextLegIndex)
return nextLegIndex == navigationStatus.legIndex
} else {
true
false
Comment thread
kmadsen marked this conversation as resolved.
}
if (nextLegStarted) {
arrivalObservers.forEach { it.onStopArrival(legProgress) }
}
return nextLegStarted
}

override fun onRouteProgressChanged(routeProgress: RouteProgress) {
Expand Down Expand Up @@ -65,15 +81,15 @@ internal class ArrivalProgressObserver(
}

private fun doOnStopArrival(routeLegProgress: RouteLegProgress) {
val moveToNextLeg = arrivalController.onStopArrival(routeLegProgress)
val moveToNextLeg = arrivalController.navigateNextRouteLeg(routeLegProgress)
if (moveToNextLeg) {
navigateNextRouteLeg()
}
}

private fun doOnRouteArrival(routeProgress: RouteProgress) {
if (!arrivedForRoute) {
arrivalController.onRouteArrival(routeProgress)
arrivalObservers.forEach { it.onRouteArrival(routeProgress) }
}
}
}
Loading