[android] register compass sensor listener only if provided data is consumed by the location layer or location camera
This commit is contained in:
committed by
Łukasz Paczos
parent
3fbd9578c7
commit
1d410c94fc
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user