From 4a3beeddba279f29ce32b172868aa907c9333e6b Mon Sep 17 00:00:00 2001 From: Tobrun Date: Sun, 6 Mar 2016 13:29:26 -0500 Subject: [android] #4211 - avoid crashes when NativeMapView is being destroyed --- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 187 ++++++++++++++++++--- 1 file changed, 161 insertions(+), 26 deletions(-) (limited to 'platform/android/MapboxGLAndroidSDK') diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 483099a387..78c502e0d6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -151,6 +151,7 @@ public class MapView extends FrameLayout { private OnMapReadyCallback mMapReadyCallback; private String mStyleUrl; private boolean mInitialLoad; + private boolean mDestroyed; @UiThread public MapView(@NonNull Context context) { @@ -477,6 +478,7 @@ public class MapView extends FrameLayout { */ @UiThread public void onDestroy() { + mDestroyed = true; mNativeMapView.terminateContext(); mNativeMapView.terminateDisplay(); mNativeMapView.destroySurface(); @@ -597,10 +599,16 @@ public class MapView extends FrameLayout { } void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction) { + if (mDestroyed) { + return; + } setDirection(direction, false); } void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction, boolean animated) { + if (mDestroyed) { + return; + } long duration = animated ? MapboxConstants.ANIMATION_DURATION : 0; mNativeMapView.cancelTransitions(); // Out of range directions are normalised in setBearing @@ -608,6 +616,9 @@ public class MapView extends FrameLayout { } void resetNorth() { + if (mDestroyed) { + return; + } mNativeMapView.cancelTransitions(); mNativeMapView.resetNorth(); } @@ -637,22 +648,37 @@ public class MapView extends FrameLayout { // double getZoom() { + if (mDestroyed) { + return 0; + } return mNativeMapView.getZoom(); } void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { + if (mDestroyed) { + return; + } mNativeMapView.setMinZoom(minZoom); } double getMinZoom() { + if (mDestroyed) { + return 0; + } return mNativeMapView.getMinZoom(); } void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { + if (mDestroyed) { + return; + } mNativeMapView.setMaxZoom(maxZoom); } double getMaxZoom() { + if (mDestroyed) { + return 0; + } return mNativeMapView.getMaxZoom(); } @@ -677,14 +703,23 @@ public class MapView extends FrameLayout { // boolean isDebugActive() { + if (mDestroyed) { + return false; + } return mNativeMapView.getDebug(); } void setDebugActive(boolean debugActive) { + if (mDestroyed) { + return; + } mNativeMapView.setDebug(debugActive); } void cycleDebugOptions() { + if (mDestroyed) { + return; + } mNativeMapView.cycleDebugOptions(); } @@ -721,6 +756,9 @@ public class MapView extends FrameLayout { * @see Style */ public void setStyleUrl(@NonNull String url) { + if (mDestroyed) { + return; + } mStyleUrl = url; mNativeMapView.setStyleUrl(url); } @@ -779,6 +817,9 @@ public class MapView extends FrameLayout { */ @UiThread public void setAccessToken(@NonNull String accessToken) { + if (mDestroyed) { + return; + } // validateAccessToken does the null check if (!TextUtils.isEmpty(accessToken)) { accessToken = accessToken.trim(); @@ -795,6 +836,9 @@ public class MapView extends FrameLayout { @UiThread @Nullable public String getAccessToken() { + if (mDestroyed) { + return ""; + } return mNativeMapView.getAccessToken(); } @@ -828,6 +872,9 @@ public class MapView extends FrameLayout { // LatLng fromScreenLocation(@NonNull PointF point) { + if (mDestroyed) { + return new LatLng(); + } float x = point.x; float y = point.y; @@ -835,6 +882,9 @@ public class MapView extends FrameLayout { } PointF toScreenLocation(@NonNull LatLng location) { + if (mDestroyed) { + return new PointF(); + } PointF point = mNativeMapView.pixelForLatLng(location); float x = point.x * mScreenDensity; @@ -866,6 +916,9 @@ public class MapView extends FrameLayout { } void loadIcon(Icon icon) { + if (mDestroyed) { + return; + } Bitmap bitmap = icon.getBitmap(); String id = icon.getId(); if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) { @@ -896,6 +949,9 @@ public class MapView extends FrameLayout { } void updateMarker(@NonNull Marker updatedMarker) { + if (mDestroyed) { + return; + } if (updatedMarker == null) { Log.w(TAG, "marker was null, doing nothing"); return; @@ -937,34 +993,59 @@ public class MapView extends FrameLayout { } long[] addMarkers(@NonNull List markerList) { + if (mDestroyed) { + return new long[]{}; + } return mNativeMapView.addMarkers(markerList); } long addPolyline(@NonNull Polyline polyline) { + if (mDestroyed) { + return 0l; + } return mNativeMapView.addPolyline(polyline); } long[] addPolylines(@NonNull List polylines) { + if (mDestroyed) { + return new long[]{}; + } return mNativeMapView.addPolylines(polylines); } long addPolygon(@NonNull Polygon polygon) { + if (mDestroyed) { + return 0l; + } return mNativeMapView.addPolygon(polygon); } long[] addPolygons(@NonNull List polygons) { + if (mDestroyed) { + return new long[]{}; + } return mNativeMapView.addPolygons(polygons); } void removeAnnotation(long id) { + if (mDestroyed) { + return; + } mNativeMapView.removeAnnotation(id); } void removeAnnotations(@NonNull long[] ids) { + if (mDestroyed) { + return; + } mNativeMapView.removeAnnotations(ids); } private List getMarkersInBounds(@NonNull LatLngBounds bbox) { + if (mDestroyed) { + return new ArrayList<>(); + } + if (bbox == null) { Log.w(TAG, "bbox was null, so just returning null"); return null; @@ -994,7 +1075,7 @@ public class MapView extends FrameLayout { int getTopOffsetPixelsForIcon(Icon icon) { // This method will dead lock if map paused. Causes a freeze if you add a marker in an // activity's onCreate() - if (mNativeMapView.isPaused()) { + if (mDestroyed || mNativeMapView.isPaused()) { return 0; } @@ -1003,6 +1084,10 @@ public class MapView extends FrameLayout { } void setContentPadding(int left, int top, int right, int bottom) { + if (mDestroyed) { + return; + } + if (left == mContentPaddingLeft && top == mContentPaddingTop && right == mContentPaddingRight && bottom == mContentPaddingBottom) { return; } @@ -1016,6 +1101,10 @@ public class MapView extends FrameLayout { } double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) { + if (mDestroyed) { + return 0; + } + return mNativeMapView.getMetersPerPixelAtLatitude(latitude, getZoom()) / mScreenDensity; } @@ -1024,7 +1113,7 @@ public class MapView extends FrameLayout { // void jumpTo(double bearing, LatLng center, double pitch, double zoom) { - if (mNativeMapView == null) { + if (mDestroyed) { return; } mNativeMapView.cancelTransitions(); @@ -1032,7 +1121,7 @@ public class MapView extends FrameLayout { } void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) { - if (mNativeMapView == null) { + if (mDestroyed) { return; } mNativeMapView.cancelTransitions(); @@ -1056,7 +1145,7 @@ public class MapView extends FrameLayout { } void flyTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) { - if (mNativeMapView == null) { + if (mDestroyed) { return; } mNativeMapView.cancelTransitions(); @@ -1100,6 +1189,9 @@ public class MapView extends FrameLayout { } private void reloadMarkers() { + if (mDestroyed) { + return; + } List annotations = mMapboxMap.getAnnotations(); int count = annotations.size(); for (int i = 0; i < count; i++) { @@ -1130,19 +1222,29 @@ public class MapView extends FrameLayout { return; } - if (!mNativeMapView.isPaused()) { - mNativeMapView.renderSync(); + if (mDestroyed || mNativeMapView.isPaused()) { + return; } + + mNativeMapView.renderSync(); } @Override protected void onSizeChanged(int width, int height, int oldw, int oldh) { + if (mDestroyed) { + return; + } + if (!isInEditMode()) { mNativeMapView.resizeView((int) (width / mScreenDensity), (int) (height / mScreenDensity)); } } double getScale() { + if (mDestroyed) { + return 0; + } + return mNativeMapView.getScale(); } @@ -1188,24 +1290,38 @@ public class MapView extends FrameLayout { // Used by UserLocationView void update() { - if (mNativeMapView != null) { - mNativeMapView.update(); + if (mDestroyed) { + return; } + + mNativeMapView.update(); } CameraPosition invalidateCameraPosition() { + if (mDestroyed) { + return new CameraPosition.Builder().build(); + } return new CameraPosition.Builder(mNativeMapView.getCameraValues()).build(); } double getBearing() { + if (mDestroyed) { + return 0; + } return mNativeMapView.getBearing(); } void setBearing(float bearing) { + if (mDestroyed) { + return; + } mNativeMapView.setBearing(bearing); } void setBearing(float bearing, long duration) { + if (mDestroyed) { + return; + } mNativeMapView.setBearing(bearing, duration); } @@ -1248,7 +1364,6 @@ public class MapView extends FrameLayout { * @param yCoordinate Original y screen cooridnate at start of gesture */ private void trackGestureEvent(@NonNull String gestureId, @NonNull float xCoordinate, @NonNull float yCoordinate) { - LatLng tapLatLng = fromScreenLocation(new PointF(xCoordinate, yCoordinate)); Hashtable evt = new Hashtable<>(); @@ -1286,6 +1401,9 @@ public class MapView extends FrameLayout { @Override public boolean onTouchEvent(@NonNull MotionEvent event) { // Check and ignore non touch or left clicks + if (mDestroyed) { + return super.onTouchEvent(event); + } if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) { return false; @@ -1368,7 +1486,7 @@ public class MapView extends FrameLayout { // Called for double taps @Override public boolean onDoubleTapEvent(MotionEvent e) { - if (!mMapboxMap.getUiSettings().isZoomGesturesEnabled()) { + if (mDestroyed || !mMapboxMap.getUiSettings().isZoomGesturesEnabled()) { return false; } @@ -1403,6 +1521,9 @@ public class MapView extends FrameLayout { @Override public boolean onSingleTapUp(MotionEvent e) { + if (mDestroyed) { + return false; + } // Cancel any animation mNativeMapView.cancelTransitions(); return true; @@ -1474,7 +1595,6 @@ public class MapView extends FrameLayout { } trackGestureEvent(MapboxEvent.GESTURE_SINGLETAP, e.getX(), e.getY()); - return true; } @@ -1490,9 +1610,8 @@ public class MapView extends FrameLayout { // Called for flings @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - if (!mMapboxMap.getUiSettings().isScrollGesturesEnabled()) { + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (mDestroyed || !mMapboxMap.getUiSettings().isScrollGesturesEnabled()) { return false; } @@ -1531,7 +1650,7 @@ public class MapView extends FrameLayout { if (!mScrollInProgress) { mScrollInProgress = true; } - if (!mMapboxMap.getUiSettings().isScrollGesturesEnabled()) { + if (mDestroyed || !mMapboxMap.getUiSettings().isScrollGesturesEnabled()) { return false; } @@ -1563,7 +1682,7 @@ public class MapView extends FrameLayout { // Called when two fingers first touch the screen @Override public boolean onScaleBegin(ScaleGestureDetector detector) { - if (!mMapboxMap.getUiSettings().isZoomGesturesEnabled()) { + if (mDestroyed || !mMapboxMap.getUiSettings().isZoomGesturesEnabled()) { return false; } @@ -1590,8 +1709,8 @@ public class MapView extends FrameLayout { @Override public boolean onScale(ScaleGestureDetector detector) { UiSettings uiSettings = mMapboxMap.getUiSettings(); - if (!uiSettings.isZoomGesturesEnabled()) { - return false; + if (mDestroyed || !uiSettings.isZoomGesturesEnabled()) { + return super.onScale(detector); } // If scale is large enough ignore a tap @@ -1648,7 +1767,7 @@ public class MapView extends FrameLayout { // Called when two fingers first touch the screen @Override public boolean onRotateBegin(RotateGestureDetector detector) { - if (!mMapboxMap.getUiSettings().isRotateGesturesEnabled()) { + if (mDestroyed || !mMapboxMap.getUiSettings().isRotateGesturesEnabled()) { return false; } @@ -1674,7 +1793,7 @@ public class MapView extends FrameLayout { // Called for rotation @Override public boolean onRotate(RotateGestureDetector detector) { - if (!mMapboxMap.getUiSettings().isRotateGesturesEnabled()) { + if (mDestroyed || !mMapboxMap.getUiSettings().isRotateGesturesEnabled()) { return false; } @@ -1752,7 +1871,7 @@ public class MapView extends FrameLayout { @Override public boolean onShove(ShoveGestureDetector detector) { - if (!mMapboxMap.getUiSettings().isTiltGesturesEnabled()) { + if (mDestroyed || !mMapboxMap.getUiSettings().isTiltGesturesEnabled()) { return false; } @@ -1818,6 +1937,10 @@ public class MapView extends FrameLayout { // down @Override public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { + if (mDestroyed) { + return super.onKeyDown(keyCode, event); + } + // If the user has held the scroll key down for a while then accelerate // the scroll speed double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0; @@ -1941,6 +2064,9 @@ public class MapView extends FrameLayout { // units @Override public boolean onTrackballEvent(MotionEvent event) { + if (mDestroyed) { + return false; + } // Choose the action switch (event.getActionMasked()) { // The trackball was rotated @@ -2031,6 +2157,9 @@ public class MapView extends FrameLayout { // such as mouse scroll events, mouse moves, joystick, trackpad @Override public boolean onGenericMotionEvent(MotionEvent event) { + if (mDestroyed) { + return false; + } // Mouse events //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) { @@ -2107,8 +2236,8 @@ public class MapView extends FrameLayout { // Called when MapView is being created private boolean isConnected() { - ConnectivityManager connectivityManager = (ConnectivityManager) getContext().getApplicationContext() - .getSystemService(Context.CONNECTIVITY_SERVICE); + Context appContext = getContext().getApplicationContext(); + ConnectivityManager connectivityManager = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); return (activeNetwork != null) && activeNetwork.isConnectedOrConnecting(); } @@ -2273,16 +2402,25 @@ public class MapView extends FrameLayout { @UiThread void addCustomLayer(CustomLayer customLayer, String before) { + if (mDestroyed) { + return; + } mNativeMapView.addCustomLayer(customLayer, before); } @UiThread void removeCustomLayer(String id) { + if (mDestroyed) { + return; + } mNativeMapView.removeCustomLayer(id); } @UiThread void invalidateCustomLayers() { + if (mDestroyed) { + return; + } mNativeMapView.update(); } @@ -2406,7 +2544,6 @@ public class MapView extends FrameLayout { } } - /** * Definition of a map change event. * @@ -2576,7 +2713,6 @@ public class MapView extends FrameLayout { */ public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13; - /** * Interface definition for a callback to be invoked when the displayed map view changes. * @@ -2605,5 +2741,4 @@ public class MapView extends FrameLayout { void onMapChanged(@MapChange int change); } - } -- cgit v1.2.1