[android] - safe guard making asyncrhonous calls to map object while it's beeing destroyed (#7613)

This commit is contained in:
Tobrun
2017-01-16 09:06:29 +01:00
committed by GitHub
parent 9a635672a6
commit 5c61ea0869

View File

@@ -9,6 +9,7 @@ import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Surface;
@@ -16,6 +17,7 @@ import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.offline.OfflineManager;
@@ -102,6 +104,15 @@ final class NativeMapView {
// Methods
//
private boolean isDestroyedOn(String callingMethod) {
if (destroyed && !TextUtils.isEmpty(callingMethod)) {
Timber.e(String.format(MapboxConstants.MAPBOX_LOCALE,
"You're calling `%s` after the `MapView` was destroyed, were you invoking it after `onDestroy()`?",
callingMethod));
}
return destroyed;
}
public void destroy() {
nativeDestroy(nativeMapViewPtr);
nativeMapViewPtr = 0;
@@ -109,43 +120,66 @@ final class NativeMapView {
destroyed = true;
}
public boolean wasDestroyed() {
return destroyed;
}
public void initializeDisplay() {
if (isDestroyedOn("initializeDisplay")) {
return;
}
nativeInitializeDisplay(nativeMapViewPtr);
}
public void terminateDisplay() {
if (isDestroyedOn("terminateDisplay")) {
return;
}
nativeTerminateDisplay(nativeMapViewPtr);
}
public void initializeContext() {
if (isDestroyedOn("initializeContext")) {
return;
}
nativeInitializeContext(nativeMapViewPtr);
}
public void terminateContext() {
if (isDestroyedOn("terminateContext")) {
return;
}
nativeTerminateContext(nativeMapViewPtr);
}
public void createSurface(Surface surface) {
if (isDestroyedOn("createSurface")) {
return;
}
nativeCreateSurface(nativeMapViewPtr, surface);
}
public void destroySurface() {
if (isDestroyedOn("destroySurface")) {
return;
}
nativeDestroySurface(nativeMapViewPtr);
}
public void update() {
if (isDestroyedOn("update")) {
return;
}
nativeUpdate(nativeMapViewPtr);
}
public void render() {
if (isDestroyedOn("render")) {
return;
}
nativeRender(nativeMapViewPtr);
}
public void resizeView(int width, int height) {
if (isDestroyedOn("resizeView")) {
return;
}
width = (int) (width / pixelRatio);
height = (int) (height / pixelRatio);
@@ -174,6 +208,9 @@ final class NativeMapView {
}
public void resizeFramebuffer(int fbWidth, int fbHeight) {
if (isDestroyedOn("resizeFramebuffer")) {
return;
}
if (fbWidth < 0) {
throw new IllegalArgumentException("fbWidth cannot be negative.");
}
@@ -195,159 +232,276 @@ final class NativeMapView {
}
public void addClass(String clazz) {
if (isDestroyedOn("addClass")) {
return;
}
nativeAddClass(nativeMapViewPtr, clazz);
}
public void removeClass(String clazz) {
if (isDestroyedOn("removeClass")) {
return;
}
nativeRemoveClass(nativeMapViewPtr, clazz);
}
public boolean hasClass(String clazz) {
if (isDestroyedOn("hasClass")) {
return false;
}
return nativeHasClass(nativeMapViewPtr, clazz);
}
public void setClasses(List<String> classes) {
if (isDestroyedOn("setClasses")) {
return;
}
nativeSetClasses(nativeMapViewPtr, classes);
}
public List<String> getClasses() {
if (isDestroyedOn("getClasses")) {
return new ArrayList<>();
}
return nativeGetClasses(nativeMapViewPtr);
}
public void setStyleUrl(String url) {
if (isDestroyedOn("setStyleUrl")) {
return;
}
nativeSetStyleUrl(nativeMapViewPtr, url);
}
public String getStyleUrl() {
if (isDestroyedOn("getStyleUrl")) {
return null;
}
return nativeGetStyleUrl(nativeMapViewPtr);
}
public void setStyleJson(String newStyleJson) {
if (isDestroyedOn("setStyleJson")) {
return;
}
nativeSetStyleJson(nativeMapViewPtr, newStyleJson);
}
public String getStyleJson() {
if (isDestroyedOn("getStyleJson")) {
return null;
}
return nativeGetStyleJson(nativeMapViewPtr);
}
public void setAccessToken(String accessToken) {
if (isDestroyedOn("setAccessToken")) {
return;
}
nativeSetAccessToken(nativeMapViewPtr, accessToken);
}
public String getAccessToken() {
if (isDestroyedOn("getAccessToken")) {
return null;
}
return nativeGetAccessToken(nativeMapViewPtr);
}
public void cancelTransitions() {
if (isDestroyedOn("cancelTransitions")) {
return;
}
nativeCancelTransitions(nativeMapViewPtr);
}
public void setGestureInProgress(boolean inProgress) {
if (isDestroyedOn("setGestureInProgress")) {
return;
}
nativeSetGestureInProgress(nativeMapViewPtr, inProgress);
}
public void moveBy(double dx, double dy) {
if (isDestroyedOn("moveBy")) {
return;
}
moveBy(dx, dy, 0);
}
public void moveBy(double dx, double dy, long duration) {
if (isDestroyedOn("moveBy")) {
return;
}
nativeMoveBy(nativeMapViewPtr, dx / pixelRatio, dy / pixelRatio, duration);
}
public void setLatLng(LatLng latLng) {
if (isDestroyedOn("setLatLng")) {
return;
}
setLatLng(latLng, 0);
}
public void setLatLng(LatLng latLng, long duration) {
if (isDestroyedOn("setLatLng")) {
return;
}
nativeSetLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude(), duration);
}
public LatLng getLatLng() {
if (isDestroyedOn("")) {
return new LatLng();
}
return nativeGetLatLng(nativeMapViewPtr);
}
public void resetPosition() {
if (isDestroyedOn("resetPosition")) {
return;
}
nativeResetPosition(nativeMapViewPtr);
}
public double getPitch() {
if (isDestroyedOn("getPitch")) {
return 0;
}
return nativeGetPitch(nativeMapViewPtr);
}
public void setPitch(double pitch, long duration) {
if (isDestroyedOn("setPitch")) {
return;
}
nativeSetPitch(nativeMapViewPtr, pitch, duration);
}
public void scaleBy(double ds) {
if (isDestroyedOn("scaleBy")) {
return;
}
scaleBy(ds, Double.NaN, Double.NaN);
}
public void scaleBy(double ds, double cx, double cy) {
if (isDestroyedOn("scaleBy")) {
return;
}
scaleBy(ds, cx, cy, 0);
}
public void scaleBy(double ds, double cx, double cy, long duration) {
if (isDestroyedOn("scaleBy")) {
return;
}
nativeScaleBy(nativeMapViewPtr, ds, cx / pixelRatio, cy / pixelRatio, duration);
}
public void setScale(double scale) {
if (isDestroyedOn("setScale")) {
return;
}
setScale(scale, Double.NaN, Double.NaN);
}
public void setScale(double scale, double cx, double cy) {
if (isDestroyedOn("setScale")) {
return;
}
setScale(scale, cx, cy, 0);
}
public void setScale(double scale, double cx, double cy, long duration) {
if (isDestroyedOn("setScale")) {
return;
}
nativeSetScale(nativeMapViewPtr, scale, cx / pixelRatio, cy / pixelRatio, duration);
}
public double getScale() {
if (isDestroyedOn("getScale")) {
return 0;
}
return nativeGetScale(nativeMapViewPtr);
}
public void setZoom(double zoom) {
if (isDestroyedOn("setZoom")) {
return;
}
setZoom(zoom, 0);
}
public void setZoom(double zoom, long duration) {
if (isDestroyedOn("setZoom")) {
return;
}
nativeSetZoom(nativeMapViewPtr, zoom, duration);
}
public double getZoom() {
if (isDestroyedOn("getZoom")) {
return 0;
}
return nativeGetZoom(nativeMapViewPtr);
}
public void resetZoom() {
if (isDestroyedOn("resetZoom")) {
return;
}
nativeResetZoom(nativeMapViewPtr);
}
public void setMinZoom(double zoom) {
if (isDestroyedOn("setMinZoom")) {
return;
}
nativeSetMinZoom(nativeMapViewPtr, zoom);
}
public double getMinZoom() {
if (isDestroyedOn("getMinZoom")) {
return 0;
}
return nativeGetMinZoom(nativeMapViewPtr);
}
public void setMaxZoom(double zoom) {
if (isDestroyedOn("setMaxZoom")) {
return;
}
nativeSetMaxZoom(nativeMapViewPtr, zoom);
}
public double getMaxZoom() {
if (isDestroyedOn("getMaxZoom")) {
return 0;
}
return nativeGetMaxZoom(nativeMapViewPtr);
}
public void rotateBy(double sx, double sy, double ex, double ey) {
if (isDestroyedOn("rotateBy")) {
return;
}
rotateBy(sx, sy, ex, ey, 0);
}
public void rotateBy(double sx, double sy, double ex, double ey,
long duration) {
if (isDestroyedOn("rotateBy")) {
return;
}
nativeRotateBy(nativeMapViewPtr, sx / pixelRatio, sy / pixelRatio, ex, ey, duration);
}
public void setContentPadding(int[] padding) {
if (isDestroyedOn("setContentPadding")) {
return;
}
nativeSetContentPadding(nativeMapViewPtr,
padding[1] / pixelRatio,
padding[0] / pixelRatio,
@@ -356,191 +510,323 @@ final class NativeMapView {
}
public void setBearing(double degrees) {
if (isDestroyedOn("setBearing")) {
return;
}
setBearing(degrees, 0);
}
public void setBearing(double degrees, long duration) {
if (isDestroyedOn("setBearing")) {
return;
}
nativeSetBearing(nativeMapViewPtr, degrees, duration);
}
public void setBearing(double degrees, double cx, double cy) {
if (isDestroyedOn("setBearing")) {
return;
}
nativeSetBearingXY(nativeMapViewPtr, degrees, cx / pixelRatio, cy / pixelRatio);
}
public double getBearing() {
if (isDestroyedOn("getBearing")) {
return 0;
}
return nativeGetBearing(nativeMapViewPtr);
}
public void resetNorth() {
if (isDestroyedOn("resetNorth")) {
return;
}
nativeResetNorth(nativeMapViewPtr);
}
public long addMarker(Marker marker) {
if (isDestroyedOn("addMarker")) {
return 0;
}
Marker[] markers = {marker};
return nativeAddMarkers(nativeMapViewPtr, markers)[0];
}
public long[] addMarkers(List<Marker> markers) {
if (isDestroyedOn("addMarkers")) {
return new long[] {};
}
return nativeAddMarkers(nativeMapViewPtr, markers.toArray(new Marker[markers.size()]));
}
public long addPolyline(Polyline polyline) {
if (isDestroyedOn("addPolyline")) {
return 0;
}
Polyline[] polylines = {polyline};
return nativeAddPolylines(nativeMapViewPtr, polylines)[0];
}
public long[] addPolylines(List<Polyline> polylines) {
if (isDestroyedOn("addPolylines")) {
return new long[] {};
}
return nativeAddPolylines(nativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()]));
}
public long addPolygon(Polygon polygon) {
if (isDestroyedOn("addPolygon")) {
return 0;
}
Polygon[] polygons = {polygon};
return nativeAddPolygons(nativeMapViewPtr, polygons)[0];
}
public long[] addPolygons(List<Polygon> polygons) {
if (isDestroyedOn("addPolygons")) {
return new long[] {};
}
return nativeAddPolygons(nativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()]));
}
public void updateMarker(Marker marker) {
if (isDestroyedOn("updateMarker")) {
return;
}
LatLng position = marker.getPosition();
Icon icon = marker.getIcon();
nativeUpdateMarker(nativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId());
}
public void updatePolygon(Polygon polygon) {
if (isDestroyedOn("updatePolygon")) {
return;
}
nativeUpdatePolygon(nativeMapViewPtr, polygon.getId(), polygon);
}
public void updatePolyline(Polyline polyline) {
if (isDestroyedOn("updatePolyline")) {
return;
}
nativeUpdatePolyline(nativeMapViewPtr, polyline.getId(), polyline);
}
public void removeAnnotation(long id) {
if (isDestroyedOn("removeAnnotation")) {
return;
}
long[] ids = {id};
removeAnnotations(ids);
}
public void removeAnnotations(long[] ids) {
if (isDestroyedOn("removeAnnotations")) {
return;
}
nativeRemoveAnnotations(nativeMapViewPtr, ids);
}
public long[] queryPointAnnotations(RectF rect) {
if (isDestroyedOn("queryPointAnnotations")) {
return new long[] {};
}
return nativeQueryPointAnnotations(nativeMapViewPtr, rect);
}
public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) {
if (isDestroyedOn("addAnnotationIcon")) {
return;
}
nativeAddAnnotationIcon(nativeMapViewPtr, symbol, width, height, scale, pixels);
}
public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) {
if (isDestroyedOn("setVisibleCoordinateBounds")) {
return;
}
nativeSetVisibleCoordinateBounds(nativeMapViewPtr, coordinates, padding, direction, duration);
}
public void onLowMemory() {
if (isDestroyedOn("onLowMemory")) {
return;
}
nativeOnLowMemory(nativeMapViewPtr);
}
public void setDebug(boolean debug) {
if (isDestroyedOn("setDebug")) {
return;
}
nativeSetDebug(nativeMapViewPtr, debug);
}
public void cycleDebugOptions() {
if (isDestroyedOn("cycleDebugOptions")) {
return;
}
nativeToggleDebug(nativeMapViewPtr);
}
public boolean getDebug() {
if (isDestroyedOn("getDebug")) {
return false;
}
return nativeGetDebug(nativeMapViewPtr);
}
public boolean isFullyLoaded() {
if (isDestroyedOn("isFullyLoaded")) {
return false;
}
return nativeIsFullyLoaded(nativeMapViewPtr);
}
public void setReachability(boolean status) {
if (isDestroyedOn("setReachability")) {
return;
}
nativeSetReachability(nativeMapViewPtr, status);
}
public double getMetersPerPixelAtLatitude(double lat) {
if (isDestroyedOn("getMetersPerPixelAtLatitude")) {
return 0;
}
return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, getZoom());
}
public ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
if (isDestroyedOn("projectedMetersForLatLng")) {
return null;
}
return nativeProjectedMetersForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
}
public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) {
if (isDestroyedOn("latLngForProjectedMeters")) {
return new LatLng();
}
return nativeLatLngForProjectedMeters(nativeMapViewPtr, projectedMeters.getNorthing(),
projectedMeters.getEasting());
}
public PointF pixelForLatLng(LatLng latLng) {
if (isDestroyedOn("pixelForLatLng")) {
return new PointF();
}
PointF pointF = nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio);
return pointF;
}
public LatLng latLngForPixel(PointF pixel) {
if (isDestroyedOn("latLngForPixel")) {
return new LatLng();
}
return nativeLatLngForPixel(nativeMapViewPtr, pixel.x / pixelRatio, pixel.y / pixelRatio);
}
public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) {
if (isDestroyedOn("getTopOffsetPixelsForAnnotationSymbol")) {
return 0;
}
return nativeGetTopOffsetPixelsForAnnotationSymbol(nativeMapViewPtr, symbolName);
}
public void jumpTo(double angle, LatLng center, double pitch, double zoom) {
if (isDestroyedOn("jumpTo")) {
return;
}
nativeJumpTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), pitch, zoom);
}
public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom,
boolean easingInterpolator) {
if (isDestroyedOn("easeTo")) {
return;
}
nativeEaseTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom,
easingInterpolator);
}
public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) {
if (isDestroyedOn("flyTo")) {
return;
}
nativeFlyTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom);
}
public double[] getCameraValues() {
if (isDestroyedOn("getCameraValues")) {
return new double[] {};
}
return nativeGetCameraValues(nativeMapViewPtr);
}
// Runtime style Api
public Layer getLayer(String layerId) {
if (isDestroyedOn("getLayer")) {
return null;
}
return nativeGetLayer(nativeMapViewPtr, layerId);
}
public void addLayer(@NonNull Layer layer, @Nullable String before) {
if (isDestroyedOn("")) {
return;
}
nativeAddLayer(nativeMapViewPtr, layer.getNativePtr(), before);
}
public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
if (isDestroyedOn("removeLayer")) {
return;
}
nativeRemoveLayerById(nativeMapViewPtr, layerId);
}
public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException {
if (isDestroyedOn("removeLayer")) {
return;
}
nativeRemoveLayer(nativeMapViewPtr, layer.getNativePtr());
}
public Source getSource(@NonNull String sourceId) {
if (isDestroyedOn("getSource")) {
return null;
}
return nativeGetSource(nativeMapViewPtr, sourceId);
}
public void addSource(@NonNull Source source) {
if (isDestroyedOn("addSource")) {
return;
}
nativeAddSource(nativeMapViewPtr, source.getNativePtr());
}
public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
if (isDestroyedOn("removeSource")) {
return;
}
nativeRemoveSourceById(nativeMapViewPtr, sourceId);
}
public void removeSource(@NonNull Source source) throws NoSuchSourceException {
if (isDestroyedOn("removeSource")) {
return;
}
nativeRemoveSource(nativeMapViewPtr, source.getNativePtr());
}
public void addImage(@NonNull String name, @NonNull Bitmap image) {
if (isDestroyedOn("addImage")) {
return;
}
//Check/correct config
if (image.getConfig() != Bitmap.Config.ARGB_8888) {
image = image.copy(Bitmap.Config.ARGB_8888, false);
@@ -558,6 +844,9 @@ final class NativeMapView {
}
public void removeImage(String name) {
if (isDestroyedOn("removeImage")) {
return;
}
nativeRemoveImage(nativeMapViewPtr, name);
}
@@ -565,6 +854,9 @@ final class NativeMapView {
@NonNull
public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
if (isDestroyedOn("queryRenderedFeatures")) {
return new ArrayList<>();
}
Feature[] features = nativeQueryRenderedFeaturesForPoint(nativeMapViewPtr, coordinates.x / pixelRatio,
coordinates.y / pixelRatio, layerIds);
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
@@ -572,6 +864,9 @@ final class NativeMapView {
@NonNull
public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
if (isDestroyedOn("queryRenderedFeatures")) {
return new ArrayList<>();
}
Feature[] features = nativeQueryRenderedFeaturesForBox(
nativeMapViewPtr,
coordinates.left / pixelRatio,
@@ -583,10 +878,16 @@ final class NativeMapView {
}
public void scheduleTakeSnapshot() {
if (isDestroyedOn("scheduleTakeSnapshot")) {
return;
}
nativeScheduleTakeSnapshot(nativeMapViewPtr);
}
public void setApiBaseUrl(String baseUrl) {
if (isDestroyedOn("setApiBaseUrl")) {
return;
}
nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl);
}
@@ -833,10 +1134,16 @@ final class NativeMapView {
private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl);
int getWidth() {
if (isDestroyedOn("")) {
return 0;
}
return mapView.getWidth();
}
int getHeight() {
if (isDestroyedOn("")) {
return 0;
}
return mapView.getHeight();
}