Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
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 @@ -89,13 +89,9 @@ void updateAnimatorListenerHolders(@NonNull Set<AnimatorListenerHolder> listener
}
}

void feedNewLocation(@NonNull Location newLocation, @NonNull CameraPosition currentCameraPosition,
boolean isGpsNorth) {
feedNewLocation(new Location[] {newLocation}, currentCameraPosition, isGpsNorth, false);
}

void feedNewLocation(@NonNull @Size(min = 1) Location[] newLocations,
@NonNull CameraPosition currentCameraPosition, boolean isGpsNorth, boolean lookAheadUpdate) {
@NonNull CameraPosition currentCameraPosition, boolean isGpsNorth,
@Nullable Long animationDuration) {
Location newLocation = newLocations[newLocations.length - 1];
if (previousLocation == null) {
previousLocation = newLocation;
Expand Down Expand Up @@ -125,28 +121,20 @@ void feedNewLocation(@NonNull @Size(min = 1) Location[] newLocations,
boolean snap = immediateAnimation(projection, previousCameraLatLng, targetLatLng)
|| immediateAnimation(projection, previousLayerLatLng, targetLatLng);

long animationDuration = 0;
if (!snap) {
long previousUpdateTimeStamp = locationUpdateTimestamp;
locationUpdateTimestamp = SystemClock.elapsedRealtime();

if (previousUpdateTimeStamp == 0) {
animationDuration = 0;
} else if (lookAheadUpdate) {
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp > newLocation.getTime()) {
animationDuration = 0;
Logger.e("LocationAnimatorCoordinator",
"Lookahead enabled, but the target location's timestamp is smaller than current timestamp");
long previousUpdateTimeStamp = locationUpdateTimestamp;
locationUpdateTimestamp = SystemClock.elapsedRealtime();
if (animationDuration == null) {
animationDuration = 0L;
if (!snap) {
if (previousUpdateTimeStamp == 0) {
animationDuration = 0L;
} else {
animationDuration = newLocation.getTime() - currentTimestamp;
animationDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * durationMultiplier)
/* make animation slightly longer with durationMultiplier, defaults to 1.1f */;
}
} else {
animationDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * durationMultiplier)
/* make animation slightly longer with durationMultiplier, defaults to 1.1f */;
}

animationDuration = Math.min(animationDuration, MAX_ANIMATION_DURATION_MS);
animationDuration = Math.min(animationDuration, MAX_ANIMATION_DURATION_MS);
}
}

playAnimators(animationDuration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.content.Context;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
import android.view.WindowManager;
Expand Down Expand Up @@ -41,6 +42,7 @@
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
Expand Down Expand Up @@ -185,7 +187,7 @@ public final class LocationComponent {
private final CopyOnWriteArrayList<OnRenderModeChangedListener> onRenderModeChangedListeners
= new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<OnIndicatorPositionChangedListener> onIndicatorPositionChangedListener
= new CopyOnWriteArrayList<>();
= new CopyOnWriteArrayList<>();

// Workaround for too frequent updates, see https://github.com/mapbox/mapbox-gl-native/issues/13587
private long fastestInterval;
Expand Down Expand Up @@ -239,6 +241,34 @@ public LocationComponent(@NonNull MapboxMap mapboxMap,
isComponentInitialized = true;
}

@VisibleForTesting
LocationComponent(@NonNull MapboxMap mapboxMap,
@NonNull Transform transform,
@NonNull List<MapboxMap.OnDeveloperAnimationListener> developerAnimationListeners,
@NonNull LocationEngineCallback<LocationEngineResult> currentListener,
@NonNull LocationLayerController locationLayerController,
@NonNull LocationCameraController locationCameraController,
@NonNull LocationAnimatorCoordinator locationAnimatorCoordinator,
@NonNull StaleStateManager staleStateManager,
@NonNull CompassEngine compassEngine,
@NonNull InternalLocationEngineProvider internalLocationEngineProvider,
boolean useSpecializedLocationLayer,
@NonNull LocationEngineRequest locationEngineRequest) {
this.mapboxMap = mapboxMap;
this.transform = transform;
developerAnimationListeners.add(developerAnimationListener);
this.currentLocationEngineListener = currentListener;
this.locationLayerController = locationLayerController;
this.locationCameraController = locationCameraController;
this.locationAnimatorCoordinator = locationAnimatorCoordinator;
this.staleStateManager = staleStateManager;
this.compassEngine = compassEngine;
this.internalLocationEngineProvider = internalLocationEngineProvider;
this.useSpecializedLocationLayer = useSpecializedLocationLayer;
this.locationEngineRequest = locationEngineRequest;
isComponentInitialized = true;
}

/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
Expand Down Expand Up @@ -885,19 +915,19 @@ public void paddingWhileTracking(double[] padding, long animationDuration) {
* @param callback The callback with finish/cancel information
*/
public void paddingWhileTracking(double[] padding, long animationDuration,
@Nullable MapboxMap.CancelableCallback callback) {
@Nullable MapboxMap.CancelableCallback callback) {
checkActivationState();
if (!isLayerReady) {
notifyUnsuccessfulCameraOperation(callback, null);
return;
} else if (getCameraMode() == CameraMode.NONE) {
notifyUnsuccessfulCameraOperation(callback, String.format("%s%s",
"LocationComponent#paddingWhileTracking method can only be used",
" when a camera mode other than CameraMode#NONE is engaged."));
"LocationComponent#paddingWhileTracking method can only be used",
" when a camera mode other than CameraMode#NONE is engaged."));
return;
} else if (locationCameraController.isTransitioning()) {
notifyUnsuccessfulCameraOperation(callback,
"LocationComponent#paddingWhileTracking method call is ignored because the camera mode is transitioning");
"LocationComponent#paddingWhileTracking method call is ignored because the camera mode is transitioning");
return;
}

Expand Down Expand Up @@ -996,7 +1026,9 @@ public void cancelTiltWhileTrackingAnimation() {
* updated.
*
* @param location where the location icon is placed on the map
* @deprecated use {@link #forceLocationUpdate(LocationUpdate)} instead
*/
@Deprecated
public void forceLocationUpdate(@Nullable Location location) {
checkActivationState();
updateLocation(location, false);
Expand All @@ -1014,20 +1046,62 @@ public void forceLocationUpdate(@Nullable Location location) {
* @param lookAheadUpdate If set to true, the last location's timestamp has to be greater than current timestamp and
* should represent the time at which the animation should actually reach this position,
* cutting out the time interpolation delay.
* @deprecated use {@link #forceLocationUpdate(LocationUpdate)} instead
*/
@Deprecated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Perhaps do not see whole picture but why is logic changed for already deprecated method?
IMHO it should have worked the same way it did before while new non-deprecated method is introduced.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I moved the calculation of duration out of the animator coordinator to maintain compatibility since the coordinator now accepts the duration as an argument.

public void forceLocationUpdate(@Nullable List<Location> locations, boolean lookAheadUpdate) {
checkActivationState();
if (locations != null && locations.size() >= 1) {
Location targetLocation = locations.get(locations.size() - 1);
if (targetLocation == null) {
return;
}
LocationUpdate.Builder builder = new LocationUpdate.Builder()
.location(targetLocation)
.intermediatePoints(locations.subList(0, locations.size() - 1));

if (lookAheadUpdate) {
long currentTimestampNs;
long locationTimestampNs;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
currentTimestampNs = SystemClock.elapsedRealtimeNanos();
locationTimestampNs = targetLocation.getElapsedRealtimeNanos();
if (locationTimestampNs == 0) {
// fallback in case the elapsed realtime is not set
currentTimestampNs = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
locationTimestampNs = TimeUnit.MILLISECONDS.toNanos(targetLocation.getTime());
}
} else {
currentTimestampNs = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
locationTimestampNs = TimeUnit.MILLISECONDS.toNanos(targetLocation.getTime());
}

if (currentTimestampNs > locationTimestampNs) {
builder.animationDuration(0L);
Logger.e("LocationAnimatorCoordinator",
"Lookahead enabled, but the target location's timestamp is smaller than current timestamp");
} else {
builder.animationDuration(locationTimestampNs - currentTimestampNs);
}
}
updateLocation(
locations.get(locations.size() - 1), // target location
locations.subList(0, locations.size() - 1), // intermediate locations
false,
lookAheadUpdate);
} else {
updateLocation(null, false);
builder.build(),
false
);
}
}

/**
* Use to either force a location update or to manually control when the user location gets
* updated.
*
* @param locationUpdate location update
* @see LocationUpdate.Builder
*/
public void forceLocationUpdate(@NonNull LocationUpdate locationUpdate) {
updateLocation(locationUpdate, false);
}

/**
* Set max FPS at which location animators can output updates. The throttling will only impact the location puck
* and camera tracking smooth animations.
Expand Down Expand Up @@ -1515,15 +1589,19 @@ private void updateMapWithOptions(@NonNull LocationComponentOptions options) {
* @param location the latest user location
*/
private void updateLocation(@Nullable final Location location, boolean fromLastLocation) {
updateLocation(location, null, fromLastLocation, false);
if (location != null) {
updateLocation(
new LocationUpdate.Builder()
.location(location)
.build(),
fromLastLocation
);
}
}

private void updateLocation(@Nullable final Location location, @Nullable List<Location> intermediatePoints,
boolean fromLastLocation, boolean lookAheadUpdate) {
if (location == null) {
return;
} else if (!isLayerReady) {
lastLocation = location;
private void updateLocation(@NonNull LocationUpdate locationUpdate, boolean fromLastLocation) {
if (!isLayerReady) {
lastLocation = locationUpdate.getLocation();
return;
} else {
long currentTime = SystemClock.elapsedRealtime();
Expand All @@ -1541,17 +1619,13 @@ private void updateLocation(@Nullable final Location location, @Nullable List<Lo
}
CameraPosition currentCameraPosition = mapboxMap.getCameraPosition();
boolean isGpsNorth = getCameraMode() == CameraMode.TRACKING_GPS_NORTH;
if (intermediatePoints != null) {
locationAnimatorCoordinator.feedNewLocation(
getTargetLocationWithIntermediates(location, intermediatePoints),
currentCameraPosition,
isGpsNorth,
lookAheadUpdate);
} else {
locationAnimatorCoordinator.feedNewLocation(location, currentCameraPosition, isGpsNorth);
}
updateAccuracyRadius(location, false);
lastLocation = location;
locationAnimatorCoordinator.feedNewLocation(
getTargetLocationWithIntermediates(locationUpdate.getLocation(), locationUpdate.getIntermediatePoints()),
currentCameraPosition,
isGpsNorth,
fromLastLocation ? Long.valueOf(0L) : locationUpdate.getAnimationDuration());
updateAccuracyRadius(locationUpdate.getLocation(), false);
lastLocation = locationUpdate.getLocation();
}

private Location[] getTargetLocationWithIntermediates(Location location, List<Location> intermediatePoints) {
Expand Down Expand Up @@ -1800,7 +1874,8 @@ public void onRenderModeChanged(int currentMode) {
@NonNull
@VisibleForTesting
OnIndicatorPositionChangedListener indicatorPositionChangedListener = new OnIndicatorPositionChangedListener() {
@Override public void onIndicatorPositionChanged(@NonNull Point point) {
@Override
public void onIndicatorPositionChanged(@NonNull Point point) {
for (OnIndicatorPositionChangedListener listener : onIndicatorPositionChangedListener) {
listener.onIndicatorPositionChanged(point);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1867,6 +1867,8 @@ public LocationComponentOptions.Builder layerBelow(String layerBelow) {

/**
* Sets the tracking animation duration multiplier.
* <p>
* <b>This value is ignored if {@link LocationUpdate.Builder#animationDuration(Long)} is provided.</b>
*
* @param trackingAnimationDurationMultiplier the tracking animation duration multiplier
*/
Expand Down
Loading