[android] register compass sensor listener only if provided data is consumed by the location layer or location camera

This commit is contained in:
Łukasz Paczos
2018-12-13 12:40:40 +01:00
committed by Łukasz Paczos
parent 3fbd9578c7
commit 1d410c94fc
8 changed files with 288 additions and 22 deletions

View File

@@ -55,11 +55,17 @@ public interface CompassEngine {
/**
* Lifecycle method that can be used for adding or releasing resources.
*
* @deprecated Use {@link #addCompassListener(CompassListener)}
*/
@Deprecated
void onStart();
/**
* Lifecycle method that can be used for adding or releasing resources.
*
* @deprecated Use {@link #removeCompassListener(CompassListener)}
*/
@Deprecated
void onStop();
}

View File

@@ -7,7 +7,7 @@ public interface CompassListener {
/**
* Callback's invoked when a new compass update occurs. You can listen into the compass updates
* using {@link LocationComponent#addCompassListener(CompassListener)} and implementing these
* using {@link CompassEngine#addCompassListener(CompassListener)} and implementing these
* callbacks. Note that this interface is also used internally to to update the UI chevron/arrow.
*
* @param userHeading the new compass heading

View File

@@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.view.MotionEvent;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -246,6 +247,11 @@ final class LocationCameraController implements MapboxAnimator.OnCameraAnimation
}
}
boolean isConsumingCompass() {
return cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.NONE_COMPASS;
}
private boolean isLocationTracking() {
return cameraMode == CameraMode.TRACKING
|| cameraMode == CameraMode.TRACKING_COMPASS

View File

@@ -107,6 +107,7 @@ public final class LocationComponent {
private LocationEngineCallback<LocationEngineResult> lastLocationEngineListener
= new LastLocationEngineCallback(this);
@Nullable
private CompassEngine compassEngine;
private LocationLayerController locationLayerController;
@@ -146,6 +147,11 @@ public final class LocationComponent {
*/
private boolean isLayerReady;
/**
* Indicates whether we are listening for compass updates.
*/
private boolean isListeningToCompass;
private StaleStateManager staleStateManager;
private final CopyOnWriteArrayList<OnLocationStaleListener> onLocationStaleListeners
= new CopyOnWriteArrayList<>();
@@ -439,6 +445,7 @@ public final class LocationComponent {
public void setCameraMode(@CameraMode.Mode int cameraMode,
@Nullable OnLocationCameraTransitionListener transitionListener) {
locationCameraController.setCameraMode(cameraMode, lastLocation, new CameraTransitionListener(transitionListener));
updateCompassListenerState(true);
}
/**
@@ -498,6 +505,7 @@ public final class LocationComponent {
public void setRenderMode(@RenderMode.Mode int renderMode) {
locationLayerController.setRenderMode(renderMode);
updateLayerOffsets(true);
updateCompassListenerState(true);
}
/**
@@ -734,10 +742,12 @@ public final class LocationComponent {
*
* @param compassEngine to be used
*/
public void setCompassEngine(@NonNull CompassEngine compassEngine) {
this.compassEngine.removeCompassListener(compassListener);
public void setCompassEngine(@Nullable CompassEngine compassEngine) {
if (this.compassEngine != null) {
updateCompassListenerState(false);
}
this.compassEngine = compassEngine;
compassEngine.addCompassListener(compassListener);
updateCompassListenerState(true);
}
/**
@@ -745,7 +755,7 @@ public final class LocationComponent {
*
* @return compass engine currently being used
*/
@NonNull
@Nullable
public CompassEngine getCompassEngine() {
return compassEngine;
}
@@ -767,9 +777,11 @@ public final class LocationComponent {
* The last known accuracy of the compass sensor, one of SensorManager.SENSOR_STATUS_*
*
* @return the last know compass accuracy bearing
* @deprecated Use {@link #getCompassEngine()}
*/
@Deprecated
public float getLastKnownCompassAccuracyStatus() {
return compassEngine.getLastAccuracySensorStatus();
return compassEngine != null ? compassEngine.getLastAccuracySensorStatus() : 0;
}
/**
@@ -778,9 +790,13 @@ public final class LocationComponent {
*
* @param compassListener a {@link CompassListener} for listening into compass heading and
* accuracy changes
* @deprecated Use {@link #getCompassEngine()}
*/
@Deprecated
public void addCompassListener(@NonNull CompassListener compassListener) {
compassEngine.addCompassListener(compassListener);
if (compassEngine != null) {
compassEngine.addCompassListener(compassListener);
}
}
/**
@@ -788,9 +804,13 @@ public final class LocationComponent {
*
* @param compassListener the {@link CompassListener} which you'd like to remove from the listener
* list.
* @deprecated Use {@link #getCompassEngine()}
*/
@Deprecated
public void removeCompassListener(@NonNull CompassListener compassListener) {
compassEngine.removeCompassListener(compassListener);
if (compassEngine != null) {
compassEngine.removeCompassListener(compassListener);
}
}
/**
@@ -934,7 +954,6 @@ public final class LocationComponent {
if (options.enableStaleState()) {
staleStateManager.onStart();
}
compassEngine.onStart();
}
if (isEnabled) {
@@ -948,6 +967,7 @@ public final class LocationComponent {
}
setCameraMode(locationCameraController.getCameraMode());
setLastLocation();
updateCompassListenerState(true);
setLastCompassHeading();
}
}
@@ -960,7 +980,9 @@ public final class LocationComponent {
isLayerReady = false;
locationLayerController.hide();
staleStateManager.onStop();
compassEngine.onStop();
if (compassEngine != null) {
updateCompassListenerState(false);
}
locationAnimatorCoordinator.cancelAllAnimations();
if (locationEngine != null) {
locationEngine.removeLocationUpdates(currentLocationEngineListener);
@@ -1001,8 +1023,9 @@ public final class LocationComponent {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
compassEngine = new LocationComponentCompassEngine(windowManager, sensorManager);
compassEngine.addCompassListener(compassListener);
if (windowManager != null && sensorManager != null) {
compassEngine = new LocationComponentCompassEngine(windowManager, sensorManager);
}
staleStateManager = new StaleStateManager(onLocationStaleListener, options);
updateMapWithOptions(options);
@@ -1022,6 +1045,38 @@ public final class LocationComponent {
locationEngine = internalLocationEngineProvider.getBestLocationEngine(context, false);
}
private void updateCompassListenerState(boolean canListen) {
if (compassEngine != null) {
if (!canListen) {
// We shouldn't listen, simply unregistering
removeCompassListener(compassEngine);
return;
}
if (!isComponentInitialized || !isComponentStarted || !isEnabled) {
return;
}
if (locationCameraController.isConsumingCompass() || locationLayerController.isConsumingCompass()) {
// If we have a consumer, and not yet listening, then start listening
if (!isListeningToCompass) {
isListeningToCompass = true;
compassEngine.addCompassListener(compassListener);
}
} else {
// If we have no consumers, stop listening
removeCompassListener(compassEngine);
}
}
}
private void removeCompassListener(@NonNull CompassEngine engine) {
if (isListeningToCompass) {
isListeningToCompass = false;
engine.removeCompassListener(compassListener);
}
}
private void enableLocationComponent() {
isEnabled = true;
onLocationLayerStart();
@@ -1091,7 +1146,7 @@ public final class LocationComponent {
}
private void setLastCompassHeading() {
updateCompassHeading(compassEngine.getLastHeading());
updateCompassHeading(compassEngine != null ? compassEngine.getLastHeading() : 0);
}
@SuppressLint("MissingPermission")

View File

@@ -10,6 +10,8 @@ import android.support.annotation.Nullable;
import android.view.Surface;
import android.view.WindowManager;
import com.mapbox.mapboxsdk.log.Logger;
import java.util.ArrayList;
import java.util.List;
@@ -21,15 +23,18 @@ import timber.log.Timber;
*/
class LocationComponentCompassEngine implements CompassEngine, SensorEventListener {
private static final String TAG = "Mbgl-LocationComponentCompassEngine";
// The rate sensor events will be delivered at. As the Android documentation states, this is only
// a hint to the system and the events might actually be received faster or slower then this
// specified rate. Since the minimum Android API levels about 9, we are able to set this value
// ourselves rather than using one of the provided constants which deliver updates too quickly for
// our use case. The default is set to 100ms
private static final int SENSOR_DELAY_MICROS = 100 * 1000;
static final int SENSOR_DELAY_MICROS = 100 * 1000;
// Filtering coefficient 0 < ALPHA < 1
private static final float ALPHA = 0.45f;
@NonNull
private final WindowManager windowManager;
@NonNull
private final SensorManager sensorManager;
@@ -61,7 +66,7 @@ class LocationComponentCompassEngine implements CompassEngine, SensorEventListen
* Construct a new instance of the this class. A internal compass listeners needed to separate it
* from the cleared list of public listeners.
*/
LocationComponentCompassEngine(WindowManager windowManager, SensorManager sensorManager) {
LocationComponentCompassEngine(@NonNull WindowManager windowManager, @NonNull SensorManager sensorManager) {
this.windowManager = windowManager;
this.sensorManager = sensorManager;
compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
@@ -80,7 +85,7 @@ class LocationComponentCompassEngine implements CompassEngine, SensorEventListen
@Override
public void addCompassListener(@NonNull CompassListener compassListener) {
if (compassListeners.isEmpty()) {
onStart();
registerSensorListeners();
}
compassListeners.add(compassListener);
}
@@ -89,7 +94,7 @@ class LocationComponentCompassEngine implements CompassEngine, SensorEventListen
public void removeCompassListener(@NonNull CompassListener compassListener) {
compassListeners.remove(compassListener);
if (compassListeners.isEmpty()) {
onStop();
unregisterSensorListeners();
}
}
@@ -105,12 +110,16 @@ class LocationComponentCompassEngine implements CompassEngine, SensorEventListen
@Override
public void onStart() {
registerSensorListeners();
if (!compassListeners.isEmpty()) {
registerSensorListeners();
}
}
@Override
public void onStop() {
unregisterSensorListeners();
if (!compassListeners.isEmpty()) {
unregisterSensorListeners();
}
}
@Override
@@ -121,7 +130,7 @@ class LocationComponentCompassEngine implements CompassEngine, SensorEventListen
return;
}
if (lastAccuracySensorStatus == SensorManager.SENSOR_STATUS_UNRELIABLE) {
Timber.d("Compass sensor is unreliable, device calibration is needed.");
Logger.d(TAG, "Compass sensor is unreliable, device calibration is needed.");
return;
}
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
@@ -238,7 +247,7 @@ class LocationComponentCompassEngine implements CompassEngine, SensorEventListen
* @param smoothedValues array of float, that contains previous state
* @return float filtered array of float
*/
@Nullable
@NonNull
private float[] lowPassFilter(@NonNull float[] newValues, @Nullable float[] smoothedValues) {
if (smoothedValues == null) {
return newValues;

View File

@@ -11,8 +11,8 @@ import com.google.gson.JsonObject;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
@@ -196,6 +196,10 @@ final class LocationLayerController implements MapboxAnimator.OnLayerAnimationsV
return isHidden;
}
boolean isConsumingCompass() {
return renderMode == RenderMode.COMPASS;
}
private void setLayerVisibility(@NonNull String layerId, boolean visible) {
Layer layer = style.getLayer(layerId);
if (layer != null) {