diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRenderer.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRenderer.java
index d9ae215dd..5cb1f37df 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRenderer.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRenderer.java
@@ -8,6 +8,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
import com.mapbox.mapboxsdk.utils.ColorUtils;
@@ -26,26 +27,30 @@ class IndicatorLocationLayerRenderer implements LocationLayerRenderer {
private Style style;
private final LayerSourceProvider layerSourceProvider;
- private LocationIndicatorLayer layer;
+ private Layer layer;
@Nullable
- private LatLng latLng;
+ private LatLng lastLatLng;
+ private double lastBearing = 0;
+ private float lastAccuracy = 0;
- IndicatorLocationLayerRenderer(Style style,
- LayerSourceProvider layerSourceProvider) {
- this.style = style;
+ IndicatorLocationLayerRenderer(LayerSourceProvider layerSourceProvider) {
this.layerSourceProvider = layerSourceProvider;
}
@Override
public void initializeComponents(Style style) {
this.style = style;
+ layer = layerSourceProvider.generateLocationComponentLayer();
+ if (lastLatLng != null) {
+ setLatLng(lastLatLng);
+ }
+ setLayerBearing(lastBearing);
+ setAccuracyRadius(lastAccuracy);
}
@Override
public void addLayers(LocationComponentPositionManager positionManager) {
- layer = layerSourceProvider.generateLocationComponentLayer();
- setLayerLocation(latLng);
positionManager.addLayerToMap(layer);
}
@@ -106,6 +111,7 @@ class IndicatorLocationLayerRenderer implements LocationLayerRenderer {
layer.setProperties(
LocationPropertyFactory.accuracyRadius(accuracy)
);
+ lastAccuracy = accuracy;
}
@Override
@@ -160,20 +166,19 @@ class IndicatorLocationLayerRenderer implements LocationLayerRenderer {
layer.setProperties(LocationPropertyFactory.visibility(visible ? VISIBLE : NONE));
}
- private void setLayerLocation(@Nullable LatLng latLng) {
- this.latLng = latLng;
- if (latLng != null) {
- Double[] values = new Double[] {latLng.getLatitude(), latLng.getLongitude(), 0d};
- layer.setProperties(
- LocationPropertyFactory.location(values)
- );
- }
+ private void setLayerLocation(LatLng latLng) {
+ Double[] values = new Double[] {latLng.getLatitude(), latLng.getLongitude(), 0d};
+ layer.setProperties(
+ LocationPropertyFactory.location(values)
+ );
+ lastLatLng = latLng;
}
private void setLayerBearing(double bearing) {
layer.setProperties(
LocationPropertyFactory.bearing(bearing)
);
+ lastBearing = bearing;
}
private void setImages(@RenderMode.Mode int renderMode, boolean isStale) {
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java
index d33206f10..3626f42db 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java
@@ -117,7 +117,16 @@ class LayerSourceProvider {
return new HashSet<>();
}
- LocationIndicatorLayer generateLocationComponentLayer() {
+ LocationLayerRenderer getSymbolLocationLayerRenderer(LayerFeatureProvider featureProvider,
+ boolean isStale) {
+ return new SymbolLocationLayerRenderer(this, featureProvider, isStale);
+ }
+
+ LocationLayerRenderer getIndicatorLocationLayerRenderer() {
+ return new IndicatorLocationLayerRenderer(this);
+ }
+
+ Layer generateLocationComponentLayer() {
LocationIndicatorLayer layer = new LocationIndicatorLayer(FOREGROUND_LAYER);
layer.setProperties(
LocationPropertyFactory.perspectiveCompensation(0.9f),
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
index 733dbb259..bbb60289d 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
@@ -141,7 +141,7 @@ public final class LocationComponent {
private boolean isComponentInitialized;
/**
- * Indicates whether we're using the {@link com.mapbox.mapboxsdk.style.layers.LocationIndicatorLayer}
+ * Indicates whether we're using the {@link com.mapbox.mapboxsdk.location.LocationIndicatorLayer}
* or the stack of {@link com.mapbox.mapboxsdk.style.layers.SymbolLayer}s.
*/
private boolean useSpecializedLocationLayer;
@@ -217,7 +217,8 @@ public final class LocationComponent {
@NonNull LocationAnimatorCoordinator locationAnimatorCoordinator,
@NonNull StaleStateManager staleStateManager,
@NonNull CompassEngine compassEngine,
- @NonNull InternalLocationEngineProvider internalLocationEngineProvider) {
+ @NonNull InternalLocationEngineProvider internalLocationEngineProvider,
+ boolean useSpecializedLocationLayer) {
this.mapboxMap = mapboxMap;
this.transform = transform;
developerAnimationListeners.add(developerAnimationListener);
@@ -229,6 +230,7 @@ public final class LocationComponent {
this.staleStateManager = staleStateManager;
this.compassEngine = compassEngine;
this.internalLocationEngineProvider = internalLocationEngineProvider;
+ this.useSpecializedLocationLayer = useSpecializedLocationLayer;
isComponentInitialized = true;
}
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentActivationOptions.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentActivationOptions.java
index 91f6141dd..bc295e920 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentActivationOptions.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentActivationOptions.java
@@ -123,14 +123,14 @@ public class LocationComponentActivationOptions {
/**
* True if you want to initialize and use the specialized location layer to render the location puck.
*
- * The specialized layer comes with significant performance improvements,
+ * The specialized layer is not based on runtime styling. This brings significant performance improvements,
* but since it's not based on the runtime styling,
* it's not fully compatible with the traditional implementation. The incompatibilities are:
*
* - Constants like {@link LocationComponentConstants#FOREGROUND_LAYER}
* or {@link LocationComponentConstants#LOCATION_SOURCE} are ignored.
*
- All options that alter the image ID, like {@link LocationComponentOptions#foregroundName()}, are ignored.
- * Use {@link LocationComponentOptions#foregroundDrawable()} instead.
+ * Use {@link LocationComponentOptions#foregroundDrawable()} to alter the image rendered as the puck.
*
*
* @return whether the default specialized location layer is used
@@ -236,14 +236,14 @@ public class LocationComponentActivationOptions {
/**
* True if you want to initialize and use the specialized location layer to render the location puck.
*
- * The specialized layer comes with significant performance improvements,
+ * The specialized layer is not based on runtime styling. This brings significant performance improvements,
* but since it's not based on the runtime styling,
* it's not fully compatible with the traditional implementation. The incompatibilities are:
*
* - Constants like {@link LocationComponentConstants#FOREGROUND_LAYER}
* or {@link LocationComponentConstants#LOCATION_SOURCE} are ignored.
*
- All options that alter the image ID, like {@link LocationComponentOptions#foregroundName()}, are ignored.
- * Use {@link LocationComponentOptions#foregroundDrawable()} instead.
+ * Use {@link LocationComponentOptions#foregroundDrawable()} to alter the image rendered as the puck.
*
*
* @param useSpecializedLocationLayer true if you want to initialize and use the
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
index 556254297..656191ddb 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
@@ -39,7 +39,6 @@ final class LocationLayerController {
private int renderMode;
private final MapboxMap mapboxMap;
- private Style style;
private final LayerBitmapProvider bitmapProvider;
private LocationComponentOptions options;
private final OnRenderModeChangedListener internalRenderModeChangedListener;
@@ -60,21 +59,20 @@ final class LocationLayerController {
@NonNull OnRenderModeChangedListener internalRenderModeChangedListener,
boolean useSpecializedLocationLayer) {
this.mapboxMap = mapboxMap;
- this.style = style;
this.bitmapProvider = bitmapProvider;
this.internalRenderModeChangedListener = internalRenderModeChangedListener;
this.useSpecializedLocationLayer = useSpecializedLocationLayer;
this.isStale = options.enableStaleState();
if (useSpecializedLocationLayer) {
- locationLayerRenderer = new IndicatorLocationLayerRenderer(style, layerSourceProvider);
+ locationLayerRenderer = layerSourceProvider.getIndicatorLocationLayerRenderer();
} else {
- locationLayerRenderer = new SymbolLocationLayerRenderer(style, layerSourceProvider, featureProvider, isStale);
+ locationLayerRenderer =
+ layerSourceProvider.getSymbolLocationLayerRenderer(featureProvider, isStale);
}
initializeComponents(style, options);
}
void initializeComponents(Style style, LocationComponentOptions options) {
- this.style = style;
this.positionManager = new LocationComponentPositionManager(style, options.layerAbove(), options.layerBelow());
locationLayerRenderer.initializeComponents(style);
locationLayerRenderer.addLayers(positionManager);
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/SymbolLocationLayerRenderer.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/SymbolLocationLayerRenderer.java
index 7ad336313..ae722b3d2 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/SymbolLocationLayerRenderer.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/SymbolLocationLayerRenderer.java
@@ -58,11 +58,9 @@ final class SymbolLocationLayerRenderer implements LocationLayerRenderer {
private Feature locationFeature;
private GeoJsonSource locationSource;
- SymbolLocationLayerRenderer(Style style,
- LayerSourceProvider layerSourceProvider,
+ SymbolLocationLayerRenderer(LayerSourceProvider layerSourceProvider,
LayerFeatureProvider featureProvider,
boolean isStale) {
- this.style = style;
this.layerSourceProvider = layerSourceProvider;
this.layerSet = layerSourceProvider.getEmptyLayerSet();
this.locationFeature = featureProvider.generateLocationFeature(locationFeature, isStale);
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java
index 735ba3d70..871ac36f9 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java
@@ -10,6 +10,8 @@ import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.utils.ColorUtils;
+import java.util.Arrays;
+
/**
* Properties for Layer
*/
@@ -124,4 +126,35 @@ public class PropertyValue {
public String toString() {
return String.format("%s: %s", name, value);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ PropertyValue> that = (PropertyValue>) o;
+
+ if (!name.equals(that.name)) {
+ return false;
+ }
+ if (value != null) {
+ if (value instanceof Object[]) {
+ return Arrays.deepEquals((Object[]) value, (Object[]) that.value);
+ }
+ return value.equals(that.value);
+ } else {
+ return that.value == null;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name.hashCode();
+ result = 31 * result + (value != null ? value.hashCode() : 0);
+ return result;
+ }
}
diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRendererTest.kt b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRendererTest.kt
new file mode 100644
index 000000000..0d485952b
--- /dev/null
+++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/IndicatorLocationLayerRendererTest.kt
@@ -0,0 +1,327 @@
+package com.mapbox.mapboxsdk.location
+
+import android.graphics.Bitmap
+import android.graphics.Color
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.location.LocationComponentConstants.*
+import com.mapbox.mapboxsdk.location.modes.RenderMode
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.style.expressions.Expression
+import com.mapbox.mapboxsdk.style.layers.Layer
+import com.mapbox.mapboxsdk.style.layers.Property
+import com.mapbox.mapboxsdk.utils.BitmapUtils
+import com.mapbox.mapboxsdk.utils.ColorUtils
+import io.mockk.*
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+
+class IndicatorLocationLayerRendererTest {
+
+ private val style: Style = mockk(relaxUnitFun = true)
+ private val layerSourceProvider: LayerSourceProvider = mockk(relaxUnitFun = true)
+ private val layer: Layer = mockk(relaxUnitFun = true)
+
+ private lateinit var locationLayerRenderer: IndicatorLocationLayerRenderer
+
+ @Before
+ fun setup() {
+ every { style.removeLayer(any()) } returns true
+ locationLayerRenderer = IndicatorLocationLayerRenderer(layerSourceProvider)
+ every { layerSourceProvider.generateLocationComponentLayer() } returns layer
+ locationLayerRenderer.initializeComponents(style)
+ }
+
+ @Test
+ fun sanity() {
+ Assert.assertNotNull(locationLayerRenderer)
+ }
+
+ @Test
+ fun initializeComponents_withLocation() {
+ val newLayer: Layer = mockk(relaxUnitFun = true)
+ every { layerSourceProvider.generateLocationComponentLayer() } returns newLayer
+ val latLng = LatLng(10.0, 20.0)
+ val bearing = 11f
+ val accuracy = 65f
+ locationLayerRenderer.setLatLng(latLng)
+ locationLayerRenderer.setGpsBearing(bearing)
+ locationLayerRenderer.setAccuracyRadius(accuracy)
+
+ locationLayerRenderer.initializeComponents(mockk())
+
+ verify { newLayer.setProperties(LocationPropertyFactory.location(latLng.toLocationArray())) }
+ verify { newLayer.setProperties(LocationPropertyFactory.bearing(bearing.toDouble())) }
+ verify { newLayer.setProperties(LocationPropertyFactory.accuracyRadius(accuracy)) }
+ }
+
+ @Test
+ fun addLayers() {
+ val positionManager: LocationComponentPositionManager = mockk(relaxUnitFun = true)
+
+ locationLayerRenderer.addLayers(positionManager)
+
+ verify { positionManager.addLayerToMap(layer) }
+ }
+
+ @Test
+ fun removeLayers() {
+ locationLayerRenderer.removeLayers()
+
+ verify { style.removeLayer(layer) }
+ }
+
+ @Test
+ fun hide() {
+ locationLayerRenderer.hide()
+
+ verify { layer.setProperties(LocationPropertyFactory.visibility(Property.NONE)) }
+ }
+
+ @Test
+ fun show() {
+ locationLayerRenderer.show(RenderMode.NORMAL, false)
+
+ verify { layer.setProperties(LocationPropertyFactory.visibility(Property.VISIBLE)) }
+ }
+
+ @Test
+ fun show_normal_notStale() {
+ locationLayerRenderer.show(RenderMode.NORMAL, false)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(FOREGROUND_ICON),
+ LocationPropertyFactory.bearingImage(BACKGROUND_ICON),
+ LocationPropertyFactory.shadowImage(SHADOW_ICON)
+ )
+ }
+ }
+
+ @Test
+ fun show_compass_notStale() {
+ locationLayerRenderer.show(RenderMode.COMPASS, false)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(FOREGROUND_ICON),
+ LocationPropertyFactory.bearingImage(BEARING_ICON),
+ LocationPropertyFactory.shadowImage(SHADOW_ICON)
+ )
+ }
+ }
+
+ @Test
+ fun show_gps_notStale() {
+ locationLayerRenderer.show(RenderMode.GPS, false)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(""),
+ LocationPropertyFactory.bearingImage(FOREGROUND_ICON),
+ LocationPropertyFactory.shadowImage("")
+ )
+ }
+ verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(0f)) }
+ }
+
+ @Test
+ fun show_normal_stale() {
+ locationLayerRenderer.show(RenderMode.NORMAL, true)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
+ LocationPropertyFactory.bearingImage(BACKGROUND_STALE_ICON),
+ LocationPropertyFactory.shadowImage(SHADOW_ICON)
+ )
+ }
+ }
+
+ @Test
+ fun show_compass_stale() {
+ locationLayerRenderer.show(RenderMode.COMPASS, true)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
+ LocationPropertyFactory.bearingImage(BEARING_STALE_ICON),
+ LocationPropertyFactory.shadowImage(SHADOW_ICON)
+ )
+ }
+ }
+
+ @Test
+ fun show_gps_stale() {
+ locationLayerRenderer.show(RenderMode.GPS, true)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(""),
+ LocationPropertyFactory.bearingImage(FOREGROUND_STALE_ICON),
+ LocationPropertyFactory.shadowImage("")
+ )
+ }
+ verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(0f)) }
+ }
+
+ @Test
+ fun styleAccuracy() {
+ val colorArray = ColorUtils.colorToRgbaArray(Color.RED)
+ val exp = Expression.rgba(colorArray[0], colorArray[1], colorArray[2], 0.7f)
+
+ locationLayerRenderer.styleAccuracy(0.7f, Color.RED)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.accuracyRadiusColor(exp),
+ LocationPropertyFactory.accuracyRadiusBorderColor(exp)
+ )
+ }
+ }
+
+ @Test
+ fun setLatLng() {
+ val latLng = LatLng(10.0, 20.0)
+ locationLayerRenderer.setLatLng(latLng)
+
+ verify { layer.setProperties(LocationPropertyFactory.location(latLng.toLocationArray())) }
+ }
+
+ @Test
+ fun setGpsBearing() {
+ val bearing = 30.0
+ locationLayerRenderer.setGpsBearing(bearing.toFloat())
+
+ verify { layer.setProperties(LocationPropertyFactory.bearing(bearing)) }
+ }
+
+ @Test
+ fun setCompassBearing() {
+ val bearing = 30.0
+ locationLayerRenderer.setCompassBearing(bearing.toFloat())
+
+ verify { layer.setProperties(LocationPropertyFactory.bearing(bearing)) }
+ }
+
+ @Test
+ fun setAccuracyRadius() {
+ val radius = 40f
+ locationLayerRenderer.setAccuracyRadius(radius)
+
+ verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(radius)) }
+ }
+
+ @Test
+ fun styleScaling() {
+ val exp = Expression.literal("")
+ locationLayerRenderer.styleScaling(exp)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.shadowImageSize(exp),
+ LocationPropertyFactory.bearingImageSize(exp),
+ LocationPropertyFactory.topImageSize(exp)
+ )
+ }
+ }
+
+ @Test
+ fun setLocationStale() {
+ locationLayerRenderer.setLocationStale(true, RenderMode.NORMAL)
+
+ verify {
+ layer.setProperties(
+ LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
+ LocationPropertyFactory.bearingImage(BACKGROUND_STALE_ICON),
+ LocationPropertyFactory.shadowImage(SHADOW_ICON)
+ )
+ }
+ }
+
+ @Test
+ fun addBitmaps_shadow() {
+ addBitmaps(withShadow = true, renderMode = RenderMode.NORMAL)
+
+ verify { style.addImage(SHADOW_ICON, shadowBitmap) }
+ }
+
+ @Test
+ fun addBitmaps_noShadow() {
+ addBitmaps(withShadow = false, renderMode = RenderMode.NORMAL)
+
+ verify { style.removeImage(SHADOW_ICON) }
+ }
+
+ @Test
+ fun addBitmaps_normal() {
+ addBitmaps(withShadow = true, renderMode = RenderMode.NORMAL)
+
+ verify { style.addImage(FOREGROUND_ICON, foregroundBitmap) }
+ verify { style.addImage(FOREGROUND_STALE_ICON, foregroundStaleBitmap) }
+ verify { style.addImage(BACKGROUND_ICON, backgroundBitmap) }
+ verify { style.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap) }
+ verify { style.addImage(BEARING_ICON, bearingBitmap) }
+ }
+
+ @Test
+ fun addBitmaps_compass() {
+ every { bearingBitmap.width } returns 40
+ every { bearingBitmap.height } returns 40
+ every { bearingBitmap.config } returns mockk()
+ every { backgroundBitmap.width } returns 20
+ every { backgroundBitmap.height } returns 10
+
+ val mergedBitmap = mockk()
+ mockkStatic(BitmapUtils::class)
+ every { BitmapUtils.mergeBitmap(bearingBitmap, backgroundBitmap, 10f, 15f) } returns mergedBitmap
+
+ every { bearingBitmap.width } returns 40
+ every { bearingBitmap.height } returns 40
+ every { bearingBitmap.config } returns mockk()
+ every { backgroundStaleBitmap.width } returns 30
+ every { backgroundStaleBitmap.height } returns 10
+
+ val mergedStaleBitmap = mockk()
+ every { BitmapUtils.mergeBitmap(bearingBitmap, backgroundStaleBitmap, 5f, 15f) } returns mergedStaleBitmap
+
+ addBitmaps(withShadow = true, renderMode = RenderMode.COMPASS)
+
+ verify { style.addImage(BEARING_ICON, mergedBitmap) }
+ verify { style.addImage(BEARING_STALE_ICON, mergedStaleBitmap) }
+
+ unmockkStatic(BitmapUtils::class)
+ }
+
+ @Test
+ fun addBitmaps_gps() {
+ addBitmaps(withShadow = true, renderMode = RenderMode.GPS)
+
+ verify { style.addImage(FOREGROUND_ICON, foregroundBitmap) }
+ verify { style.addImage(FOREGROUND_STALE_ICON, foregroundStaleBitmap) }
+ verify { style.addImage(BACKGROUND_ICON, backgroundBitmap) }
+ verify { style.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap) }
+ verify { style.addImage(BEARING_ICON, bearingBitmap) }
+ }
+
+ private val shadowBitmap = mockk()
+ private val backgroundBitmap = mockk()
+ private val backgroundStaleBitmap = mockk()
+ private val bearingBitmap = mockk()
+ private val foregroundBitmap = mockk()
+ private val foregroundStaleBitmap = mockk()
+
+ private fun addBitmaps(withShadow: Boolean, @RenderMode.Mode renderMode: Int) {
+ locationLayerRenderer.addBitmaps(
+ renderMode,
+ if (withShadow) shadowBitmap else null,
+ backgroundBitmap,
+ backgroundStaleBitmap,
+ bearingBitmap,
+ foregroundBitmap,
+ foregroundStaleBitmap
+ )
+ }
+
+ private fun LatLng.toLocationArray() = arrayOf(latitude, longitude, 0.0)
+}
\ No newline at end of file
diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt
index 4a2839361..33a067f59 100644
--- a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt
+++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt
@@ -13,6 +13,7 @@ import com.mapbox.mapboxsdk.location.LocationComponentConstants.TRANSITION_ANIMA
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.Projection
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.maps.Transform
import org.junit.Assert
@@ -80,7 +81,7 @@ class LocationComponentTest {
fun before() {
MockitoAnnotations.initMocks(this)
developerAnimationListeners = mutableListOf()
- locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, locationEngineProvider)
+ locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, locationEngineProvider, false)
doReturn(locationEngine).`when`(locationEngineProvider).getBestLocationEngine(context, false)
doReturn(style).`when`(mapboxMap).style
}
@@ -587,4 +588,46 @@ class LocationComponentTest {
verify(callback, times(0)).onCancel()
verify(locationAnimatorCoordinator).feedNewZoomLevel(14.0, CameraPosition.DEFAULT, 500L, callback)
}
+
+ @Test
+ fun newLocation_accuracy_symbolLayerRadiusValue() {
+ val location = Location("test")
+ location.accuracy = 50f
+ val projection: Projection = mock(Projection::class.java)
+ `when`(projection.getMetersPerPixelAtLatitude(location.latitude)).thenReturn(10.0)
+ `when`(mapboxMap.projection).thenReturn(projection)
+ `when`(style.isFullyLoaded).thenReturn(true)
+ locationComponent.activateLocationComponent(
+ LocationComponentActivationOptions.builder(context, style)
+ .locationComponentOptions(locationComponentOptions)
+ .useDefaultLocationEngine(false)
+ .build()
+ )
+ locationComponent.isLocationComponentEnabled = true
+ locationComponent.onStart()
+ locationComponent.forceLocationUpdate(location)
+
+ val radius = (location.accuracy * (1 / 10.0)).toFloat()
+ verify(locationAnimatorCoordinator).feedNewAccuracyRadius(radius, false)
+ }
+
+ @Test
+ fun newLocation_accuracy_indicatorLayerRadiusValue() {
+ val location = Location("test")
+ location.accuracy = 50f
+ `when`(style.isFullyLoaded).thenReturn(true)
+ locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, locationEngineProvider, true)
+ locationComponent.activateLocationComponent(
+ LocationComponentActivationOptions.builder(context, style)
+ .locationComponentOptions(locationComponentOptions)
+ .useSpecializedLocationLayer(true)
+ .useDefaultLocationEngine(false)
+ .build()
+ )
+ locationComponent.isLocationComponentEnabled = true
+ locationComponent.onStart()
+ locationComponent.forceLocationUpdate(location)
+
+ verify(locationAnimatorCoordinator).feedNewAccuracyRadius(location.accuracy, false)
+ }
}
\ No newline at end of file
diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
index c41732bc9..40726acbe 100644
--- a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
+++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.location;
import android.graphics.Bitmap;
+
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
@@ -15,6 +16,8 @@ import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.HashSet;
import java.util.Set;
@@ -43,6 +46,8 @@ import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_LATLNG
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -53,6 +58,7 @@ public class LocationLayerControllerTest {
private MapboxMap mapboxMap = mock(MapboxMap.class);
private Style style = mock(Style.class);
+ private LocationLayerRenderer indicatorRenderer = mock(LocationLayerRenderer.class);
@Before
public void before() {
@@ -316,6 +322,20 @@ public class LocationLayerControllerTest {
verify(style).addImage(BEARING_ICON, bitmap);
}
+ @Test
+ public void applyStyle_specializedLayer_ignoreBitmapNames() {
+ OnRenderModeChangedListener internalRenderModeChangedListener = mock(OnRenderModeChangedListener.class);
+ LayerSourceProvider sourceProvider = buildLayerProvider();
+ LocationComponentOptions options = mock(LocationComponentOptions.class);
+ when(options.foregroundName()).thenReturn("new_name");
+ LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class);
+
+ new LocationLayerController(mapboxMap, mapboxMap.getStyle(), sourceProvider, buildFeatureProvider(options),
+ bitmapProvider, options, internalRenderModeChangedListener, true);
+
+ verify(indicatorRenderer).updateIconIds(eq(FOREGROUND_ICON), anyString(), anyString(), anyString(), anyString());
+ }
+
@Test
public void applyStyle_layerBelowChanged() {
OnRenderModeChangedListener internalRenderModeChangedListener = mock(OnRenderModeChangedListener.class);
@@ -599,7 +619,7 @@ public class LocationLayerControllerTest {
LocationLayerController controller =
new LocationLayerController(mapboxMap, mapboxMap.getStyle(), sourceProvider, buildFeatureProvider(options),
- bitmapProvider, options, internalRenderModeChangedListener, false);
+ bitmapProvider, options, internalRenderModeChangedListener, false);
controller.setRenderMode(RenderMode.NORMAL);
controller.setRenderMode(RenderMode.NORMAL);
@@ -618,7 +638,7 @@ public class LocationLayerControllerTest {
LocationLayerController controller =
new LocationLayerController(mapboxMap, mapboxMap.getStyle(), sourceProvider, buildFeatureProvider(options),
- bitmapProvider, options, internalRenderModeChangedListener, false);
+ bitmapProvider, options, internalRenderModeChangedListener, false);
controller.setRenderMode(RenderMode.GPS);
controller.setRenderMode(RenderMode.GPS);
@@ -642,7 +662,7 @@ public class LocationLayerControllerTest {
LocationLayerController controller =
new LocationLayerController(mapboxMap, mapboxMap.getStyle(), sourceProvider, buildFeatureProvider(options),
- bitmapProvider, options, internalRenderModeChangedListener, false);
+ bitmapProvider, options, internalRenderModeChangedListener, false);
verify(style).addImage(FOREGROUND_ICON, bitmap);
@@ -674,7 +694,18 @@ public class LocationLayerControllerTest {
}
private LayerSourceProvider buildLayerProvider() {
- LayerSourceProvider layerSourceProvider = mock(LayerSourceProvider.class);
+ final LayerSourceProvider layerSourceProvider = mock(LayerSourceProvider.class);
+ when(layerSourceProvider.getIndicatorLocationLayerRenderer()).thenReturn(indicatorRenderer);
+ when(layerSourceProvider.getSymbolLocationLayerRenderer(any(LayerFeatureProvider.class), anyBoolean())).thenAnswer(
+ new Answer() {
+ @Override
+ public LocationLayerRenderer answer(InvocationOnMock invocation) {
+ LayerFeatureProvider featureProvider = invocation.getArgument(0);
+ boolean isStale = invocation.getArgument(1);
+ return new SymbolLocationLayerRenderer(layerSourceProvider, featureProvider, isStale);
+ }
+ }
+ );
Layer shadowLayer = mock(Layer.class);
when(shadowLayer.getId()).thenReturn(SHADOW_LAYER);
diff --git a/gradle/gradle-checkstyle.gradle b/gradle/gradle-checkstyle.gradle
index 8eb4baa85..3e36e7746 100644
--- a/gradle/gradle-checkstyle.gradle
+++ b/gradle/gradle-checkstyle.gradle
@@ -21,6 +21,9 @@ task checkstyle(type: Checkstyle) {
exclude '**/log/LoggerDefinition.java'
exclude '**/log/Logger.java'
exclude '**/Expression.java'
+ exclude '**/location/LocationPropertyFactory.java'
+ exclude '**/location/LocationIndicatorLayer.java'
+ exclude '**/location/LocationIndicatorLayerTest.java'
classpath = files()
ignoreFailures = false
}