diff --git a/app/build.gradle b/app/build.gradle
index 90fee0c93..0500c99d0 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,8 @@ android {
buildTypes {
debug {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
testCoverageEnabled true
}
release {
diff --git a/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java b/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java
index 76afe38d8..9e3a79431 100644
--- a/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java
+++ b/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java
@@ -13,6 +13,7 @@
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.mapboxsdk.plugins.testapp.activity.location.LocationLayerModesActivity;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
@@ -38,7 +39,6 @@
import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_LAYER;
import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_STALE_ICON;
import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.LOCATION_SOURCE;
-import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.NAVIGATION_LAYER;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
@@ -91,7 +91,7 @@ public void locationSourceAdded() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
assertTrue(mapboxMap.getSource(LOCATION_SOURCE) != null);
}
});
@@ -103,7 +103,7 @@ public void locationTrackingLayersAdded() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
assertTrue(mapboxMap.getLayer(ACCURACY_LAYER) != null);
assertTrue(mapboxMap.getLayer(BACKGROUND_LAYER) != null);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER) != null);
@@ -117,7 +117,7 @@ public void locationBearingLayersAdded() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.COMPASS);
+ locationLayerPlugin.setRenderMode(RenderMode.COMPASS);
assertTrue(mapboxMap.getLayer(ACCURACY_LAYER) != null);
assertTrue(mapboxMap.getLayer(BACKGROUND_LAYER) != null);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER) != null);
@@ -132,8 +132,8 @@ public void locationNavigationLayersAdded() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.COMPASS);
- assertTrue(mapboxMap.getLayer(NAVIGATION_LAYER) != null);
+ locationLayerPlugin.setRenderMode(RenderMode.COMPASS);
+ assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER) != null);
}
});
}
@@ -144,9 +144,9 @@ public void locationLayerModeCorrectlySetToNone() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER) != null);
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.NONE);
+ locationLayerPlugin.setLocationLayerEnabled(false);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER).getVisibility().getValue()
.equals(Property.NONE));
}
@@ -159,11 +159,11 @@ public void onMapChangeLocationLayerRedrawn() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER) != null);
mapboxMap.setStyleUrl(Style.SATELLITE);
uiController.loopMainThreadForAtLeast(500);
- assertEquals(locationLayerPlugin.getLocationLayerMode(), LocationLayerMode.TRACKING);
+ assertEquals(locationLayerPlugin.getRenderMode(), RenderMode.NORMAL);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER) != null);
assertTrue(mapboxMap.getLayer(FOREGROUND_LAYER).getVisibility().getValue()
.equals(Property.VISIBLE));
@@ -181,11 +181,11 @@ public void whenStaleTimeSet_iconsDoChangeAtAppropriateTime() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
SymbolLayer symbolLayer = mapboxMap.getLayerAs(FOREGROUND_LAYER);
assert symbolLayer != null;
assertThat(symbolLayer.getIconImage().getValue(), equalTo(FOREGROUND_ICON));
- locationLayerPlugin.applyStyle(LocationLayerOptions.builder(context).staleStateDelay(400).build());
+ locationLayerPlugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(400).build());
locationLayerPlugin.forceLocationUpdate(location);
uiController.loopMainThreadForAtLeast(500);
assertThat(symbolLayer.getIconImage().getValue(), equalTo(FOREGROUND_STALE_ICON));
@@ -199,8 +199,8 @@ public void whenDrawableChanged_continuesUsingStaleIcons() throws Exception {
@Override
public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, MapboxMap mapboxMap,
UiController uiController, Context context) {
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
- locationLayerPlugin.applyStyle(LocationLayerOptions.builder(context).staleStateDelay(100).build());
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
+ locationLayerPlugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(100).build());
locationLayerPlugin.forceLocationUpdate(location);
uiController.loopMainThreadForAtLeast(200);
rule.getActivity().toggleStyle();
@@ -215,9 +215,10 @@ public void onLocationLayerAction(LocationLayerPlugin locationLayerPlugin, Mapbo
public void whenMapCameraInitializesTilted_iconsGetPlacedWithCorrectOffset() throws Exception {
executeLocationLayerTest((locationLayerPlugin, mapboxMap, uiController, context) -> {
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(60).build()));
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
+ locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
locationLayerPlugin.forceLocationUpdate(location);
SymbolLayer layer = mapboxMap.getLayerAs(FOREGROUND_LAYER);
+ uiController.loopMainThreadForAtLeast(200);
Float[] value = layer.getIconOffset().getValue();
Assert.assertEquals((-0.05 * 60), value[1], 0.1);
});
diff --git a/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java b/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java
index 11fd20898..cad3e330c 100644
--- a/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java
+++ b/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java
@@ -9,8 +9,6 @@
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.plugins.testapp.activity.TrafficActivity;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
@@ -822,11 +820,7 @@ public void lineWidthFunctionLocalBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Local.BASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(2, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -838,11 +832,7 @@ public void lineWidthFunctionLocalCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Local.CASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(2, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -855,11 +845,7 @@ public void lineWidthFunctionSecondaryBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Secondary.BASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(3, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -871,11 +857,7 @@ public void lineWidthFunctionSecondaryCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Secondary.CASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(3, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -887,11 +869,7 @@ public void lineWidthFunctionPrimaryBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Primary.BASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(3, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -903,11 +881,7 @@ public void lineWidthFunctionPrimaryCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Primary.CASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(3, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -919,11 +893,7 @@ public void lineWidthFunctionTrunkBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Trunk.BASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(3, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -935,11 +905,7 @@ public void lineWidthFunctionTrunkCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Trunk.CASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -951,11 +917,7 @@ public void lineWidthFunctionMotorwayBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(MotorWay.BASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -967,11 +929,7 @@ public void lineWidthFunctionMotorwayCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(MotorWay.CASE_LAYER_ID);
assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+ assertNotNull(layer.getLineWidth().getExpression());
}
});
}
@@ -983,11 +941,7 @@ public void lineOffsetFunctionLocalBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Local.BASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(2, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -999,11 +953,7 @@ public void lineOffsetFunctionLocalCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Local.CASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(2, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1016,11 +966,7 @@ public void lineOffsetFunctionSecondaryBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Secondary.BASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1032,11 +978,7 @@ public void lineOffsetFunctionSecondaryCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Secondary.CASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1048,11 +990,7 @@ public void lineOffsetFunctionPrimaryBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Primary.BASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1064,11 +1002,7 @@ public void lineOffsetFunctionPrimaryCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Primary.CASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1080,11 +1014,7 @@ public void lineOffsetFunctionTrunkBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Trunk.BASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1096,11 +1026,7 @@ public void lineOffsetFunctionTrunkCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(Trunk.CASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(4, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1112,11 +1038,7 @@ public void lineOffsetFunctionMotorwayBaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(MotorWay.BASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(5, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
@@ -1128,11 +1050,7 @@ public void lineOffsetFunctionMotorwayCaseLayer() throws Exception {
public void onTrafficAction(TrafficPlugin trafficPlugin, MapboxMap mapboxMap, UiController controller) {
LineLayer layer = mapboxMap.getLayerAs(MotorWay.CASE_LAYER_ID);
assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(5, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+ assertNotNull(layer.getLineOffset().getExpression());
}
});
}
diff --git a/app/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java b/app/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java
index 31c699b4b..ff3ab5e4a 100644
--- a/app/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java
+++ b/app/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java
@@ -3,20 +3,25 @@
import android.app.Activity;
import android.support.test.espresso.IdlingResource;
-import timber.log.Timber;
-
+import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import java.lang.reflect.Field;
-public class OnMapReadyIdlingResource implements IdlingResource {
+public class OnMapReadyIdlingResource implements IdlingResource, OnMapReadyCallback {
- private final Activity activity;
private MapboxMap mapboxMap;
private IdlingResource.ResourceCallback resourceCallback;
public OnMapReadyIdlingResource(Activity activity) {
- this.activity = activity;
+ try {
+ Field field = activity.getClass().getDeclaredField("mapView");
+ field.setAccessible(true);
+ ((MapView) field.get(activity)).getMapAsync(this);
+ } catch (Exception err) {
+ throw new RuntimeException(err);
+ }
}
@Override
@@ -26,11 +31,7 @@ public String getName() {
@Override
public boolean isIdleNow() {
- boolean idle = isMapboxMapReady();
- if (idle && resourceCallback != null) {
- resourceCallback.onTransitionToIdle();
- }
- return idle;
+ return mapboxMap != null;
}
@Override
@@ -38,20 +39,15 @@ public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
- private boolean isMapboxMapReady() {
- try {
- Field field = activity.getClass().getDeclaredField("mapboxMap");
- field.setAccessible(true);
- mapboxMap = (MapboxMap) field.get(activity);
- Timber.e("isMapboxReady called with value " + (mapboxMap != null));
- return mapboxMap != null;
- } catch (Exception exception) {
- Timber.e("could not reflect", exception);
- return false;
- }
- }
-
public MapboxMap getMapboxMap() {
return mapboxMap;
}
+
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ if (resourceCallback != null) {
+ resourceCallback.onTransitionToIdle();
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/BuildingActivity.java b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/BuildingActivity.java
index 76a5f01a2..c081b2084 100644
--- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/BuildingActivity.java
+++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/BuildingActivity.java
@@ -117,7 +117,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
-
switch (item.getItemId()) {
case R.id.menu_building_min_zoom:
buildingPlugin.setMinZoomLevel(14);
diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/FeatureOverviewActivity.java b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/FeatureOverviewActivity.java
index 1be6e6ec5..1c8932779 100644
--- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/FeatureOverviewActivity.java
+++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/FeatureOverviewActivity.java
@@ -26,9 +26,9 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.mapbox.android.core.permissions.PermissionsListener;
+import com.mapbox.android.core.permissions.PermissionsManager;
import com.mapbox.mapboxsdk.plugins.testapp.R;
-import com.mapbox.services.android.telemetry.permissions.PermissionsListener;
-import com.mapbox.services.android.telemetry.permissions.PermissionsManager;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/CompassListenerActivity.java b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/CompassListenerActivity.java
index 16dbc5992..2a66e011c 100644
--- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/CompassListenerActivity.java
+++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/CompassListenerActivity.java
@@ -3,17 +3,17 @@
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
+import com.mapbox.android.core.location.LocationEngine;
+import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.plugins.locationlayer.CompassListener;
-import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerMode;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
+import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.mapboxsdk.plugins.testapp.R;
-import com.mapbox.services.android.telemetry.location.LocationEngine;
-import com.mapbox.services.android.telemetry.location.LostLocationEngine;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -39,9 +39,9 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onMapReady(final MapboxMap mapboxMap) {
- LocationEngine locationEngine = new LostLocationEngine(this);
+ LocationEngine locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable();
locationLayerPlugin = new LocationLayerPlugin(mapView, mapboxMap, locationEngine);
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.COMPASS);
+ locationLayerPlugin.setRenderMode(RenderMode.COMPASS);
locationLayerPlugin.addCompassListener(new CompassListener() {
@Override
public void onCompassChanged(float userHeading) {
@@ -96,7 +96,7 @@ public void onLowMemory() {
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
- locationLayerPlugin.removeCompassListener(null);
+ //locationLayerPlugin.removeCompassListener();
}
@Override
diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerMapChangeActivity.java b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerMapChangeActivity.java
index d6e5e8a25..37f31f058 100644
--- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerMapChangeActivity.java
+++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerMapChangeActivity.java
@@ -6,16 +6,16 @@
import android.view.Menu;
import android.view.MenuItem;
+import com.mapbox.android.core.location.LocationEngine;
+import com.mapbox.android.core.location.LocationEnginePriority;
+import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerMode;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
+import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.mapboxsdk.plugins.testapp.R;
import com.mapbox.mapboxsdk.plugins.testapp.Utils;
-import com.mapbox.services.android.telemetry.location.LocationEngine;
-import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
-import com.mapbox.services.android.telemetry.location.LostLocationEngine;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -48,11 +48,12 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onMapReady(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
- locationEngine = LostLocationEngine.getLocationEngine(this);
+ locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable();
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationEngine.activate();
locationPlugin = new LocationLayerPlugin(mapView, mapboxMap, locationEngine);
- locationPlugin.setLocationLayerEnabled(LocationLayerMode.COMPASS);
+ locationPlugin.setRenderMode(RenderMode.COMPASS);
+ getLifecycle().addObserver(locationPlugin);
}
@OnClick(R.id.fabStyles)
@@ -65,9 +66,6 @@ public void onStyleFabClick() {
@Override
protected void onStart() {
super.onStart();
- if (locationPlugin != null) {
- locationPlugin.onStart();
- }
mapView.onStart();
}
@@ -86,9 +84,6 @@ protected void onPause() {
@Override
protected void onStop() {
super.onStop();
- if (locationPlugin != null) {
- locationPlugin.onStop();
- }
if (locationEngine != null) {
locationEngine.removeLocationUpdates();
}
diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerModesActivity.java b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerModesActivity.java
index c66993be9..1dec7753e 100644
--- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerModesActivity.java
+++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/location/LocationLayerModesActivity.java
@@ -1,43 +1,72 @@
package com.mapbox.mapboxsdk.plugins.testapp.activity.location;
+import android.annotation.SuppressLint;
+import android.content.res.Configuration;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.ListPopupWindow;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.TextView;
import android.widget.Toast;
+import com.mapbox.android.core.location.LocationEngine;
+import com.mapbox.android.core.location.LocationEngineListener;
+import com.mapbox.android.core.location.LocationEnginePriority;
+import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerMode;
+import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerOptions;
import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin;
+import com.mapbox.mapboxsdk.plugins.locationlayer.OnCameraTrackingChangedListener;
import com.mapbox.mapboxsdk.plugins.locationlayer.OnLocationLayerClickListener;
+import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode;
+import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode;
import com.mapbox.mapboxsdk.plugins.testapp.R;
-import com.mapbox.services.android.telemetry.location.LocationEngine;
-import com.mapbox.services.android.telemetry.location.LocationEngineListener;
-import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
-import com.mapbox.services.android.telemetry.location.LostLocationEngine;
+
+import java.util.ArrayList;
+import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class LocationLayerModesActivity extends AppCompatActivity implements OnMapReadyCallback,
- LocationEngineListener, OnLocationLayerClickListener {
+ LocationEngineListener, OnLocationLayerClickListener, OnCameraTrackingChangedListener {
@BindView(R.id.map_view)
MapView mapView;
+ @BindView(R.id.tv_mode)
+ TextView modeText;
+ @BindView(R.id.tv_tracking)
+ TextView trackingText;
+ @BindView(R.id.button_location_mode)
+ Button locationModeBtn;
+ @BindView(R.id.button_location_tracking)
+ Button locationTrackingBtn;
private LocationLayerPlugin locationLayerPlugin;
private LocationEngine locationEngine;
private MapboxMap mapboxMap;
private boolean customStyle;
+ private static final String SAVED_STATE_CAMERA = "saved_state_camera";
+ private static final String SAVED_STATE_RENDER = "saved_state_render";
+
+ @CameraMode.Mode
+ private int cameraMode = CameraMode.NONE;
+
+ @RenderMode.Mode
+ private int renderMode = RenderMode.NORMAL;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -46,53 +75,56 @@ protected void onCreate(Bundle savedInstanceState) {
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
- }
- @SuppressWarnings( {"MissingPermission"})
- @OnClick(R.id.button_location_mode_none)
- public void locationModeNone(View view) {
- if (locationLayerPlugin == null) {
- return;
+ if (savedInstanceState != null) {
+ cameraMode = savedInstanceState.getInt(SAVED_STATE_CAMERA);
+ renderMode = savedInstanceState.getInt(SAVED_STATE_RENDER);
}
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.NONE);
}
@SuppressWarnings( {"MissingPermission"})
- @OnClick(R.id.button_location_mode_compass)
- public void locationModeCompass(View view) {
+ @OnClick(R.id.button_location_mode)
+ public void locationMode(View view) {
if (locationLayerPlugin == null) {
return;
}
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.COMPASS);
+ showModeListDialog();
}
- @SuppressWarnings( {"MissingPermission"})
- @OnClick(R.id.button_location_mode_tracking)
- public void locationModeTracking(View view) {
- if (locationLayerPlugin == null) {
- return;
- }
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.TRACKING);
- }
-
- @SuppressWarnings( {"MissingPermission"})
- @OnClick(R.id.button_location_mode_navigation)
- public void locationModeNavigation(View view) {
+ @OnClick(R.id.button_location_tracking)
+ public void locationModeCompass(View view) {
if (locationLayerPlugin == null) {
return;
}
- locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.NAVIGATION);
+ showTrackingListDialog();
}
+ @SuppressLint("MissingPermission")
@Override
public void onMapReady(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
- locationEngine = new LostLocationEngine(this);
+
+ locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable();
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
+ locationEngine.setFastestInterval(1000);
locationEngine.addLocationEngineListener(this);
locationEngine.activate();
- locationLayerPlugin = new LocationLayerPlugin(mapView, mapboxMap, locationEngine);
- locationLayerPlugin.setOnLocationClickListener(this);
+
+ int[] padding;
+ if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ padding = new int[] {0, 750, 0, 0};
+ } else {
+ padding = new int[] {0, 250, 0, 0};
+ }
+ LocationLayerOptions options = LocationLayerOptions.builder(this)
+ .padding(padding)
+ .build();
+ locationLayerPlugin = new LocationLayerPlugin(mapView, mapboxMap, locationEngine, options);
+ locationLayerPlugin.addOnLocationClickListener(this);
+ locationLayerPlugin.addOnCameraTrackingChangedListener(this);
+ locationLayerPlugin.setCameraMode(cameraMode);
+ setRendererMode(renderMode);
+
getLifecycle().addObserver(locationLayerPlugin);
}
@@ -102,6 +134,7 @@ public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
+ @SuppressLint("MissingPermission")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (locationLayerPlugin == null) {
@@ -111,6 +144,12 @@ public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_style_change) {
toggleStyle();
return true;
+ } else if (item.getItemId() == R.id.action_plugin_disable) {
+ locationLayerPlugin.setLocationLayerEnabled(false);
+ return true;
+ } else if (item.getItemId() == R.id.action_plugin_enabled) {
+ locationLayerPlugin.setLocationLayerEnabled(true);
+ return true;
}
return super.onOptionsItemSelected(item);
@@ -165,6 +204,8 @@ protected void onStop() {
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
+ outState.putInt(SAVED_STATE_CAMERA, cameraMode);
+ outState.putInt(SAVED_STATE_RENDER, renderMode);
}
@Override
@@ -192,10 +233,101 @@ public void onConnected() {
public void onLocationChanged(Location location) {
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(location.getLatitude(), location.getLongitude()), 16));
+ locationEngine.removeLocationEngineListener(this);
}
@Override
public void onLocationLayerClick() {
Toast.makeText(this, "OnLocationLayerClick", Toast.LENGTH_LONG).show();
}
+
+ private void showModeListDialog() {
+ List
+ * When the value of this property is equal to {0,0,0,0}, viewport + * properties such as `centerCoordinate` assume a viewport that matches the map + * view’s frame. Otherwise, those properties are inset, excluding part of the + * frame from the viewport. For instance, if the only the top edge is inset, the + * map center is effectively shifted downward. + *
+ * + * @return integer array of padding values + * @since 0.5.0 + */ + @SuppressWarnings("mutable") + public abstract int[] padding(); + + /** + * The maximum zoom level the map can be displayed at. + * + * @return the maximum zoom level + * @since 0.5.0 + */ + public abstract double maxZoom(); + + /** + * The minimum zoom level the map can be displayed at. + * + * @return the minimum zoom level + * @since 0.5.0 + */ + public abstract double minZoom(); + + /** + * Minimum single pointer movement in pixels required to break camera tracking. + * + * @return the minimum movement + * @since 0.5.0 + */ + public abstract float trackingInitialMoveThreshold(); + + /** + * Minimum multi pointer movement in pixels required to break camera tracking (for example during scale gesture). + * + * @return the minimum movement + * @since 0.5.0 + */ + public abstract float trackingMultiFingerMoveThreshold(); /** * Builder class for constructing a new instance of {@link LocationLayerOptions}. @@ -392,12 +469,12 @@ public abstract static class Builder { /** * Defines the drawable used for the navigation state icon. * - * @param navigationDrawable the drawable resource ID + * @param gpsDrawable the drawable resource ID * @return this builder for chaining options together * @attr ref R.styleable#LocationLayer_navigationDrawable * @since 0.4.0 */ - public abstract Builder navigationDrawable(@DrawableRes int navigationDrawable); + public abstract Builder gpsDrawable(@DrawableRes int gpsDrawable); /** * Supply a Drawable that is to be rendered on top of all of the content in the Location Layer @@ -482,18 +559,68 @@ public abstract static class Builder { public abstract Builder enableStaleState(boolean enabled); /** - * Set the delay before the location icon becomes stale. The timer begins approximately when a + * Set the timeout before the location icon becomes stale. The timer begins approximately when a * new location update comes in and using this defined time, if an update hasn't occurred by the * end, the location is considered stale. * - * @param delay the duration in milliseconds which it should take before the location layer is - * considered stale + * @param timeout the duration in milliseconds which it should take before the location layer is + * considered stale * @return this builder for chaining options together - * @attr ref R.styleable#LocationLayer_staleStateDelay + * @attr ref R.styleable#LocationLayer_staleStateTimeout * @since 0.4.0 */ - public abstract Builder staleStateDelay(long delay); + public abstract Builder staleStateTimeout(long timeout); + /** + * Sets the distance from the edges of the map view’s frame to the edges of the map + * view’s logical viewport. + * + *+ * When the value of this property is equal to {0,0,0,0}, viewport + * properties such as `centerCoordinate` assume a viewport that matches the map + * view’s frame. Otherwise, those properties are inset, excluding part of the + * frame from the viewport. For instance, if the only the top edge is inset, the + * map center is effectively shifted downward. + *
+ * + * @param padding The margins for the map in pixels (left, top, right, bottom). + * @since 0.5.0 + */ + public abstract Builder padding(int[] padding); + + /** + * Sets the maximum zoom level the map can be displayed at. + *+ * The default maximum zoomn level is 22. The upper bound for this value is 25.5. + * + * @param maxZoom The new maximum zoom level. + * @since 0.5.0 + */ + public abstract Builder maxZoom(double maxZoom); + + /** + * Sets the minimum zoom level the map can be displayed at. + * + * @param minZoom The new minimum zoom level. + */ + public abstract Builder minZoom(double minZoom); + + /** + * Sets minimum single pointer movement (map pan) in pixels required to break camera tracking. + * + * @param moveThreshold the minimum movement + * @since 0.5.0 + */ + public abstract Builder trackingInitialMoveThreshold(float moveThreshold); + + /** + * Sets minimum multi pointer movement (map pan) in pixels required to break camera tracking + * (for example during scale gesture). + * + * @param moveThreshold the minimum movement + * @since 0.5.0 + */ + public abstract Builder trackingMultiFingerMoveThreshold(float moveThreshold); abstract LocationLayerOptions autoBuild(); diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java index aaf2f1a5e..29681b4d0 100644 --- a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java +++ b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java @@ -1,19 +1,18 @@ package com.mapbox.mapboxsdk.plugins.locationlayer; -import android.animation.ValueAnimator; +import android.annotation.SuppressLint; import android.arch.lifecycle.Lifecycle; import android.arch.lifecycle.LifecycleObserver; import android.arch.lifecycle.OnLifecycleEvent; import android.location.Location; -import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresPermission; import android.support.annotation.StyleRes; import android.support.v7.app.AppCompatDelegate; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.LinearInterpolator; +import com.mapbox.android.core.location.LocationEngine; +import com.mapbox.android.core.location.LocationEngineListener; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; @@ -21,74 +20,67 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener; import com.mapbox.mapboxsdk.maps.MapboxMap.OnMapClickListener; -import com.mapbox.services.android.telemetry.location.LocationEngine; -import com.mapbox.services.android.telemetry.location.LocationEngineListener; -import com.mapbox.services.commons.geojson.Point; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode; -import timber.log.Timber; +import java.util.concurrent.CopyOnWriteArrayList; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; -import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.ACCURACY_LAYER; -import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BEARING_LAYER; -import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.COMPASS_UPDATE_RATE_MS; -import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.MAX_ANIMATION_DURATION_MS; -import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.NAVIGATION_LAYER; -import static com.mapbox.mapboxsdk.plugins.locationlayer.Utils.shortestRotation; /** * The Location layer plugin provides location awareness to your mobile application. Enabling this * plugin provides a contextual experience to your users by showing an icon representing the users * current location. A few different modes are offered to provide the right context to your users at - * the correct time. {@link LocationLayerMode#TRACKING} simply shows the users location on the map - * represented as a dot. {@link LocationLayerMode#COMPASS} mode allows you to display an arrow icon + * the correct time. {@link RenderMode#NORMAL} simply shows the users location on the map + * represented as a dot. {@link RenderMode#COMPASS} mode allows you to display an arrow icon * (by default) that points in the direction the device is pointing in. - * {@link LocationLayerMode#NAVIGATION} can be used in conjunction with our Navigation SDK to - * display a larger icon we call the user puck. Lastly, {@link LocationLayerMode#NONE} can be used + * {@link RenderMode#GPS} can be used in conjunction with our Navigation SDK to + * display a larger icon (customized with {@link LocationLayerOptions#gpsDrawable()}) we call the user puck. + *
+ * This plugin also offers the ability to set a map camera behavior for tracking the user + * location. These different {@link CameraMode}s will track, stop tracking the location based on the + * mode set with {@link LocationLayerPlugin#setCameraMode(int)}. + *
+ * Lastly, {@link LocationLayerPlugin#setLocationLayerEnabled(boolean)} can be used * to disable the Location Layer but keep the instance around till the activity is destroyed. *
* Using this plugin requires you to request permission beforehand manually or using
- * {@link com.mapbox.services.android.telemetry.permissions.PermissionsManager}. Either
+ * {@link com.mapbox.android.core.permissions.PermissionsManager}. Either
* {@code ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permissions can be requested and
* this plugin work as expected.
*
* @since 0.1.0
*/
-public final class LocationLayerPlugin implements LocationEngineListener, CompassListener,
- OnMapChangedListener, LifecycleObserver, OnCameraMoveListener, OnMapClickListener,
- OnLocationStaleListener {
+public final class LocationLayerPlugin implements LifecycleObserver {
- private LocationLayer locationLayer;
- private CompassManager compassManager;
- private LocationEngine locationEngine;
private final MapboxMap mapboxMap;
private final MapView mapView;
+ private LocationLayerOptions options;
+ private LocationEngine locationEngine;
+ private CompassManager compassManager;
- // Enabled booleans
- @LocationLayerMode.Mode
- private int locationLayerMode;
-
- // Previous compass and location values
- private float previousMagneticHeading;
- private Point previousPoint;
- private Location location;
-
- // Animators
- private ValueAnimator locationChangeAnimator;
- private ValueAnimator bearingChangeAnimator;
+ private LocationLayer locationLayer;
+ private LocationLayerCamera locationLayerCamera;
- private long locationUpdateTimestamp;
- private boolean linearAnimation;
+ private LocationLayerAnimator locationLayerAnimator;
- private OnLocationLayerClickListener onLocationLayerClickListener;
- private StaleStateRunnable staleStateRunnable;
- private LocationLayerOptions options;
+ private boolean isEnabled;
+ private StaleStateManager staleStateManager;
+ private final CopyOnWriteArrayList
*
+ *
- *
*
- * @param locationLayerMode one of the modes found in {@link LocationLayerMode}
- * @since 0.1.0
+ * @param cameraMode one of the modes found in {@link CameraMode}
+ * @since 0.5.0
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
- public void setLocationLayerEnabled(@LocationLayerMode.Mode int locationLayerMode) {
- this.locationLayerMode = locationLayerMode;
- if (locationLayerMode != LocationLayerMode.NONE) {
- locationLayer.setLayersVisibility(true);
-
- // Set an initial location if one is available and the locationEngines not null
- if (locationEngine != null) {
- setLastLocation();
- locationEngine.addLocationEngineListener(this);
- }
-
- // On Camera move is called here so that the layer icon offsets adjusted properly when the
- // maps initially tilted.
- onCameraMove();
-
- toggleCameraListener();
-
- if (locationLayerMode == LocationLayerMode.COMPASS) {
- setLinearAnimation(false);
- setNavigationEnabled(false);
- setMyBearingEnabled(true);
- } else if (locationLayerMode == LocationLayerMode.NAVIGATION) {
- setMyBearingEnabled(false);
- setNavigationEnabled(true);
- } else if (locationLayerMode == LocationLayerMode.TRACKING) {
- setLinearAnimation(false);
- setMyBearingEnabled(false);
- setNavigationEnabled(false);
- }
- } else {
- disableLocationLayerPlugin();
- }
+ public void setCameraMode(@CameraMode.Mode int cameraMode) {
+ boolean isGpsNorth = cameraMode == CameraMode.TRACKING_GPS_NORTH;
+ locationLayerAnimator.resetAllCameraAnimations(mapboxMap.getCameraPosition(), isGpsNorth);
+ locationLayerCamera.setCameraMode(cameraMode);
}
/**
- * Returns the current location mode being used with this plugin.
+ * Provides the current camera mode being used to track
+ * the location or compass updates.
*
- * @return on of the {@link LocationLayerMode} values
- * @since 0.1.0
+ * @return the current camera mode
+ * @since 0.5.0
*/
- public int getLocationLayerMode() {
- return locationLayerMode;
+ @CameraMode.Mode
+ public int getCameraMode() {
+ return locationLayerCamera.getCameraMode();
}
- public LocationLayerOptions getLocationLayerOptions() {
- return options;
+ /**
+ * Sets the render mode, which determines how the location updates will be rendered on the map.
+ *
+ *
+ *
+ * @param renderMode one of the modes found in {@link RenderMode}
+ * @since 0.5.0
+ */
+ public void setRenderMode(@RenderMode.Mode int renderMode) {
+ locationLayer.setRenderMode(renderMode);
}
- @Override
- public void onMapChanged(int change) {
- if (change == MapView.WILL_START_LOADING_MAP) {
- stopAllAnimations();
- } else if (change == MapView.DID_FINISH_LOADING_STYLE) {
- mapStyleFinishedLoading();
- }
+ /**
+ * Provides the current render mode being used to show
+ * the location and/or compass updates on the map.
+ *
+ * @return the current render mode
+ * @since 0.5.0
+ */
+ @RenderMode.Mode
+ public int getRenderMode() {
+ return locationLayer.getRenderMode();
}
- @Override
- public void isLocationStale(boolean stale) {
- Timber.v("isLocationStale: %b", stale);
- locationLayer.locationsStale(stale);
+ /**
+ * Returns the current location options being used.
+ *
+ * @return the current {@link LocationLayerOptions}
+ * @since 0.4.0
+ */
+ public LocationLayerOptions getLocationLayerOptions() {
+ return options;
}
/**
- * Apply a new Location Layer style after the {@link LocationLayerPlugin} has been constructed.
+ * Apply a new LocationLayer style with a style resource.
*
* @param styleRes a XML style overriding some or all the options
- * @since 0.1.0
+ * @since 0.4.0
*/
public void applyStyle(@StyleRes int styleRes) {
applyStyle(LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes));
}
+ /**
+ * Apply a new LocationLayer style with location layer options.
+ *
+ * @param options to update the current style
+ * @since 0.4.0
+ */
public void applyStyle(LocationLayerOptions options) {
+ this.options = options;
locationLayer.applyStyle(options);
if (!options.enableStaleState()) {
- staleStateRunnable.reset();
+ staleStateManager.onStop();
}
- staleStateRunnable.setDelayTime(options.staleStateDelay());
+ staleStateManager.setDelayTime(options.staleStateTimeout());
+ updateMapWithOptions(options);
}
/**
- * Use to either force a location update or to manually control when the user location gets
- * updated.
+ * Sets the distance from the edges of the map view’s frame to the edges of the map
+ * view’s logical viewport.
+ *
+ * When the value of this property is equal to {0,0,0,0}, viewport + * properties such as `centerCoordinate` assume a viewport that matches the map + * view’s frame. Otherwise, those properties are inset, excluding part of the + * frame from the viewport. For instance, if the only the top edge is inset, the + * map center is effectively shifted downward. + *
* - * @param location where you'd like the location icon to be placed on the map - * @since 0.1.0 + * @param left The left margin in pixels. + * @param top The top margin in pixels. + * @param right The right margin in pixels. + * @param bottom The bottom margin in pixels. + * @since 0.5.0 */ - public void forceLocationUpdate(@Nullable Location location) { - updateLocation(location); + public void setPadding(int left, int top, int right, int bottom) { + mapboxMap.setPadding(left, top, right, bottom); } /** - * The {@link LocationEngine} the plugin will use to update it's position. If {@code null} is - * passed in, all updates will occur through the - * {@link LocationLayerPlugin#forceLocationUpdate(Location)} method. + * Sets the maximum zoom level the map can be displayed at. + *+ * The default maximum zoom level is 22. The upper bound for this value is 25.5. * - * @param locationEngine a {@link LocationEngine} this plugin should use to handle updates - * @since 0.1.0 + * @param maxZoom The new maximum zoom level. + * @since 0.5.0 */ - @SuppressWarnings( {"MissingPermission"}) - public void setLocationEngine(@Nullable LocationEngine locationEngine) { - if (locationEngine != null) { - this.locationEngine = locationEngine; - setLocationLayerEnabled(locationLayerMode); - } else if (this.locationEngine != null) { - this.locationEngine.removeLocationEngineListener(this); - this.locationEngine = null; - } + public void setMaxZoom(double maxZoom) { + mapboxMap.setMaxZoomPreference(maxZoom); } /** - * Returns the current {@link LocationEngine} being used for updating the user location layer. + * Sets the minimum zoom level the map can be displayed at. * - * @return the {@link LocationEngine} being used to update the user location layer - * @since 0.1.0 + * @param minZoom The new minimum zoom level. */ - @Nullable - public LocationEngine getLocationEngine() { - return locationEngine; + public void setMinZoom(double minZoom) { + mapboxMap.setMinZoomPreference(minZoom); } /** - * Required to place inside your activities {@code onStop} method. + * Use to either force a location update or to manually control when the user location gets + * updated. * + * @param location where the location icon is placed on the map * @since 0.1.0 */ - @OnLifecycleEvent(Lifecycle.Event.ON_STOP) - public void onStop() { - staleStateRunnable.onStop(); - stopAllAnimations(); - if (compassManager != null && compassManager.isSensorAvailable()) { - compassManager.onStop(); - } - if (locationEngine != null) { - locationEngine.removeLocationEngineListener(this); - } - if (mapboxMap != null) { - mapboxMap.removeOnCameraMoveListener(this); - } + public void forceLocationUpdate(@Nullable Location location) { + updateLocation(location); } /** - * Required to place inside your activities {@code onStart} method. You'll also most likely want - * to check that this Location Layer plugin instance inside your activity is null or not. + * Set the location engine to update the current user location. + *
+ * If {@code null} is passed in, all updates will occur through the + * {@link LocationLayerPlugin#forceLocationUpdate(Location)} method. * + * @param locationEngine a {@link LocationEngine} this plugin should use to handle updates * @since 0.1.0 */ - @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) - @OnLifecycleEvent(Lifecycle.Event.ON_START) - public void onStart() { - if (locationLayerMode != LocationLayerMode.NONE) { - setLocationLayerEnabled(locationLayerMode); + @SuppressWarnings( {"MissingPermission"}) + public void setLocationEngine(@Nullable LocationEngine locationEngine) { + if (this.locationEngine != null) { + this.locationEngine.removeLocationEngineListener(locationEngineListener); + this.locationEngine = null; } - if (!compassManager.getCompassListeners().isEmpty() - || (locationLayerMode == LocationLayerMode.COMPASS && compassManager.isSensorAvailable())) { - compassManager.onStart(); - } - if (mapboxMap != null) { - mapboxMap.addOnCameraMoveListener(this); + if (locationEngine != null) { + this.locationEngine = locationEngine; + if (isEnabled) { + this.locationEngine.addLocationEngineListener(locationEngineListener); + } } - staleStateRunnable.addOnLocationStaleListener(this); } /** - * Check whether the location update animator is using a linear or an accelerate/decelerate - * interpolator. When the navigation mode is being used, the animator automatically become linear. + * Returns the current {@link LocationEngine} being used for updating the user location layer. * - * @return boolean true if the location update animator is set to linear, otherwise false + * @return the {@link LocationEngine} being used to update the user location layer * @since 0.1.0 */ - public boolean isLinearAnimation() { - return linearAnimation; + @Nullable + public LocationEngine getLocationEngine() { + return locationEngine; } /** - * Set whether the location update animator is using linear (true) or an accelerate/decelerate - * (false) interpolator. When the navigation mode is being used, the animator automatically become - * linear. + * Get the last know location of the location layer plugin. * - * @param linearAnimation boolean true if you'd like to set the location update animator to - * linear, otherwise false + * @return the last known location * @since 0.1.0 */ - public void setLinearAnimation(boolean linearAnimation) { - this.linearAnimation = linearAnimation; + @SuppressLint("MissingPermission") + @Nullable + public Location getLastKnownLocation() { + return locationEngine != null ? locationEngine.getLastLocation() : null; } /** @@ -348,203 +348,195 @@ public void setLinearAnimation(boolean linearAnimation) { * accuracy changes * @since 0.2.0 */ + public void addCompassListener(@NonNull CompassListener compassListener) { compassManager.addCompassListener(compassListener); - compassManager.onStart(); } /** - * Remove either a single instance of compass listener or all the listeners using null. + * Remove a compass listener. * * @param compassListener the {@link CompassListener} which you'd like to remove from the listener - * list. You can optionally pass in null to remove all listeners + * list. */ - public void removeCompassListener(@Nullable CompassListener compassListener) { + public void removeCompassListener(@NonNull CompassListener compassListener) { compassManager.removeCompassListener(compassListener); - if (compassManager.getCompassListeners().isEmpty()) { - compassManager.onStop(); - } } /** * Adds a listener that gets invoked when the user clicks the location layer. * - * @param locationClickListener The location layer click listener that is invoked when the - * location layer is clicked + * @param listener The location layer click listener that is invoked when the + * location layer is clicked * @since 0.3.0 */ - public void setOnLocationClickListener( - @Nullable OnLocationLayerClickListener locationClickListener) { - this.onLocationLayerClickListener = locationClickListener; - if (onLocationLayerClickListener != null) { - mapboxMap.addOnMapClickListener(this); - } - } - - @Override - public void onMapClick(@NonNull LatLng point) { - if (onLocationLayerClickListener != null && locationLayer.onMapClick(point)) { - onLocationLayerClickListener.onLocationLayerClick(); - } + public void addOnLocationClickListener(@NonNull OnLocationLayerClickListener listener) { + onLocationLayerClickListeners.add(listener); } - @Override - @SuppressWarnings( {"MissingPermission"}) - public void onConnected() { - if (locationEngine != null) { - locationEngine.requestLocationUpdates(); - } - } - - @Override - public void onLocationChanged(Location location) { - updateLocation(location); - } - - @Override - public void onCompassChanged(float userHeading) { - bearingChangeAnimate(userHeading); - } - - @Override - public void onCompassAccuracyChange(int compassStatus) { - // Currently don't handle this inside SDK - } - - private void toggleCameraListener() { - if (locationLayerMode == LocationLayerMode.NAVIGATION) { - mapboxMap.removeOnCameraMoveListener(this); - return; - } - mapboxMap.addOnCameraMoveListener(this); + /** + * Removes the passed listener from the current list of location click listeners. + * + * @param listener to be removed + * @since 0.3.0 + */ + public void removeOnLocationClickListener(@NonNull OnLocationLayerClickListener listener) { + onLocationLayerClickListeners.remove(listener); } - private void updateLocation(Location location) { - this.location = location; - if (location == null) { - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - return; - } - if (locationLayerMode == LocationLayerMode.NAVIGATION && location.hasBearing()) { - bearingChangeAnimate(location.getBearing()); - } else if (locationLayerMode != LocationLayerMode.NAVIGATION) { - locationLayer.updateAccuracyRadius(location); - } - setLocation(location); + /** + * Adds a listener that gets invoked when the user long clicks the location layer. + * + * @param listener The location layer click listener that is invoked when the + * location layer is clicked + * @since 0.5.0 + */ + public void addOnLocationLongClickListener(@NonNull OnLocationLayerLongClickListener listener) { + onLocationLayerLongClickListeners.add(listener); } /** - * disable the location layer plugin if the locationLayerMode is set to none. + * Removes the passed listener from the current list of location long click listeners. + * + * @param listener to be removed + * @since 0.5.0 */ - private void disableLocationLayerPlugin() { - if (locationEngine != null) { - locationEngine.removeLocationEngineListener(this); - } - locationLayer.setLayersVisibility(false); + public void removeOnLocationLongClickListener(@NonNull OnLocationLayerLongClickListener listener) { + onLocationLayerLongClickListeners.remove(listener); } /** - * If the locationEngine contains a last location value, we use it for the initial location layer - * position. + * Adds a listener that gets invoked when camera tracking state changes. + * + * @param listener Listener that gets invoked when camera tracking state changes. + * @since 0.5.0 */ - @SuppressWarnings( {"MissingPermission"}) - private void setLastLocation() { - Location lastLocation = locationEngine.getLastLocation(); - if (lastLocation != null) { - setLocation(lastLocation); - if (locationLayerMode != LocationLayerMode.NAVIGATION) { - locationLayer.updateAccuracyRadius(lastLocation); - } - } + public void addOnCameraTrackingChangedListener(@NonNull OnCameraTrackingChangedListener listener) { + onCameraTrackingChangedListeners.add(listener); } /** - * Get the last know location of the location layer plugin. + * Removes a listener that gets invoked when camera tracking state changes. * - * @return the last known location + * @param listener Listener that gets invoked when camera tracking state changes. + * @since 0.5.0 */ - @Nullable - public Location getLastKnownLocation() { - return location; + public void removeOnCameraTrackingChangedListener(@NonNull OnCameraTrackingChangedListener listener) { + onCameraTrackingChangedListeners.remove(listener); } /** - * Convenience method for stopping all animations + * Adds the passed listener that gets invoked when user updates have stopped long enough for the last update + * to be considered stale. + *
+ * This timeout is set by {@link LocationLayerOptions#staleStateTimeout()}. + * + * @param listener invoked when last update is considered stale + * @since 0.5.0 */ - private void stopAllAnimations() { - if (locationChangeAnimator != null) { - locationChangeAnimator.removeAllListeners(); - locationChangeAnimator.cancel(); - locationChangeAnimator = null; - } - if (bearingChangeAnimator != null) { - bearingChangeAnimator.removeAllListeners(); - bearingChangeAnimator.cancel(); - bearingChangeAnimator = null; - } + public void addOnLocationStaleListener(@NonNull OnLocationStaleListener listener) { + onLocationStaleListeners.add(listener); } /** - * If the location layer was being displayed before the style change, it will need to be displayed - * in the new style. + * Removes the passed listener from the current list of stale listeners. + * + * @param listener to be removed from the list + * @since 0.5.0 */ - @SuppressWarnings( {"MissingPermission"}) - private void mapStyleFinishedLoading() { - // recreate runtime style components - locationLayer = new LocationLayer(mapView, mapboxMap, options, staleStateRunnable); - // reset state - setLocationLayerEnabled(locationLayerMode); - setBearing(previousMagneticHeading); - if (previousPoint != null) { - locationLayer.setLocationPoint(previousPoint); - } + public void removeOnLocationStaleListener(@NonNull OnLocationStaleListener listener) { + onLocationStaleListeners.remove(listener); } /** - * Enable or disable the My Location bearing by passing in a boolean here. Once enabled, The users - * location and bearing's indicated on the map by default as a small blue dot with a chevron - * pointing in the direction of the devices compass bearing. + * Required to place inside your activities {@code onStart} method. You'll also most likely want + * to check that this Location Layer plugin instance inside your activity is null or not. * - * @param bearingEnabled boolean true if you'd like to enable the user location bearing, - * otherwise, false will disable * @since 0.1.0 */ - private void setMyBearingEnabled(boolean bearingEnabled) { - locationLayer.setLayerVisibility(BEARING_LAYER, bearingEnabled); - if (bearingEnabled) { - compassManager.onStart(); - } else { - if (compassManager != null && compassManager.getCompassListeners().isEmpty()) { - compassManager.onStop(); + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + @OnLifecycleEvent(Lifecycle.Event.ON_START) + public void onStart() { + if (isEnabled) { + if (locationEngine != null) { + locationEngine.addLocationEngineListener(locationEngineListener); } + setLastLocation(); + setLastCompassHeading(); } + if (mapboxMap != null) { + mapboxMap.addOnCameraMoveListener(onCameraMoveListener); + } + if (options.enableStaleState()) { + staleStateManager.onStart(); + } + compassManager.onStart(); } /** - * Enable or disable the My Location navigation by passing in a boolean here. Once enabled, The - * users location indicated on the map will show (by default) as a large navigation puck with a - * cheveron/arrow showing the users GPS location bearing. + * Required to place inside your activities {@code onStop} method. * - * @param navigationEnabled boolean true if you'd like to enable the user location navigation, - * disable otherwise, false will * @since 0.1.0 */ - private void setNavigationEnabled(boolean navigationEnabled) { - setNavigationLayerVisibility(navigationEnabled); - setLinearAnimation(navigationEnabled); - locationLayer.setLayerVisibility(ACCURACY_LAYER, !navigationEnabled); + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + staleStateManager.onStop(); + compassManager.onStop(); + locationLayerAnimator.cancelAllAnimations(); + if (locationEngine != null) { + locationEngine.removeLocationEngineListener(locationEngineListener); + } + if (mapboxMap != null) { + mapboxMap.removeOnCameraMoveListener(onCameraMoveListener); + } } - private void setNavigationLayerVisibility(boolean visible) { - locationLayer.setLayerVisibility(NAVIGATION_LAYER, visible); + private void initialize() { + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); + + mapView.addOnMapChangedListener(onMapChangedListener); + mapboxMap.addOnMapClickListener(onMapClickListener); + mapboxMap.addOnMapLongClickListener(onMapLongClickListener); + updateMapWithOptions(options); + + locationLayer = new LocationLayer(mapView, mapboxMap, options); + locationLayerCamera = new LocationLayerCamera( + mapView.getContext(), mapboxMap, cameraTrackingChangedListener, options); + locationLayerAnimator = new LocationLayerAnimator(); + locationLayerAnimator.addLayerListener(locationLayer); + locationLayerAnimator.addCameraListener(locationLayerCamera); + + compassManager = new CompassManager(mapView.getContext()); + compassManager.addCompassListener(compassListener); + staleStateManager = new StaleStateManager(onLocationStaleListener, options.staleStateTimeout()); + + enableLocationLayerPlugin(); } - @Override - public void onCameraMove() { - CameraPosition position = mapboxMap.getCameraPosition(); - locationLayer.updateAccuracyRadius(location); - locationLayer.updateForegroundOffset(position.tilt); - locationLayer.updateForegroundBearing((float) position.bearing); + @SuppressLint("MissingPermission") + private void enableLocationLayerPlugin() { + isEnabled = true; + onStart(); + locationLayer.show(); + } + + private void disableLocationLayerPlugin() { + isEnabled = false; + onStop(); + locationLayer.hide(); + } + + private void updateMapWithOptions(LocationLayerOptions options) { + int[] padding = options.padding(); + if (padding != null && padding.length == 4) { + setPadding(options.padding()[0], padding[1], padding[2], padding[3]); + } + if (options.maxZoom() > 0) { + setMaxZoom(options.maxZoom()); + } + if (options.minZoom() > 0) { + setMinZoom(options.minZoom()); + } } /** @@ -553,113 +545,136 @@ public void onCameraMove() { * @param location the latest user location * @since 0.1.0 */ - private void setLocation(final Location location) { - this.location = location; - staleStateRunnable.updateLatestLocationTime(); - - // Convert the new location to a Point object. - Point newPoint = Point.fromCoordinates(new double[] {location.getLongitude(), - location.getLatitude()}); - - // If the source doesn't have geometry, a Point gets added. - if (previousPoint == null) { - locationLayer.setLocationPoint(newPoint); - previousPoint = newPoint; - return; - } - - // Do nothing if the location source's current Point is identical to the new location Point. - if (previousPoint.getCoordinates().equals(newPoint.getCoordinates())) { + private void updateLocation(final Location location) { + if (location == null) { return; } - locationChangeAnimate(previousPoint, newPoint); + staleStateManager.updateLatestLocationTime(); + CameraPosition currentCameraPosition = mapboxMap.getCameraPosition(); + boolean isGpsNorth = getCameraMode() == CameraMode.TRACKING_GPS_NORTH; + locationLayerAnimator.feedNewLocation(location, currentCameraPosition, isGpsNorth); + locationLayer.updateAccuracyRadius(location); } - /* - * Animators - */ + private void updateCompassHeading(float heading) { + locationLayerAnimator.feedNewCompassBearing(heading, mapboxMap.getCameraPosition()); + } /** - * Handles the animation from currentSourcePoint to the new user location point. + * If the locationEngine contains a last location value, we use it for the initial location layer + * position. */ - private void locationChangeAnimate(@NonNull Point currentSourcePoint, @NonNull Point newPoint) { - if (locationChangeAnimator != null) { - locationChangeAnimator.end(); + @SuppressWarnings( {"MissingPermission"}) + private void setLastLocation() { + if (locationEngine != null) { + updateLocation(locationEngine.getLastLocation()); } + } - locationChangeAnimator = ValueAnimator.ofObject(new Utils.PointEvaluator(), currentSourcePoint, - newPoint); + private void setLastCompassHeading() { + updateCompassHeading(compassManager.getLastHeading()); + } - float speed = location == null ? 0 : location.getSpeed(); + private OnCameraMoveListener onCameraMoveListener = new OnCameraMoveListener() { - locationChangeAnimator.setDuration(linearAnimation || speed > 0 - ? getLocationUpdateDuration() : LocationLayerConstants.LOCATION_UPDATE_DELAY_MS); - if (linearAnimation || speed > 0) { - locationChangeAnimator.setInterpolator(new LinearInterpolator()); - } else { - locationChangeAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + private double lastZoom; + + @Override + public void onCameraMove() { + double zoom = mapboxMap.getCameraPosition().zoom; + if (zoom != lastZoom) { + locationLayer.updateAccuracyRadius(getLastKnownLocation()); + } + lastZoom = zoom; } - locationChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - previousPoint = (Point) animation.getAnimatedValue(); - locationLayer.setLocationPoint(previousPoint); + }; + + private OnMapClickListener onMapClickListener = new OnMapClickListener() { + @Override + public void onMapClick(@NonNull LatLng point) { + if (!onLocationLayerClickListeners.isEmpty() && locationLayer.onMapClick(point)) { + for (OnLocationLayerClickListener listener : onLocationLayerClickListeners) { + listener.onLocationLayerClick(); + } } - }); - locationChangeAnimator.start(); - } + } + }; + + private MapboxMap.OnMapLongClickListener onMapLongClickListener = new MapboxMap.OnMapLongClickListener() { + @Override + public void onMapLongClick(@NonNull LatLng point) { + if (!onLocationLayerLongClickListeners.isEmpty() && locationLayer.onMapClick(point)) { + for (OnLocationLayerLongClickListener listener : onLocationLayerLongClickListeners) { + listener.onLocationLayerLongClick(); + } + } + } + }; - /** - * Handles the animation from the previous user bearing to the current. - * - * @param magneticHeading the raw compass heading - * @since 0.1.0 - */ - private void bearingChangeAnimate(float magneticHeading) { - if (bearingChangeAnimator != null) { - previousMagneticHeading = (Float) bearingChangeAnimator.getAnimatedValue(); - bearingChangeAnimator.end(); - bearingChangeAnimator = null; + private OnLocationStaleListener onLocationStaleListener = new OnLocationStaleListener() { + @Override + public void onStaleStateChange(boolean isStale) { + locationLayer.setLocationsStale(isStale); + + for (OnLocationStaleListener listener : onLocationStaleListeners) { + listener.onStaleStateChange(isStale); + } } + }; + + private OnMapChangedListener onMapChangedListener = new OnMapChangedListener() { + @SuppressLint("MissingPermission") + @Override + public void onMapChanged(int change) { + if (change == MapView.WILL_START_LOADING_MAP) { + onStop(); + } else if (change == MapView.DID_FINISH_LOADING_STYLE) { + locationLayer.initializeComponents(options); + locationLayerCamera.initializeOptions(options); + setRenderMode(locationLayer.getRenderMode()); + onStart(); + } + } + }; - // Always rotate the bearing shortest distance - magneticHeading = shortestRotation(magneticHeading, previousMagneticHeading); + private CompassListener compassListener = new CompassListener() { + @Override + public void onCompassChanged(float userHeading) { + updateCompassHeading(userHeading); + } - // No visible change occurred - if (Math.abs(magneticHeading - previousMagneticHeading) < 1) { - return; + @Override + public void onCompassAccuracyChange(int compassStatus) { + // Currently don't handle this inside SDK } + }; - bearingChangeAnimator = ValueAnimator.ofFloat(previousMagneticHeading, magneticHeading); - bearingChangeAnimator.setDuration(COMPASS_UPDATE_RATE_MS); - bearingChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator valueAnimator) { - setBearing((float) valueAnimator.getAnimatedValue()); - } - }); - bearingChangeAnimator.start(); - previousMagneticHeading = magneticHeading; - } + private LocationEngineListener locationEngineListener = new LocationEngineListener() { + @Override + @SuppressWarnings( {"MissingPermission"}) + public void onConnected() { + // Currently don't handle this inside SDK + } - private void setBearing(float bearing) { - locationLayer.setLayerBearing( - locationLayerMode == LocationLayerMode.NAVIGATION - ? NAVIGATION_LAYER : BEARING_LAYER, bearing - ); - } + @Override + public void onLocationChanged(Location location) { + updateLocation(location); + } + }; - /** - * Internal method being used to calculate the time duration for the location change animator. - * - * @return millisecond time value as a long value - * @since 0.1.0 - */ - private long getLocationUpdateDuration() { - // calculate updateLatLng time + add some extra offset to improve animation - long previousUpdateTimeStamp = locationUpdateTimestamp; - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - long duration = locationUpdateTimestamp - previousUpdateTimeStamp; - return duration < MAX_ANIMATION_DURATION_MS ? duration : MAX_ANIMATION_DURATION_MS; - } + private OnCameraTrackingChangedListener cameraTrackingChangedListener = new OnCameraTrackingChangedListener() { + @Override + public void onCameraTrackingDismissed() { + for (OnCameraTrackingChangedListener listener : onCameraTrackingChangedListeners) { + listener.onCameraTrackingDismissed(); + } + } + + @Override + public void onCameraTrackingChanged(int currentMode) { + for (OnCameraTrackingChangedListener listener : onCameraTrackingChangedListeners) { + listener.onCameraTrackingChanged(currentMode); + } + } + }; } diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java new file mode 100644 index 000000000..272b3c73f --- /dev/null +++ b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java @@ -0,0 +1,21 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode; + +/** + * Listener that gets invoked when camera tracking state changes. + */ +public interface OnCameraTrackingChangedListener { + /** + * Invoked whenever camera tracking is broken. + * This callback gets invoked just after {@link #onCameraTrackingChanged(int)}, if needed. + */ + void onCameraTrackingDismissed(); + + /** + * Invoked on every {@link CameraMode} change. + * + * @param currentMode current active {@link CameraMode}. + */ + void onCameraTrackingChanged(@CameraMode.Mode int currentMode); +} diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java index ec811319b..7cfb79502 100644 --- a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java +++ b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java @@ -10,5 +10,4 @@ public interface OnLocationLayerClickListener { void onLocationLayerClick(); - } diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java new file mode 100644 index 000000000..cebcf3e8d --- /dev/null +++ b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java @@ -0,0 +1,13 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +/** + * The Location Layer Plugin exposes an API for listening to when the user long clicks on the location + * layer icon visible on the map. when this event occurs, the {@link #onLocationLayerLongClick()} method + * gets invoked. + * + * @since 0.5.0 + */ +public interface OnLocationLayerLongClickListener { + + void onLocationLayerLongClick(); +} diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java index a872f5fee..7389dd945 100644 --- a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java +++ b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java @@ -1,7 +1,15 @@ package com.mapbox.mapboxsdk.plugins.locationlayer; +/** + * Listener that can be added as a callback when the last location update + * is considered stale. + *
+ * The time from the last location update that determines if a location update
+ * is stale or not is provided by {@link LocationLayerOptions#staleStateTimeout()}.
+ *
+ * @since 0.5.0
+ */
public interface OnLocationStaleListener {
- void isLocationStale(boolean stale);
-
+ void onStaleStateChange(boolean isStale);
}
diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java
new file mode 100644
index 000000000..5558832de
--- /dev/null
+++ b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java
@@ -0,0 +1,65 @@
+package com.mapbox.mapboxsdk.plugins.locationlayer;
+
+import android.os.Handler;
+
+/**
+ * Class controls the location layer stale state when the {@link android.location.Location} hasn't
+ * been updated in 'x' amount of time. {@link LocationLayerOptions#staleStateTimeout()} can be used to
+ * control the amount of time before the locations considered stale.
+ * {@link LocationLayerOptions#enableStaleState()} is available for disabling this behaviour.
+ *
+ * @since 0.4.0
+ */
+class StaleStateManager {
+
+ private final OnLocationStaleListener innerOnLocationStaleListeners;
+ private final Handler handler;
+ private boolean isStale;
+ private long delayTime;
+
+ StaleStateManager(OnLocationStaleListener innerListener, long delayTime) {
+ innerOnLocationStaleListeners = innerListener;
+ this.delayTime = delayTime;
+ handler = new Handler();
+ }
+
+ private Runnable staleStateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ isStale = true;
+ innerOnLocationStaleListeners.onStaleStateChange(true);
+ }
+ };
+
+ boolean isStale() {
+ return isStale;
+ }
+
+ void updateLatestLocationTime() {
+ if (isStale) {
+ isStale = false;
+ innerOnLocationStaleListeners.onStaleStateChange(false);
+ }
+ postTheCallback();
+ }
+
+ void setDelayTime(long delayTime) {
+ this.delayTime = delayTime;
+ postTheCallback();
+ }
+
+ void onStart() {
+ if (!isStale) {
+ postTheCallback();
+ }
+ }
+
+ void onStop() {
+ handler.removeCallbacksAndMessages(null);
+ }
+
+ private void postTheCallback() {
+ handler.removeCallbacksAndMessages(null);
+ handler.postDelayed(staleStateRunnable, delayTime);
+ }
+}
diff --git a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateRunnable.java b/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateRunnable.java
deleted file mode 100644
index 56f2f3dff..000000000
--- a/plugin-locationlayer/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateRunnable.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.mapbox.mapboxsdk.plugins.locationlayer;
-
-import android.os.Handler;
-import android.support.annotation.NonNull;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Class controls the location layer stale state when the {@link android.location.Location} hasn't
- * been updated in 'x' amount of time. {@link LocationLayerOptions#staleStateDelay()} can be used to
- * control the amount of time before the locations considered stale.
- * {@link LocationLayerOptions#enableStaleState()} is avaliable for disabling this behaviour.
- *
- * @since 0.4.0
- */
-class StaleStateRunnable implements Runnable {
-
- private final List