Skip to content
Draft
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Mapbox welcomes participation and contributions from everyone.
- Fixed an issue with restricted road visualization on the route line that occurred during route refreshes. [#6399](https://github.com/mapbox/mapbox-navigation-android/pull/6399)
- Improved precision of restricted sections visualization, especially for long routes. [#6399](https://github.com/mapbox/mapbox-navigation-android/pull/6399)
- Fixed a rare issue where alternative route would not be vanished until deviation point for `MapboxRouteLineApi#setNavigationRoutes(routes, metadata)` when the route's geometry contained duplicate points. [#6399](https://github.com/mapbox/mapbox-navigation-android/pull/6399)
- Make `NavigationLocationProvider` an open class so it can be extended. [#6420](https://github.com/mapbox/mapbox-navigation-android/pull/6420)
- Make `NavigationLocationProvider` inherit from `MapboxNavigationObserver` so it can be used with `MapboxNavigationApp`. [#6420](https://github.com/mapbox/mapbox-navigation-android/pull/6420)
- Convert `LocationObserver` into a java interface with default functions so the functions are optional and new functions can be added. [#6420](https://github.com/mapbox/mapbox-navigation-android/pull/6420)

## Mapbox Navigation SDK 2.9.0-alpha.4 - 30 September, 2022
### Changelog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ class IndependentRouteGenerationActivity : AppCompatActivity() {
private val locationObserver = object : LocationObserver {
private var initialUpdateDone = false

override fun onNewRawLocation(rawLocation: Location) {}
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
val enhancedLocation = locationMatcherResult.enhancedLocation
if (!initialUpdateDone) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ class MapboxBuildingHighlightActivity : AppCompatActivity(), OnMapLongClickListe
}

private val locationObserver = object : LocationObserver {
override fun onNewRawLocation(rawLocation: Location) {}
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
navigationLocationProvider.changePosition(
locationMatcherResult.enhancedLocation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ class MapboxCustomStyleActivity : AppCompatActivity(), OnMapLongClickListener {
private val replayProgressObserver = ReplayProgressObserver(mapboxReplayer)

private val locationObserver = object : LocationObserver {
override fun onNewRawLocation(rawLocation: Location) {}
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
navigationLocationProvider.changePosition(
locationMatcherResult.enhancedLocation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ class MapboxJunctionActivity : AppCompatActivity(), OnMapLongClickListener {
private val replayProgressObserver = ReplayProgressObserver(mapboxReplayer)

private val locationObserver = object : LocationObserver {
override fun onNewRawLocation(rawLocation: Location) {}
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
navigationLocationProvider.changePosition(
locationMatcherResult.enhancedLocation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,6 @@ class MapboxManeuverActivity : AppCompatActivity(), OnMapLongClickListener {
}

private val locationObserver = object : LocationObserver {

override fun onNewRawLocation(rawLocation: Location) {}

override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
navigationLocationProvider.changePosition(
locationMatcherResult.enhancedLocation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,6 @@ class MapboxNavigationActivity : AppCompatActivity() {

/* ----- Location and route progress callbacks ----- */
private val locationObserver = object : LocationObserver {
override fun onNewRawLocation(rawLocation: Location) {
// not handled
}

override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
// update location puck's position on the map
navigationLocationProvider.changePosition(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,6 @@ class MapboxRouteLineAndArrowActivity : AppCompatActivity(), OnMapLongClickListe
}

private val locationObserver = object : LocationObserver {
override fun onNewRawLocation(rawLocation: Location) {}
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
navigationLocationProvider.changePosition(
locationMatcherResult.enhancedLocation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,6 @@ class MapboxCameraAnimationsActivity :
private val poiSource = geoJsonSource("circle_source") {}.data("")

private val locationObserver = object : LocationObserver {

override fun onNewRawLocation(rawLocation: Location) {}

override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
val transitionOptions: (ValueAnimator.() -> Unit) =
if (locationMatcherResult.isTeleport) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ class FirstLocationIdlingResource(

/** Used to communicate with [MapboxNavigation.registerLocationObserver] **/
private val locationObserver = object : LocationObserver {
override fun onNewRawLocation(rawLocation: Location) {
// Do nothing
}

override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
if (firstLocation == null) {
firstLocation = locationMatcherResult.enhancedLocation
Expand Down
4 changes: 2 additions & 2 deletions libnavigation-core/api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -932,8 +932,8 @@ package com.mapbox.navigation.core.trip.session {
}

@UiThread public interface LocationObserver {
method public void onNewLocationMatcherResult(com.mapbox.navigation.core.trip.session.LocationMatcherResult locationMatcherResult);
method public void onNewRawLocation(android.location.Location rawLocation);
method public default void onNewLocationMatcherResult(com.mapbox.navigation.core.trip.session.LocationMatcherResult);
method public default void onNewRawLocation(android.location.Location);
}

public abstract sealed class NavigationSessionState {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.mapbox.navigation.core.trip.session;

import android.location.Location;

import androidx.annotation.NonNull;
import androidx.annotation.UiThread;

/**
* An interface which enables listening to location updates
*
* @see LocationMatcherResult
*/
@UiThread
public interface LocationObserver {

/**
* Invoked as soon as a new [Location] has been received.
*
* @param rawLocation un-snapped update
*/
default void onNewRawLocation(@NonNull Location rawLocation) {
// Override to capture
}

/**
* Provides the best possible location update, snapped to the route or map-matched to the road if possible.
*
* @param locationMatcherResult details about the status of the enhanced location.
*/
default void onNewLocationMatcherResult(@NonNull LocationMatcherResult locationMatcherResult) {
// Override to capture
}
}

This file was deleted.

20 changes: 14 additions & 6 deletions libnavui-maps/api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -717,15 +717,23 @@ package com.mapbox.navigation.ui.maps.installer {

package com.mapbox.navigation.ui.maps.location {

public final class NavigationLocationProvider implements com.mapbox.maps.plugin.locationcomponent.LocationProvider {
public class NavigationLocationProvider implements com.mapbox.navigation.core.trip.session.LocationObserver com.mapbox.maps.plugin.locationcomponent.LocationProvider com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver {
ctor public NavigationLocationProvider();
method public void changePosition(android.location.Location location, java.util.List<? extends android.location.Location> keyPoints = emptyList(), kotlin.jvm.functions.Function1<? super android.animation.ValueAnimator,kotlin.Unit>? latLngTransitionOptions = null, kotlin.jvm.functions.Function1<? super android.animation.ValueAnimator,kotlin.Unit>? bearingTransitionOptions = null);
method public java.util.List<android.location.Location> getLastKeyPoints();
method public android.location.Location? getLastLocation();
method public void registerLocationConsumer(com.mapbox.maps.plugin.locationcomponent.LocationConsumer locationConsumer);
method public void unRegisterLocationConsumer(com.mapbox.maps.plugin.locationcomponent.LocationConsumer locationConsumer);
method @CallSuper public final void changePosition(android.location.Location location, java.util.List<? extends android.location.Location> keyPoints = emptyList(), kotlin.jvm.functions.Function1<? super android.animation.ValueAnimator,kotlin.Unit>? latLngTransitionOptions = null, kotlin.jvm.functions.Function1<? super android.animation.ValueAnimator,kotlin.Unit>? bearingTransitionOptions = null);
method public final java.util.List<android.location.Location> getLastKeyPoints();
method public final android.location.Location? getLastLocation();
method public static final com.mapbox.navigation.ui.maps.location.NavigationLocationProvider getRegisteredInstance();
method @CallSuper public void onAttached(com.mapbox.navigation.core.MapboxNavigation mapboxNavigation);
method @CallSuper public void onDetached(com.mapbox.navigation.core.MapboxNavigation mapboxNavigation);
method public final void registerLocationConsumer(com.mapbox.maps.plugin.locationcomponent.LocationConsumer locationConsumer);
method public final void unRegisterLocationConsumer(com.mapbox.maps.plugin.locationcomponent.LocationConsumer locationConsumer);
property public final java.util.List<android.location.Location> lastKeyPoints;
property public final android.location.Location? lastLocation;
field public static final com.mapbox.navigation.ui.maps.location.NavigationLocationProvider.Companion Companion;
}

public static final class NavigationLocationProvider.Companion {
method public com.mapbox.navigation.ui.maps.location.NavigationLocationProvider getRegisteredInstance();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ package com.mapbox.navigation.ui.maps.location
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.location.Location
import androidx.annotation.CallSuper
import com.mapbox.geojson.Point
import com.mapbox.maps.plugin.locationcomponent.LocationComponentConstants
import com.mapbox.maps.plugin.locationcomponent.LocationComponentPlugin
import com.mapbox.maps.plugin.locationcomponent.LocationConsumer
import com.mapbox.maps.plugin.locationcomponent.LocationProvider
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorPositionChangedListener
import com.mapbox.navigation.core.MapboxNavigation
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
import com.mapbox.navigation.core.trip.session.LocationMatcherResult
import com.mapbox.navigation.core.trip.session.LocationObserver
import com.mapbox.navigation.ui.maps.internal.location.PuckAnimationEvaluator
import com.mapbox.navigation.utils.internal.ifNonNull
Expand Down Expand Up @@ -53,7 +57,10 @@ import java.util.concurrent.CopyOnWriteArraySet
* }
* ```
*/
class NavigationLocationProvider : LocationProvider {
open class NavigationLocationProvider :
LocationProvider,
LocationObserver,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By implementing the interface directly, we're exposing it as part of the NavigationLocationProvider surface, while it's not needed. The LocationObserver instance could be a member of the NavigationLocationProvider instead.

Copy link
Contributor Author

@kmadsen kmadsen Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes it so you can capture onNewLocationMatcherResult events downstream.

LocationConsumer does not give access to LocationMatcherResult. If it is internal, we need a another way to surface the map matched locations. Do you think there should be another registry of LocationObserver observers?

MapboxNavigationObserver {

private val locationConsumers = CopyOnWriteArraySet<LocationConsumer>()

Expand All @@ -73,6 +80,17 @@ class NavigationLocationProvider : LocationProvider {
var lastKeyPoints: List<Location> = emptyList()
private set

/**
* Automatically updated when this class is registered to [MapboxNavigationApp]
*/
@CallSuper
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
changePosition(
locationMatcherResult.enhancedLocation,
locationMatcherResult.keyPoints,
)
}

/**
* Register the location consumer to the Location Provider.
*
Expand All @@ -81,7 +99,7 @@ class NavigationLocationProvider : LocationProvider {
* @param locationConsumer
*/
@SuppressLint("MissingPermission")
override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
final override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
if (locationConsumers.add(locationConsumer)) {
ifNonNull(lastLocation, lastKeyPoints) { location, keyPoints ->
locationConsumer.notifyLocationUpdates(
Expand All @@ -103,7 +121,7 @@ class NavigationLocationProvider : LocationProvider {
*
* @param locationConsumer
*/
override fun unRegisterLocationConsumer(locationConsumer: LocationConsumer) {
final override fun unRegisterLocationConsumer(locationConsumer: LocationConsumer) {
locationConsumers.remove(locationConsumer)
}

Expand All @@ -122,6 +140,7 @@ class NavigationLocationProvider : LocationProvider {
* @see LocationObserver
* @see MapboxNavigation.registerLocationObserver
*/
@CallSuper
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about making this final.. Leaving it open provides more flexibility but it's not covering a real use case.

Once it is open it cannot be closed, so am debating making it final. Maybe someone would want to intercept these events 🤔

fun changePosition(
location: Location,
keyPoints: List<Location> = emptyList(),
Expand All @@ -140,6 +159,27 @@ class NavigationLocationProvider : LocationProvider {
lastKeyPoints = keyPoints
}

/**
* Use [getRegisteredInstance] to share a single instance of the [NavigationLocationProvider].
*
* @see [MapboxNavigationApp]
*/
@CallSuper
override fun onAttached(mapboxNavigation: MapboxNavigation) {
mapboxNavigation.registerLocationObserver(this)
}

/**
* Disabled automatically with the [MapboxNavigationApp]. You can manually disable with
* [MapboxNavigationApp.unregisterObserver].
*
* @see [MapboxNavigationApp]
*/
@CallSuper
override fun onDetached(mapboxNavigation: MapboxNavigation) {
mapboxNavigation.unregisterLocationObserver(this)
}

private fun LocationConsumer.notifyLocationUpdates(
location: Location,
keyPoints: List<Location>,
Expand Down Expand Up @@ -176,4 +216,14 @@ class NavigationLocationProvider : LocationProvider {
clientOptions?.also { apply(it) }
}
}

companion object {
/**
* Get the registered instance or create one and register it to [MapboxNavigationApp].
*/
@JvmStatic
fun getRegisteredInstance(): NavigationLocationProvider = MapboxNavigationApp
.getObservers(NavigationLocationProvider::class).firstOrNull()
?: NavigationLocationProvider().also { MapboxNavigationApp.registerObserver(it) }
}
}
Loading