diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index 1c100c6e9..38265b79d 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -64,6 +64,7 @@ import com.mapbox.mapboxgl.annotations.PolylineOptions; import com.mapbox.mapboxgl.geometry.BoundingBox; import com.mapbox.mapboxgl.geometry.LatLng; import com.mapbox.mapboxgl.geometry.LatLngZoom; +import com.mapbox.mapboxgl.views.widgets.CompassView; import com.mapzen.android.lost.api.LocationListener; import com.mapzen.android.lost.api.LocationRequest; import com.mapzen.android.lost.api.LocationServices; @@ -90,7 +91,7 @@ import java.util.List; *
Warning: Please note that you are responsible for getting permission to use the map data, * and for ensuring your use adheres to the relevant terms of use.
*/ -public class MapView extends FrameLayout implements LocationListener { +public class MapView extends FrameLayout implements LocationListener, CompassView.CompassDelegate { // // Static members @@ -181,18 +182,7 @@ public class MapView extends FrameLayout implements LocationListener { private Location mGpsLocation; // Used for the compass - private ImageView mCompassView; - private SensorManager mSensorManager; - private Sensor mSensorAccelerometer; - private Sensor mSensorMagneticField; - private CompassListener mCompassListener; - private float[] mValuesAccelerometer = new float[3]; - private float[] mValuesMagneticField = new float[3]; - private float[] mMatrixR = new float[9]; - private float[] mMatrixI = new float[9]; - private float[] mMatrixValues = new float[3]; - private float mCompassBearing; - private boolean mCompassValid = false; + private CompassView mCompassView; // Used for displaying annotation markers // Every annotation that has been added to the map @@ -223,7 +213,6 @@ public class MapView extends FrameLayout implements LocationListener { private boolean mRotateEnabled = true; private String mStyleUrl; private boolean mIsMyLocationEnabled = false; - private boolean mIsCompassEnabled = true; // // Enums @@ -473,22 +462,10 @@ public class MapView extends FrameLayout implements LocationListener { addView(mGpsMarker); // Setup compass - mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); - mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); - mCompassListener = new CompassListener(); - - // Setup compass UI - mCompassView = new ImageView(mContext); - mCompassView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass)); - mCompassView.setContentDescription(getResources().getString(R.string.compassContentDescription)); - LayoutParams lp = new FrameLayout.LayoutParams( - (int) (48 * mScreenDensity), - (int) (48 * mScreenDensity)); - mCompassView.setLayoutParams(lp); + mCompassView = new CompassView(mContext); mCompassView.setVisibility(View.INVISIBLE); + mCompassView.setOnClickListener(new CompassView.CompassClickListener(this)); addView(mCompassView); - mCompassView.setOnClickListener(new CompassOnClickListener()); // Setup Mapbox logo mLogoView = new ImageView(mContext); @@ -2141,16 +2118,14 @@ public class MapView extends FrameLayout implements LocationListener { mLocationClient.connect(); updateLocation(LocationServices.FusedLocationApi.getLastLocation()); LocationServices.FusedLocationApi.requestLocationUpdates(mLocationRequest, this); - //mSensorManager.registerListener(mCompassListener, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI); - //mSensorManager.registerListener(mCompassListener, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI); + mCompassView.registerListeners(this); } } else { if (mLocationClient.isConnected()) { + mCompassView.unRegisterListeners(); LocationServices.FusedLocationApi.removeLocationUpdates(this); mLocationClient.disconnect(); mGpsLocation = null; - //mSensorManager.unregisterListener(mCompassListener, mSensorAccelerometer); - //mSensorManager.unregisterListener(mCompassListener, mSensorMagneticField); } } @@ -2220,7 +2195,7 @@ public class MapView extends FrameLayout implements LocationListener { * @return true if the compass is enabled; false if the compass is disabled. */ public boolean isCompassEnabled() { - return mIsCompassEnabled; + return mCompassView.isEnabled(); } /** @@ -2235,7 +2210,7 @@ public class MapView extends FrameLayout implements LocationListener { * @param compassEnabled true to enable the compass; false to disable the compass. */ public void setCompassEnabled(boolean compassEnabled) { - this.mIsCompassEnabled = compassEnabled; + mCompassView.setEnabled(compassEnabled); onInvalidate(); } @@ -2247,60 +2222,6 @@ public class MapView extends FrameLayout implements LocationListener { setWidgetMargins(mCompassView, left, top, right, bottom); } - // This class handles sensor updates to calculate compass bearing - private class CompassListener implements SensorEventListener { - - @Override - public void onSensorChanged(SensorEvent event) { - switch (event.sensor.getType()) { - case Sensor.TYPE_ACCELEROMETER: - System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3); - break; - case Sensor.TYPE_MAGNETIC_FIELD: - System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3); - break; - } - - boolean valid = SensorManager.getRotationMatrix(mMatrixR, mMatrixI, - mValuesAccelerometer, - mValuesMagneticField); - - if (valid) { - SensorManager.getOrientation(mMatrixR, mMatrixValues); - //mAzimuthRadians.putValue(mMatrixValues[0]); - //mAzimuth = Math.toDegrees(mAzimuthRadians.getAverage()); - - Location mGpsLocation = getMyLocation(); - if (mGpsLocation != null) { - GeomagneticField geomagneticField = new GeomagneticField( - (float) mGpsLocation.getLatitude(), - (float) mGpsLocation.getLongitude(), - (float) mGpsLocation.getAltitude(), - System.currentTimeMillis()); - mCompassBearing = (float) Math.toDegrees(mMatrixValues[0]) + geomagneticField.getDeclination(); - mCompassValid = true; - } - } - - onInvalidate(); - } - - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - // TODO: ignore unreliable stuff - } - } - - // Called when someone presses the compass - private class CompassOnClickListener implements View.OnClickListener { - - @Override - public void onClick(View view) { - resetNorth(); - } - - } - // Rotates an ImageView - does not work if the ImageView has padding, use margins private void rotateImageView(ImageView imageView, float angle) { Matrix matrix = new Matrix(); @@ -2320,6 +2241,11 @@ public class MapView extends FrameLayout implements LocationListener { } } + @Override + public Location getLocation() { + return mGpsLocation; + } + // // Logo // diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/widgets/CompassView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/widgets/CompassView.java new file mode 100644 index 000000000..52a8c0bab --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/widgets/CompassView.java @@ -0,0 +1,160 @@ +package com.mapbox.mapboxgl.views.widgets; + +import android.content.Context; +import android.hardware.GeomagneticField; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.location.Location; +import android.support.v4.content.ContextCompat; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.mapbox.mapboxgl.views.MapView; +import com.mapbox.mapboxgl.views.R; + +import java.lang.ref.WeakReference; + +public class CompassView extends ImageView implements SensorEventListener { + + private CompassDelegate mCompassDelegate; + + // Sensor model + private SensorManager mSensorManager; + private Sensor mSensorAccelerometer; + private Sensor mSensorMagneticField; + + // Sensor data + private boolean mSensorValid; + private float[] mValuesAccelerometer = new float[3]; + private float[] mValuesMagneticField = new float[3]; + private float[] mMatrixR = new float[9]; + private float[] mMatrixI = new float[9]; + private float[] mMatrixValues = new float[3]; + + // Location data + private GeomagneticField mGeomagneticField; + private Location mGpsLocation; + + // Compass date + private float mCompassBearing; + private boolean mCompassValid; + + public CompassView(Context context) { + super(context); + initialize(context); + } + + public CompassView(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(context); + } + + public CompassView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context); + } + + private void initialize(Context context) { + // Sensor initialisation + mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + + // View configuration + setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass)); + setContentDescription(getResources().getString(R.string.compassContentDescription)); + + // Layout params + float mScreenDensity = context.getResources().getDisplayMetrics().density; + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) (48 * mScreenDensity), (int) (48 * mScreenDensity)); + setLayoutParams(lp); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); + } + + public boolean isValid() { + return mCompassValid; + } + + public float getBearing() { + return mCompassBearing; + } + + public void registerListeners(CompassDelegate compassDelegate) { + mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI); + mSensorManager.registerListener(this, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI); + mCompassDelegate = compassDelegate; + } + + public void unRegisterListeners() { + mCompassDelegate = null; + mSensorManager.unregisterListener(this, mSensorMagneticField); + mSensorManager.unregisterListener(this, mSensorAccelerometer); + } + + @Override + public void onSensorChanged(SensorEvent event) { + switch (event.sensor.getType()) { + case Sensor.TYPE_ACCELEROMETER: + System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3); + break; + case Sensor.TYPE_MAGNETIC_FIELD: + System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3); + break; + } + + mSensorValid = SensorManager.getRotationMatrix(mMatrixR, mMatrixI, + mValuesAccelerometer, + mValuesMagneticField); + + if (mSensorValid && mCompassDelegate != null) { + SensorManager.getOrientation(mMatrixR, mMatrixValues); + mGpsLocation = mCompassDelegate.getLocation(); + if (mGpsLocation != null) { + mGeomagneticField = new GeomagneticField( + (float) mGpsLocation.getLatitude(), + (float) mGpsLocation.getLongitude(), + (float) mGpsLocation.getAltitude(), + System.currentTimeMillis()); + mCompassBearing = (float) Math.toDegrees(mMatrixValues[0]) + mGeomagneticField.getDeclination(); + mCompassValid = true; + } + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // TODO: ignore unreliable stuff + } + + public interface CompassDelegate { + + Location getLocation(); + + } + + public static class CompassClickListener implements View.OnClickListener { + + private WeakReference