diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb33f7ca..e3b07dd32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,62 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. ## master + +### Performance improvements + - Improved rendering performance for the styles with multiple sources [#15756](https://github.com/mapbox/mapbox-gl-native/pull/15756) + +## 8.5.0-alpha.1 - October 3, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.4.0...android-v8.5.0-alpha.1) since [Mapbox Maps SDK for Android v8.4.0](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.4.0): +### Bug fixes + - Suppress network requests for expired tiles update, if these tiles are invisible. [#15741](https://github.com/mapbox/mapbox-gl-native/pull/15741) + - Fixed opacity interpolation for composition expressions [#15738](https://github.com/mapbox/mapbox-gl-native/pull/15738) + - Fixed an issue where `Projection#getMetersPerPixelAtLatitude` returned a value incorrectly divided by the pixel ratio. This also fixes an issue where `LocationComponent` accuracy circle's radius was artificially increased. [#15742](https://github.com/mapbox/mapbox-gl-native/pull/15742) + +## 8.4.0 - September 25, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.4.0-beta.1...android-v8.4.0) since [Mapbox Maps SDK for Android v8.4.0-beta.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.4.0-beta.1): + +### Bug fixes + - Fixing a crash when `CameraPosition` padding is set when using `MapSnapshotter`. [#15699](https://github.com/mapbox/mapbox-gl-native/pull/15699) + +### Other Changes + - Bumped Java SDK dependency to stable 4.9.0 [#15700](https://github.com/mapbox/mapbox-gl-native/pull/15700) + - Migrate map feedback to GL JS–powered feedback form [#15623](https://github.com/mapbox/mapbox-gl-native/pull/15623) + +## 8.4.0-beta.1 - September 19, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.4.0-alpha.2...android-v8.4.0-beta.1) since [Mapbox Maps SDK for Android v8.4.0-alpha.2](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.4.0-alpha.2): + +### Bug fixes + - Fixed an issue that `maxzoom` in style `Sources` option was ignored when URL resource is provided. It may cause problems such as extra tiles downloading at higher zoom level than `maxzoom`, or problems that wrong setting of `overscaledZ` in `OverscaledTileID` that will be passed to `SymbolLayout`, leading wrong rendering appearance. [#15581](https://github.com/mapbox/mapbox-gl-native/pull/15581) + - Fixed constant repainting for the sources with invisible layers, caused by `RenderSource::hasFadingTiles()` returning `true` all the time. [#15600](https://github.com/mapbox/mapbox-gl-native/pull/15600) + - Fixed an issue that caused the state of CompassView not up to date when `UiSettings.setCompassEnabled()` is set to true. [#15606](https://github.com/mapbox/mapbox-gl-native/pull/15606) + - Ignore location tracking mode based animations when the camera is transitioning. [#15641](https://github.com/mapbox/mapbox-gl-native/pull/15641) + - Fixed MapSnapshotter so that `MapSnapshotter.withApiBaseUri` works again. [#15642](https://github.com/mapbox/mapbox-gl-native/pull/15642) + - Fixed an assertion hit caused by possibility of adding a layer to an incompatible source. [#15644](https://github.com/mapbox/mapbox-gl-native/pull/15644) + +## 8.3.2 - September 19, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.3.1...android-v8.3.2) since [Mapbox Maps SDK for Android v8.3.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.3.1): + ### Bug fixes - Fixed an issue of integer overflow when converting `tileCoordinates` to `LatLon`, which caused issues such as `queryRenderedFeatures` and `querySourceFeatures` returning incorrect coordinates at zoom levels 20 and higher. [#15560](https://github.com/mapbox/mapbox-gl-native/pull/15560) + +## 8.3.1 - September 18, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.3.0...android-v8.3.1) since [Mapbox Maps SDK for Android v8.3.0](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.3.0): + +### Bug fixes + - Updated earcut.hpp submodule file [#15660](https://github.com/mapbox/mapbox-gl-native/pull/15660) + - Fixed a wrong variable assignment of `MapSnapshotter.Options.withApiBaseUri`. [#15642](https://github.com/mapbox/mapbox-gl-native/pull/15642) + +## 8.4.0-alpha.2 - September 11, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.4.0-alpha.1...android-v8.4.0-alpha.2) since [Mapbox Maps SDK for Android v8.4.0-alpha.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.4.0-alpha.1): + +### Performance improvements + - Newly loaded labels appear faster on the screen. [#15308](https://github.com/mapbox/mapbox-gl-native/pull/15308) + +### Bug fixes + - Fixed an issue of integer overflow when converting `tileCoordinates` to `LatLon`, which caused issues such as `queryRenderedFeatures` and `querySourceFeatures` returning incorrect coordinates at zoom levels 20 and higher. [#15560](https://github.com/mapbox/mapbox-gl-native/pull/15560) + +### Other Changes + - Bumped Java SDK dependency to 4.9.0-alpha.1 [#15570](https://github.com/mapbox/mapbox-gl-native/pull/15570) ## 8.4.0-alpha.1 - September 4, 2019 [Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.3.0...android-v8.4.0-alpha.1) since [Mapbox Maps SDK for Android v8.3.0](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.3.0): diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java index 01c82ddad..35f7a5975 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java @@ -2,6 +2,8 @@ package com.mapbox.mapboxsdk; import android.annotation.SuppressLint; import android.content.Context; +import android.content.res.AssetManager; +import android.support.annotation.Keep; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; @@ -24,6 +26,7 @@ import com.mapbox.mapboxsdk.utils.ThreadUtils; */ @UiThread @SuppressLint("StaticFieldLeak") +@Keep public final class Mapbox { private static final String TAG = "Mbgl-Mapbox"; @@ -222,4 +225,13 @@ public final class Mapbox { public static boolean hasInstance() { return INSTANCE != null; } + + /** + * Internal use. Returns AssetManager. + * + * @return the asset manager + */ + private static AssetManager getAssetManager() { + return getApplicationContext().getResources().getAssets(); + } } \ No newline at end of file diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java index 46de3673e..8b014b0e9 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java @@ -726,6 +726,10 @@ public final class LocationComponent { * If you are not using any of {@link CameraMode} modes, * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + *

+ * If the camera is transitioning when the zoom change is requested, the call is going to be ignored. + * Use {@link CameraTransitionListener} to chain the animations, or provide the zoom as a camera change argument. + *

* * @param zoomLevel The desired zoom level. * @param animationDuration The zoom animation duration. @@ -741,6 +745,10 @@ public final class LocationComponent { "LocationComponent#zoomWhileTracking method can only be used", " when a camera mode other than CameraMode#NONE is engaged.")); return; + } else if (locationCameraController.isTransitioning()) { + Logger.e(TAG, + "LocationComponent#zoomWhileTracking method call is ignored because the camera mode is transitioning"); + return; } locationAnimatorCoordinator.feedNewZoomLevel(zoomLevel, mapboxMap.getCameraPosition(), animationDuration, callback); } @@ -751,6 +759,10 @@ public final class LocationComponent { * If you are not using any of {@link CameraMode} modes, * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + *

+ * If the camera is transitioning when the zoom change is requested, the call is going to be ignored. + * Use {@link CameraTransitionListener} to chain the animations, or provide the zoom as a camera change argument. + *

* * @param zoomLevel The desired zoom level. * @param animationDuration The zoom animation duration. @@ -766,6 +778,10 @@ public final class LocationComponent { * If you are not using any of {@link CameraMode} modes, * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + *

+ * If the camera is transitioning when the zoom change is requested, the call is going to be ignored. + * Use {@link CameraTransitionListener} to chain the animations, or provide the zoom as a camera change argument. + *

* * @param zoomLevel The desired zoom level. */ @@ -788,6 +804,10 @@ public final class LocationComponent { * If you are not using any of {@link CameraMode} modes, * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + *

+ * If the camera is transitioning when the tilt change is requested, the call is going to be ignored. + * Use {@link CameraTransitionListener} to chain the animations, or provide the tilt as a camera change argument. + *

* * @param tilt The desired camera tilt. * @param animationDuration The tilt animation duration. @@ -803,6 +823,10 @@ public final class LocationComponent { "LocationComponent#tiltWhileTracking method can only be used", " when a camera mode other than CameraMode#NONE is engaged.")); return; + } else if (locationCameraController.isTransitioning()) { + Logger.e(TAG, + "LocationComponent#tiltWhileTracking method call is ignored because the camera mode is transitioning"); + return; } locationAnimatorCoordinator.feedNewTilt(tilt, mapboxMap.getCameraPosition(), animationDuration, callback); } @@ -813,6 +837,10 @@ public final class LocationComponent { * If you are not using any of {@link CameraMode} modes, * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + *

+ * If the camera is transitioning when the tilt change is requested, the call is going to be ignored. + * Use {@link CameraTransitionListener} to chain the animations, or provide the tilt as a camera change argument. + *

* * @param tilt The desired camera tilt. * @param animationDuration The tilt animation duration. @@ -828,6 +856,10 @@ public final class LocationComponent { * If you are not using any of {@link CameraMode} modes, * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + *

+ * If the camera is transitioning when the tilt change is requested, the call is going to be ignored. + * Use {@link CameraTransitionListener} to chain the animations, or provide the tilt as a camera change argument. + *

* * @param tilt The desired camera tilt. */ diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java index 4f523948d..5384a29fc 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java @@ -26,6 +26,8 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Responsible for managing attribution interactions on the map. @@ -36,9 +38,10 @@ import java.util.Set; *

*/ public class AttributionDialogManager implements View.OnClickListener, DialogInterface.OnClickListener { - private static final String MAP_FEEDBACK_URL = "https://apps.mapbox.com/feedback"; - private static final String MAP_FEEDBACK_LOCATION_FORMAT = MAP_FEEDBACK_URL + "/#/%f/%f/%d"; + private static final String MAP_FEEDBACK_URL_OLD = "https://www.mapbox.com/map-feedback"; + private static final String MAP_FEEDBACK_URL_LOCATION_FRAGMENT_FORMAT = "/%f/%f/%f/%f/%d"; + private static final String MAP_FEEDBACK_STYLE_URI_REGEX = "^(.*://[^:^/]*)/(.*)/(.*)"; @NonNull private final Context context; @@ -90,7 +93,7 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt if (isLatestEntry(which)) { showTelemetryDialog(); } else { - showMapFeedbackWebPage(which); + showMapAttributionWebPage(which); } } @@ -138,21 +141,54 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt builder.show(); } - private void showMapFeedbackWebPage(int which) { + private void showMapAttributionWebPage(int which) { Attribution[] attributions = attributionSet.toArray(new Attribution[attributionSet.size()]); String url = attributions[which].getUrl(); - if (url.contains(MAP_FEEDBACK_URL)) { - url = buildMapFeedbackMapUrl(mapboxMap.getCameraPosition()); + if (url.contains(MAP_FEEDBACK_URL_OLD) || url.contains(MAP_FEEDBACK_URL)) { + url = buildMapFeedbackMapUrl(Mapbox.getAccessToken()); } showWebPage(url); } @NonNull - private String buildMapFeedbackMapUrl(@Nullable CameraPosition cameraPosition) { - // appends current location to the map feedback url if available - return cameraPosition != null ? String.format(Locale.getDefault(), - MAP_FEEDBACK_LOCATION_FORMAT, cameraPosition.target.getLongitude(), cameraPosition.target.getLatitude(), - (int) cameraPosition.zoom) : MAP_FEEDBACK_URL; + String buildMapFeedbackMapUrl(@Nullable String accessToken) { + // TODO Add Android Maps SDK version to the query parameter, currently the version API is not available. + // TODO Keep track of this issue at [#15632](https://github.com/mapbox/mapbox-gl-native/issues/15632) + + Uri.Builder builder = Uri.parse(MAP_FEEDBACK_URL).buildUpon(); + + CameraPosition cameraPosition = mapboxMap.getCameraPosition(); + if (cameraPosition != null) { + builder.encodedFragment(String.format(Locale.getDefault(), MAP_FEEDBACK_URL_LOCATION_FRAGMENT_FORMAT, + cameraPosition.target.getLongitude(), cameraPosition.target.getLatitude(), + cameraPosition.zoom, cameraPosition.bearing, (int) cameraPosition.tilt)); + } + + String packageName = context.getApplicationContext().getPackageName(); + if (packageName != null) { + builder.appendQueryParameter("referrer", packageName); + } + + if (accessToken != null) { + builder.appendQueryParameter("access_token", accessToken); + } + + Style style = mapboxMap.getStyle(); + if (style != null) { + String styleUri = style.getUri(); + Pattern pattern = Pattern.compile(MAP_FEEDBACK_STYLE_URI_REGEX); + Matcher matcher = pattern.matcher(styleUri); + + if (matcher.find()) { + String styleOwner = matcher.group(2); + String styleId = matcher.group(3); + + builder.appendQueryParameter("owner", styleOwner) + .appendQueryParameter("id", styleId); + } + } + + return builder.build().toString(); } private void showWebPage(@NonNull String url) { @@ -189,10 +225,10 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt Style style = mapboxMap.getStyle(); if (style != null) { - for (Source source : mapboxMap.getStyle().getSources()) { + for (Source source : style.getSources()) { attribution = source.getAttribution(); if (!attribution.isEmpty()) { - attributions.add(source.getAttribution()); + attributions.add(attribution); } } } diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index acd5093da..8f4cb9438 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -6,6 +6,7 @@ import android.graphics.PointF; import android.graphics.RectF; import android.os.Bundle; import android.support.annotation.FloatRange; +import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.Size; @@ -246,12 +247,16 @@ public final class MapboxMap { // Style /** - * Sets tile pre-fetching from MapboxOptions. + * Sets tile pre-fetching zoom delta from MapboxOptions. * * @param options the options object */ private void setPrefetchesTiles(@NonNull MapboxMapOptions options) { - setPrefetchesTiles(options.getPrefetchesTiles()); + if (!options.getPrefetchesTiles()) { + setPrefetchZoomDelta(0); + } else { + setPrefetchZoomDelta(options.getPrefetchZoomDelta()); + } } /** @@ -259,7 +264,9 @@ public final class MapboxMap { * tile is rendered as soon as possible at the expense of a little bandwidth. * * @param enable true to enable + * @deprecated Use {@link #setPrefetchZoomDelta(int)} instead. */ + @Deprecated public void setPrefetchesTiles(boolean enable) { nativeMapView.setPrefetchTiles(enable); } @@ -269,11 +276,38 @@ public final class MapboxMap { * * @return true if enabled * @see MapboxMap#setPrefetchesTiles(boolean) + * @deprecated Use {@link #getPrefetchZoomDelta()} instead. */ + @Deprecated public boolean getPrefetchesTiles() { return nativeMapView.getPrefetchTiles(); } + /** + * Set the tile pre-fetching zoom delta. Pre-fetching makes sure that a low-resolution + * tile at the (current_zoom_level - delta) is rendered as soon as possible at the + * expense of a little bandwidth. + * Note: This operation will override the MapboxMapOptions#setPrefetchesTiles(boolean) + * Setting zoom delta to 0 will disable pre-fetching. + * Default zoom delta is 4. + * + * @param delta zoom delta + */ + public void setPrefetchZoomDelta(@IntRange(from = 0) int delta) { + nativeMapView.setPrefetchZoomDelta(delta); + } + + /** + * Check current pre-fetching zoom delta. + * + * @return current zoom delta. + * @see MapboxMap#setPrefetchZoomDelta(int) + */ + @IntRange(from = 0) + public int getPrefetchZoomDelta() { + return nativeMapView.getPrefetchZoomDelta(); + } + // // MinZoom // diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java index 6cd3271d1..827756870 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java @@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.ColorInt; +import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; @@ -70,6 +71,7 @@ public class MapboxMapOptions implements Parcelable { private boolean quickZoomGesturesEnabled = true; private boolean prefetchesTiles = true; + private int prefetchZoomDelta = 4; private boolean zMediaOverlay = false; private boolean localIdeographFontFamilyEnabled = true; @@ -134,6 +136,7 @@ public class MapboxMapOptions implements Parcelable { textureMode = in.readByte() != 0; translucentTextureSurface = in.readByte() != 0; prefetchesTiles = in.readByte() != 0; + prefetchZoomDelta = in.readInt(); zMediaOverlay = in.readByte() != 0; localIdeographFontFamilyEnabled = in.readByte() != 0; localIdeographFontFamily = in.readString(); @@ -257,6 +260,8 @@ public class MapboxMapOptions implements Parcelable { typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_renderTextureTranslucentSurface, false)); mapboxMapOptions.setPrefetchesTiles( typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_enableTilePrefetch, true)); + mapboxMapOptions.setPrefetchZoomDelta( + typedArray.getInt(R.styleable.mapbox_MapView_mapbox_prefetchZoomDelta, 4)); mapboxMapOptions.renderSurfaceOnTop( typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_enableZMediaOverlay, false)); @@ -633,13 +638,32 @@ public class MapboxMapOptions implements Parcelable { * * @param enable true to enable * @return This + * @deprecated Use {@link #setPrefetchZoomDelta(int)} instead. */ + @Deprecated @NonNull public MapboxMapOptions setPrefetchesTiles(boolean enable) { this.prefetchesTiles = enable; return this; } + /** + * Set the tile pre-fetching zoom delta. Pre-fetching makes sure that a low-resolution + * tile at the (current_zoom_level - delta) is rendered as soon as possible at the + * expense of a little bandwidth. + * Note: This operation will override the MapboxMapOptions#setPrefetchesTiles(boolean) + * Setting zoom delta to 0 will disable pre-fetching. + * Default zoom delta is 4. + * + * @param delta zoom delta + * @return This + */ + @NonNull + public MapboxMapOptions setPrefetchZoomDelta(@IntRange(from = 0) int delta) { + this.prefetchZoomDelta = delta; + return this; + } + /** * Enable cross-source symbol collision detection, defaults to true. *

@@ -721,11 +745,23 @@ public class MapboxMapOptions implements Parcelable { * Check whether tile pre-fetching is enabled. * * @return true if enabled + * @deprecated Use {@link #getPrefetchZoomDelta()} instead. */ + @Deprecated public boolean getPrefetchesTiles() { return prefetchesTiles; } + /** + * Check current pre-fetching zoom delta. + * + * @return current zoom delta. + */ + @IntRange(from = 0) + public int getPrefetchZoomDelta() { + return prefetchZoomDelta; + } + /** * Check whether cross-source symbol collision detection is enabled. * @@ -1081,6 +1117,7 @@ public class MapboxMapOptions implements Parcelable { dest.writeByte((byte) (textureMode ? 1 : 0)); dest.writeByte((byte) (translucentTextureSurface ? 1 : 0)); dest.writeByte((byte) (prefetchesTiles ? 1 : 0)); + dest.writeInt(prefetchZoomDelta); dest.writeByte((byte) (zMediaOverlay ? 1 : 0)); dest.writeByte((byte) (localIdeographFontFamilyEnabled ? 1 : 0)); dest.writeString(localIdeographFontFamily); @@ -1175,6 +1212,9 @@ public class MapboxMapOptions implements Parcelable { if (prefetchesTiles != options.prefetchesTiles) { return false; } + if (prefetchZoomDelta != options.prefetchZoomDelta) { + return false; + } if (zMediaOverlay != options.zMediaOverlay) { return false; } @@ -1231,6 +1271,7 @@ public class MapboxMapOptions implements Parcelable { result = 31 * result + (textureMode ? 1 : 0); result = 31 * result + (translucentTextureSurface ? 1 : 0); result = 31 * result + (prefetchesTiles ? 1 : 0); + result = 31 * result + prefetchZoomDelta; result = 31 * result + (zMediaOverlay ? 1 : 0); result = 31 * result + (localIdeographFontFamilyEnabled ? 1 : 0); result = 31 * result + (localIdeographFontFamily != null ? localIdeographFontFamily.hashCode() : 0); diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java index 7f3017c7a..c805dcddb 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java @@ -6,6 +6,7 @@ import android.graphics.RectF; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; + import com.mapbox.geojson.Feature; import com.mapbox.geojson.Geometry; import com.mapbox.mapboxsdk.annotations.Marker; @@ -214,6 +215,11 @@ interface NativeMap { boolean getPrefetchTiles(); + void setPrefetchZoomDelta(@IntRange(from = 0) int delta); + + @IntRange(from = 0) + int getPrefetchZoomDelta(); + void setGestureInProgress(boolean inProgress); float getPixelRatio(); diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index 8496160c7..75ca5edfc 100755 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -620,7 +620,7 @@ final class NativeMapView implements NativeMap { if (checkState("getMetersPerPixelAtLatitude")) { return 0; } - return nativeGetMetersPerPixelAtLatitude(lat, getZoom()) / pixelRatio; + return nativeGetMetersPerPixelAtLatitude(lat, getZoom()); } @Override @@ -724,6 +724,23 @@ final class NativeMapView implements NativeMap { return nativeGetPrefetchTiles(); } + @Override + public void setPrefetchZoomDelta(@IntRange(from = 0) int delta) { + if (checkState("nativeSetPrefetchZoomDelta")) { + return; + } + nativeSetPrefetchZoomDelta(delta); + } + + @Override + @IntRange(from = 0) + public int getPrefetchZoomDelta() { + if (checkState("nativeGetPrefetchZoomDelta")) { + return 0; + } + return nativeGetPrefetchZoomDelta(); + } + // Runtime style Api @Override @@ -1383,6 +1400,12 @@ final class NativeMapView implements NativeMap { @Keep private native boolean nativeGetPrefetchTiles(); + @Keep + private native void nativeSetPrefetchZoomDelta(int delta); + + @Keep + private native int nativeGetPrefetchZoomDelta(); + @Override public long getNativePtr() { return nativePtr; diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java index 9e72be8e9..3fd155837 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java @@ -417,10 +417,6 @@ public final class UiSettings { } void update(@NonNull CameraPosition cameraPosition) { - if (!isCompassEnabled()) { - return; - } - double clockwiseBearing = -cameraPosition.bearing; compassView.update(clockwiseBearing); } @@ -1073,6 +1069,7 @@ public final class UiSettings { */ public void invalidate() { setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom()); + setCompassEnabled(isCompassEnabled()); setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom()); setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(), getAttributionMarginBottom()); diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java index 53c0c1c60..b593076dc 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java @@ -91,6 +91,7 @@ public final class CompassView extends ImageView implements Runnable { resetAnimation(); setAlpha(1.0f); setVisibility(View.VISIBLE); + update(rotation); } else { resetAnimation(); setAlpha(0.0f); diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java index 1e0069c25..990bd3226 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java @@ -235,7 +235,7 @@ public class MapSnapshotter { */ @NonNull public Options withApiBaseUri(String apiBaseUri) { - this.apiBaseUrl = apiBaseUrl; + this.apiBaseUrl = apiBaseUri; return this; } diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index 763c97cca..07e5b7e16 100644 --- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.res.AssetManager; import android.os.AsyncTask; import android.os.Environment; import android.support.annotation.Keep; @@ -90,7 +89,7 @@ public class FileSource { @UiThread public static synchronized FileSource getInstance(@NonNull Context context) { if (INSTANCE == null) { - INSTANCE = new FileSource(getResourcesCachePath(context), context.getResources().getAssets()); + INSTANCE = new FileSource(getResourcesCachePath(context)); } return INSTANCE; @@ -366,8 +365,8 @@ public class FileSource { @Keep private long nativePtr; - private FileSource(String cachePath, AssetManager assetManager) { - initialize(Mapbox.getAccessToken(), cachePath, assetManager); + private FileSource(String cachePath) { + initialize(Mapbox.getAccessToken(), cachePath); } @Keep @@ -404,7 +403,7 @@ public class FileSource { private native void setResourceCachePath(String path, ResourcesCachePathChangeCallback callback); @Keep - private native void initialize(String accessToken, String cachePath, AssetManager assetManager); + private native void initialize(String accessToken, String cachePath); @Override @Keep diff --git a/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/MapboxGLAndroidSDK/src/main/res-public/values/public.xml index 60a1efc77..36071cc2a 100644 --- a/MapboxGLAndroidSDK/src/main/res-public/values/public.xml +++ b/MapboxGLAndroidSDK/src/main/res-public/values/public.xml @@ -69,6 +69,7 @@ + diff --git a/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/MapboxGLAndroidSDK/src/main/res/values/attrs.xml index ff8a32ac6..137f72f8d 100644 --- a/MapboxGLAndroidSDK/src/main/res/values/attrs.xml +++ b/MapboxGLAndroidSDK/src/main/res/values/attrs.xml @@ -109,6 +109,7 @@ + diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AttributionDialogManagerTest.java b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AttributionDialogManagerTest.java new file mode 100644 index 000000000..9b4eeb27a --- /dev/null +++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AttributionDialogManagerTest.java @@ -0,0 +1,99 @@ +package com.mapbox.mapboxsdk.maps; + +import android.content.Context; + +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.geometry.LatLng; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.robolectric.RobolectricTestRunner; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +public class AttributionDialogManagerTest { + @InjectMocks + Context context = mock(Context.class); + + @InjectMocks + MapboxMap mapboxMap = mock(MapboxMap.class); + + @InjectMocks + Style style = mock(Style.class); + + private AttributionDialogManager attributionDialogManager; + private CameraPosition cameraPosition; + + private static final String ASSERT_MAPBOX_TOKEN = "TestAccessToken"; + + private static final String ASSERT_MAPBOX_STYLE_URI = "mapbox://styles/mapbox/streets-v11"; + private static final String ASSERT_MAPBOX_LOCAL_STYLE_URI = "asset://style.json"; + + private static final String ASSERT_MAPBOX_PACKAGE_NAME = "com.mapbox.attributionmanagertest"; + + private static final String ASSERT_MAPBOX_FEEDBACK_FINAL_URL = + "https://apps.mapbox.com/feedback?referrer=com.mapbox.attributionmanagertest&" + + "access_token=TestAccessToken&owner=mapbox&id=streets-v11" + + "#/22.200001/11.100000/12.000000/24.000000/5"; + private static final String ASSERT_MAPBOX_FEEDHACK_FINAL_URL_LOCAL_STYLE = + "https://apps.mapbox.com/feedback?referrer=com.mapbox.attributionmanagertest&" + + "access_token=TestAccessToken#/22.200001/11.100000/12.000000/24.000000/5"; + private static final String ASSERT_MAPBOX_FEEDBACL_FINAL_URL_NULL_CAMERA_POSITION = + "https://apps.mapbox.com/feedback?referrer=com.mapbox.attributionmanagertest&access_token=TestAccessToken"; + + @Before + public void beforeTest() { + attributionDialogManager = new AttributionDialogManager(context, mapboxMap); + cameraPosition = new CameraPosition.Builder(CameraPosition.DEFAULT) + .tilt(5.0f).zoom(12).bearing(24.0f).target(new LatLng(11.1f, 22.2f)).build(); + } + + @Test + public void testSanity() { + assertNotNull("AttributionDialogManager should not be null", attributionDialogManager); + } + + @Test + public void testBuildMapFeedbackMapUrl() { + when(context.getApplicationContext()).thenReturn(context); + when(context.getPackageName()).thenReturn(ASSERT_MAPBOX_PACKAGE_NAME); + when(style.getUri()).thenReturn(ASSERT_MAPBOX_STYLE_URI); + when(mapboxMap.getCameraPosition()).thenReturn(cameraPosition); + when(mapboxMap.getStyle()).thenReturn(style); + + Assert.assertEquals(ASSERT_MAPBOX_FEEDBACK_FINAL_URL, + attributionDialogManager.buildMapFeedbackMapUrl(ASSERT_MAPBOX_TOKEN)); + } + + @Test + public void testBuildMapFeedbackMapUrlWithLocalStyleJson() { + when(context.getApplicationContext()).thenReturn(context); + when(context.getPackageName()).thenReturn(ASSERT_MAPBOX_PACKAGE_NAME); + when(style.getUri()).thenReturn(ASSERT_MAPBOX_LOCAL_STYLE_URI); + when(mapboxMap.getCameraPosition()).thenReturn(cameraPosition); + when(mapboxMap.getStyle()).thenReturn(style); + + Assert.assertEquals(ASSERT_MAPBOX_FEEDHACK_FINAL_URL_LOCAL_STYLE, + attributionDialogManager.buildMapFeedbackMapUrl(ASSERT_MAPBOX_TOKEN)); + } + + @Test + public void testBuildMapFeedbackMapUrlWithNullCameraPosition() { + when(context.getApplicationContext()).thenReturn(context); + when(context.getPackageName()).thenReturn(ASSERT_MAPBOX_PACKAGE_NAME); + when(style.getUri()).thenReturn(ASSERT_MAPBOX_LOCAL_STYLE_URI); + when(mapboxMap.getCameraPosition()).thenReturn(null); + when(mapboxMap.getStyle()).thenReturn(style); + + Assert.assertEquals(ASSERT_MAPBOX_FEEDBACL_FINAL_URL_NULL_CAMERA_POSITION, + attributionDialogManager.buildMapFeedbackMapUrl(ASSERT_MAPBOX_TOKEN)); + } + + +} diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java index 6978afcf1..c46e6e319 100644 --- a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java +++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java @@ -167,6 +167,16 @@ public class MapboxMapOptionsTest { assertFalse(new MapboxMapOptions().setPrefetchesTiles(false).getPrefetchesTiles()); } + @Test + public void testPrefetchZoomDelta() { + // Default value + assertEquals(4, new MapboxMapOptions().getPrefetchZoomDelta()); + + // Check mutations + assertEquals(5, new MapboxMapOptions().setPrefetchZoomDelta(5).getPrefetchZoomDelta()); + } + + @Test public void testCrossSourceCollisions() { // Default value diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt index deb5f603c..6647fe559 100644 --- a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt +++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt @@ -126,6 +126,18 @@ class MapboxMapTest { verify { nativeMapView.prefetchTiles = true } } + @Test + fun testGetPrefetchZoomDelta() { + every { nativeMapView.prefetchZoomDelta } answers { 3 } + assertEquals(3, mapboxMap.prefetchZoomDelta) + } + + @Test + fun testSetPrefetchZoomDelta() { + mapboxMap.prefetchZoomDelta = 2 + verify { nativeMapView.prefetchZoomDelta = 2 } + } + @Test fun testCameraForLatLngBounds() { val bounds = LatLngBounds.Builder().include(LatLng()).include(LatLng(1.0, 1.0)).build() diff --git a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java index cfcf0a048..a84e93cd7 100644 --- a/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java +++ b/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java @@ -5,6 +5,7 @@ import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; +import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.maps.widgets.CompassView; import org.junit.Before; @@ -17,6 +18,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; public class UiSettingsTest { @@ -412,4 +414,20 @@ public class UiSettingsTest { assertEquals("Zoom rate should be 0.83f", 0.83f, uiSettings.getZoomRate(), 0); } + + @Test + public void testUpdateWhenCompassViewNotHidden() { + CameraPosition cameraPosition = new CameraPosition.Builder(CameraPosition.DEFAULT).bearing(24.0f).build(); + when(compassView.isHidden()).thenReturn(false); + uiSettings.update(cameraPosition); + verify(compassView).update(-24.0f); + } + + @Test + public void testUpdateWhenCompassViewHidden() { + CameraPosition cameraPosition = new CameraPosition.Builder(CameraPosition.DEFAULT).bearing(24.0f).build(); + when(compassView.isHidden()).thenReturn(true); + uiSettings.update(cameraPosition); + verify(compassView).update(-24.0f); + } } diff --git a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt index fb113502e..51c9e1c10 100644 --- a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt +++ b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt @@ -1288,6 +1288,36 @@ class LocationComponentTest : EspressoTest() { executeComponentTest(componentAction) } + @Test + fun animators_dontZoomWhileTransitioning() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction( + component: LocationComponent, + mapboxMap: MapboxMap, + style: Style, + uiController: UiController, + context: Context + ) { + component.activateLocationComponent(LocationComponentActivationOptions + .builder(context, style) + .useDefaultLocationEngine(false) + .build()) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + + val zoom = mapboxMap.cameraPosition.zoom + component.setCameraMode(CameraMode.TRACKING_GPS, 500L, null, null, null, null) + component.zoomWhileTracking(16.0, 1000) + uiController.loopMainThreadForAtLeast(1000) + TestingAsyncUtils.waitForLayer(uiController, mapView) + + assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.0001) + } + } + + executeComponentTest(componentAction) + } + @Test @Ignore fun animators_cancelZoomWhileTracking() { @@ -1433,6 +1463,36 @@ class LocationComponentTest : EspressoTest() { executeComponentTest(componentAction) } + @Test + fun animators_dontTiltWhileTransitioning() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction( + component: LocationComponent, + mapboxMap: MapboxMap, + style: Style, + uiController: UiController, + context: Context + ) { + component.activateLocationComponent(LocationComponentActivationOptions + .builder(context, style) + .useDefaultLocationEngine(false) + .build()) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + + val tilt = mapboxMap.cameraPosition.tilt + component.setCameraMode(CameraMode.TRACKING_GPS, 500L, null, null, null, null) + component.tiltWhileTracking(30.0, 1000) + uiController.loopMainThreadForAtLeast(1000) + TestingAsyncUtils.waitForLayer(uiController, mapView) + + assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.0001) + } + } + + executeComponentTest(componentAction) + } + @Test @Ignore fun animators_cancelTiltWhileTracking() { diff --git a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt index b13bb6b79..dc313b5f6 100644 --- a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt +++ b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt @@ -221,6 +221,23 @@ class NativeMapViewTest : AppCenter() { assertEquals("Flag should match", expected, actual) } + @Test + @UiThreadTest + fun testPrefetchZoomDelta() { + val expected = 2 + nativeMapView.prefetchZoomDelta = 2 + val actual = nativeMapView.prefetchZoomDelta + assertEquals("Prefetch zoom delta should match", expected, actual) + } + + @Test + @UiThreadTest + fun testPrefetchZoomDeltaDefault() { + val expected = 4 + val actual = nativeMapView.prefetchZoomDelta + assertEquals("Prefetch zoom delta should match", expected, actual) + } + @Test @UiThreadTest fun testSetContentPadding() { @@ -254,7 +271,7 @@ class NativeMapViewTest : AppCenter() { @Test @UiThreadTest fun testGetProjectedMetersAtLatitude() { - val expected = 38986.83510557766 + val expected = 77973.67021115532 val actual = nativeMapView.getMetersPerPixelAtLatitude(5.0) assertEquals("Get projected meters should match", expected, actual) } diff --git a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java index 45dac2361..b6c16c814 100644 --- a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java +++ b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java @@ -4,6 +4,7 @@ import android.content.Context; import android.support.annotation.CallSuper; import android.support.annotation.UiThread; import android.support.test.rule.ActivityTestRule; +import android.support.test.rule.GrantPermissionRule; import com.mapbox.mapboxsdk.AppCenter; import com.mapbox.mapboxsdk.Mapbox; @@ -35,6 +36,10 @@ public abstract class BaseTest extends AppCenter { @Rule public TestName testName = new TestName(); + @Rule + public GrantPermissionRule grantLocationPermissionRule = GrantPermissionRule + .grant(android.Manifest.permission.ACCESS_FINE_LOCATION); + protected MapboxMap mapboxMap; protected MapView mapView; private final CountDownLatch latch = new CountDownLatch(1); @@ -75,7 +80,12 @@ public abstract class BaseTest extends AppCenter { try { rule.runOnUiThread(() -> { mapView = rule.getActivity().findViewById(R.id.mapView); - mapView.getMapAsync(this::initMap); + if (mapView != null) { + mapView.getMapAsync(this::initMap); + } else { + Timber.w("Skipping map load test since mapView is not found."); + latch.countDown(); + } }); } catch (Throwable throwable) { throwable.printStackTrace(); diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java index 05337081d..d8fd42876 100644 --- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java +++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java @@ -151,6 +151,9 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView @Override protected void onDestroy() { super.onDestroy(); + if (progressDialog != null) { + progressDialog.dismiss(); + } mapView.onDestroy(); } diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java index 40ea7509b..a0e8b31fc 100644 --- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java +++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java @@ -81,7 +81,9 @@ public class MapFragmentActivity extends AppCompatActivity implements MapFragmen @Override protected void onDestroy() { super.onDestroy(); - mapView.removeOnDidFinishRenderingFrameListener(this); + if (mapView != null) { + mapView.removeOnDidFinishRenderingFrameListener(this); + } } @Override diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt index ff2afb50c..7e18cbfa2 100644 --- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt +++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt @@ -116,7 +116,7 @@ class LocationFragmentActivity : AppCompatActivity() { } override fun onSuccess(result: LocationEngineResult?) { - mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation), 12.0)) + if (!mapView.isDestroyed) mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation), 12.0)) } override fun onFailure(exception: Exception) { diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java index 59c708266..ab7ffed83 100644 --- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java +++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java @@ -89,6 +89,7 @@ public class MapSnapshotterActivity extends AppCompatActivity { .bearing(randomInRange(0, 360)) .tilt(randomInRange(0, 60)) .zoom(randomInRange(0, 20)) + .padding(1, 1, 1, 1) .build() ); } diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java index 24bfe62e7..e80d6fe3e 100644 --- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java +++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java @@ -362,7 +362,12 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR @Override protected void onPostExecute(HashMap bitmapHashMap) { super.onPostExecute(bitmapHashMap); - mapboxMap.getStyle().addImagesAsync(bitmapHashMap); + mapboxMap.getStyle(new Style.OnStyleLoaded() { + @Override + public void onStyleLoaded(@NonNull Style style) { + style.addImagesAsync(bitmapHashMap); + } + }); } } } \ No newline at end of file diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index c1c489472..31633488e 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -7,7 +7,7 @@ ext { ] versions = [ - mapboxServices : '4.9.0-alpha.1', + mapboxServices : '4.9.0', mapboxTelemetry : '4.5.1', mapboxCore : '1.3.0', mapboxGestures : '0.5.1', diff --git a/gradle/jacoco-report.gradle b/gradle/jacoco-report.gradle index c4e0bb913..64c99e09f 100644 --- a/gradle/jacoco-report.gradle +++ b/gradle/jacoco-report.gradle @@ -15,7 +15,7 @@ task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) { } def fileExcludes = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] - def debugTree = fileTree(dir: "${project.buildDir}/intermediates/javac/debug/compileDebugJavaWithJavac/classes", excludes: fileExcludes) + def debugTree = fileTree(dir: "${project.buildDir}/intermediates/javac/debug/classes", excludes: fileExcludes) def mainSrc = "${project.projectDir}/src/main/java" println(mainSrc) def ecSrc = fileTree(dir: "$project.buildDir", include: "**/*.ec") diff --git a/scripts/exclude-activity-gen.json b/scripts/exclude-activity-gen.json index 0f5bb81b5..ab84957e3 100644 --- a/scripts/exclude-activity-gen.json +++ b/scripts/exclude-activity-gen.json @@ -5,7 +5,6 @@ "MapSnapshotterLocalStyleActivity", "LatLngBoundsActivity", "BottomSheetActivity", - "MapSnapshotterActivity", "MockLocationEngine", "DeleteRegionActivity", "RealTimeGeoJsonActivity", @@ -50,7 +49,5 @@ "EspressoTestActivity", "FragmentBackStackActivity", "ChildFragmentMapInDialogActivity", - "PerformanceMeasurementActivity", - "DownloadRegionActivity", - "CacheManagementActivity" + "PerformanceMeasurementActivity" ] diff --git a/src/file_source.cpp b/src/file_source.cpp index 05b57e5d1..a002d6616 100644 --- a/src/file_source.cpp +++ b/src/file_source.cpp @@ -1,5 +1,7 @@ #include "file_source.hpp" + #include "attach_env.hpp" +#include "mapbox.hpp" #include #include @@ -14,8 +16,15 @@ namespace mbgl { std::shared_ptr FileSource::createPlatformFileSource(const ResourceOptions& options) { - auto* assetFileSource = reinterpret_cast(options.platformContext()); - auto fileSource = std::make_shared(options.cachePath(), std::unique_ptr(assetFileSource)); + auto env{android::AttachEnv()}; + std::shared_ptr fileSource; + if (android::Mapbox::hasInstance(*env)) { + auto assetManager = android::Mapbox::getAssetManager(*env); + fileSource = std::make_shared(options.cachePath(), + std::make_unique(*env, assetManager)); + } else { + fileSource = std::make_shared(options.cachePath(), options.assetPath()); + } fileSource->setAccessToken(options.accessToken()); return fileSource; } @@ -24,17 +33,12 @@ namespace android { // FileSource // -FileSource::FileSource(jni::JNIEnv& _env, - const jni::String& accessToken, - const jni::String& _cachePath, - const jni::Object& assetManager) { +FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath) { std::string path = jni::Make(_env, _cachePath); mapbox::sqlite::setTempPath(path); - resourceOptions - .withAccessToken(accessToken ? jni::Make(_env, accessToken) : "") - .withCachePath(path + DATABASE_FILE) - .withPlatformContext(reinterpret_cast(new AssetManagerFileSource(_env, assetManager))); + resourceOptions.withAccessToken(accessToken ? jni::Make(_env, accessToken) : "") + .withCachePath(path + DATABASE_FILE); // Create a core default file source fileSource = std::static_pointer_cast(mbgl::FileSource::getSharedFileSource(resourceOptions)); @@ -58,14 +62,15 @@ void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) { void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object& transformCallback) { if (transformCallback) { auto global = jni::NewGlobal(env, transformCallback); - resourceTransform = std::make_unique>(*Scheduler::GetCurrent(), + resourceTransform = std::make_unique>( + *Scheduler::GetCurrent(), // Capture the ResourceTransformCallback object as a managed global into // the lambda. It is released automatically when we're setting a new ResourceTransform in // a subsequent call. // Note: we're converting it to shared_ptr because this lambda is converted to a std::function, // which requires copyability of its captured variables. - [callback = std::make_shared(std::move(global))] - (mbgl::Resource::Kind kind, const std::string&& url_) { + [callback = std::make_shared(std::move(global))](mbgl::Resource::Kind kind, + const std::string& url_) { android::UniqueEnv _env = android::AttachEnv(); return FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_); }); @@ -170,20 +175,20 @@ void FileSource::registerNative(jni::JNIEnv& env) { #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer( - env, javaClass, "nativePtr", - jni::MakePeer&>, - "initialize", - "finalize", - METHOD(&FileSource::getAccessToken, "getAccessToken"), - METHOD(&FileSource::setAccessToken, "setAccessToken"), - METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"), - METHOD(&FileSource::setResourceTransform, "setResourceTransform"), - METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"), - METHOD(&FileSource::resume, "activate"), - METHOD(&FileSource::pause, "deactivate"), - METHOD(&FileSource::isResumed, "isActivated") - ); + jni::RegisterNativePeer(env, + javaClass, + "nativePtr", + jni::MakePeer, + "initialize", + "finalize", + METHOD(&FileSource::getAccessToken, "getAccessToken"), + METHOD(&FileSource::setAccessToken, "setAccessToken"), + METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"), + METHOD(&FileSource::setResourceTransform, "setResourceTransform"), + METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"), + METHOD(&FileSource::resume, "activate"), + METHOD(&FileSource::pause, "deactivate"), + METHOD(&FileSource::isResumed, "isActivated")); } diff --git a/src/file_source.hpp b/src/file_source.hpp index f3ad33eb3..6a9190fa0 100644 --- a/src/file_source.hpp +++ b/src/file_source.hpp @@ -41,7 +41,7 @@ public: const jni::String&); }; - FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object&); + FileSource(jni::JNIEnv&, const jni::String&, const jni::String&); ~FileSource(); diff --git a/src/i18n/collator.cpp b/src/i18n/collator.cpp new file mode 100644 index 000000000..b3dd8e21b --- /dev/null +++ b/src/i18n/collator.cpp @@ -0,0 +1,194 @@ +#include +#include + +#include + +#include "../attach_env.hpp" +#include "collator_jni.hpp" + +namespace mbgl { +namespace android { + +void Collator::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +jni::Local> Collator::getInstance(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "getInstance"); + return javaClass.Call(env, method, locale); +} + +void Collator::setStrength(jni::JNIEnv& env, const jni::Object& collator, jni::jint strength) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "setStrength"); + collator.Call(env, method, strength); +} + +jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object& collator, const jni::String& lhs, const jni::String& rhs) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "compare"); + return collator.Call(env, method, lhs, rhs); +} + +void StringUtils::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +jni::Local StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod(env, "unaccent"); + return javaClass.Call(env, method, value); +} + +void Locale::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +/* +We would prefer to use for/toLanguageTag, but they're only available in API level 21+ + +jni::Object Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) { + using Signature = jni::Object(jni::String); + auto method = javaClass.GetStaticMethod(env, "forLanguageTag"); + return javaClass.Call(env, method, languageTag); +} + +jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object locale) { + using Signature = jni::String(); + auto static method = javaClass.GetMethod(env, "toLanguageTag"); + return locale.Call(env, method); +} +*/ + +jni::Local Locale::getLanguage(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getLanguage"); + return locale.Call(env, method); +} + +jni::Local Locale::getCountry(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getCountry"); + return locale.Call(env, method); +} + +jni::Local> Locale::getDefault(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod ()>(env, "getDefault"); + return javaClass.Call(env, method); +} + +jni::Local> Locale::New(jni::JNIEnv& env, const jni::String& language) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, language); +} + +jni::Local> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, language, region); +} + +} // namespace android + +namespace platform { + +class Collator::Impl { +public: + Impl(bool caseSensitive_, bool diacriticSensitive_, optional locale_) + : caseSensitive(caseSensitive_) + , diacriticSensitive(diacriticSensitive_) + , env(android::AttachEnv()) + { + LanguageTag languageTag = locale_ ? LanguageTag::fromBCP47(*locale_) : LanguageTag(); + if (!languageTag.language) { + locale = jni::NewGlobal(*env, + android::Locale::getDefault(*env)); + } else if (!languageTag.region) { + locale = jni::NewGlobal(*env, + android::Locale::New(*env, jni::Make(*env, *languageTag.language))); + } else { + locale = jni::NewGlobal(*env, + android::Locale::New(*env, jni::Make(*env, *languageTag.language), + jni::Make(*env, *languageTag.region))); + } + collator = jni::NewGlobal(*env, android::Collator::getInstance(*env, locale)); + if (!diacriticSensitive && !caseSensitive) { + android::Collator::setStrength(*env, collator, 0 /*PRIMARY*/); + } else if (diacriticSensitive && !caseSensitive) { + android::Collator::setStrength(*env, collator, 1 /*SECONDARY*/); + } else if (caseSensitive) { + // If we're case-sensitive and diacritic-sensitive, we use a case-sensitive collator + // and a fallback implementation of diacritic-insensitivity. + android::Collator::setStrength(*env, collator, 2 /*TERTIARY*/); + } + } + + bool operator==(const Impl& other) const { + return caseSensitive == other.caseSensitive && + diacriticSensitive == other.diacriticSensitive && + resolvedLocale() == other.resolvedLocale(); + } + + int compare(const std::string& lhs, const std::string& rhs) const { + bool useUnaccent = !diacriticSensitive && caseSensitive; + // java.text.Collator doesn't support a diacritic-insensitive/case-sensitive collation + // order, so we have to compromise here. We use Android's case-sensitive Collator + // against strings that have been "unaccented" using non-locale-aware nunicode logic. + // Because of the difference in locale-awareness, this means turning on case-sensitivity + // can _potentially_ change compare results for strings that don't actually have any case + // differences. + jni::Local jlhs = useUnaccent + ? android::StringUtils::unaccent(*env, jni::Make(*env, lhs)) + : jni::Make(*env, lhs); + jni::Local jrhs = useUnaccent + ? android::StringUtils::unaccent(*env, jni::Make(*env, rhs)) + : jni::Make(*env, rhs); + + jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs); + + return result; + } + + std::string resolvedLocale() const { + std::string language = jni::Make(*env, android::Locale::getLanguage(*env, locale)); + std::string region = jni::Make(*env, android::Locale::getCountry(*env, locale)); + + optional resultLanguage; + if (!language.empty()) resultLanguage = language; + optional resultRegion; + if (!region.empty()) resultRegion = region; + + return LanguageTag(resultLanguage, {}, resultRegion).toBCP47(); + } + +private: + bool caseSensitive; + bool diacriticSensitive; + + android::UniqueEnv env; + jni::Global> collator; + jni::Global> locale; +}; + + +Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional locale_) + : impl(std::make_shared(caseSensitive, diacriticSensitive, std::move(locale_))) +{} + +bool Collator::operator==(const Collator& other) const { + return *impl == *(other.impl); +} + +int Collator::compare(const std::string& lhs, const std::string& rhs) const { + return impl->compare(lhs, rhs); +} + +std::string Collator::resolvedLocale() const { + return impl->resolvedLocale(); +} + +} // namespace platform +} // namespace mbgl diff --git a/src/i18n/collator_jni.hpp b/src/i18n/collator_jni.hpp new file mode 100644 index 000000000..612f9b49f --- /dev/null +++ b/src/i18n/collator_jni.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include + +/* + android::Collator and android::Locale are + the JNI wrappers of + java/text/Collator and java/util/Locale + + mbgl::Collator is the portable interface + Both implementations are in collator.cpp + */ + +namespace mbgl { +namespace android { + +class Locale { +public: + static constexpr auto Name() { return "java/util/Locale"; }; + + /* Requires API level 21+ in order to support script/variant + static jni::Object forLanguageTag(jni::JNIEnv&, jni::String); + static jni::String toLanguageTag(jni::JNIEnv&, jni::Object); + */ + static jni::Local> getDefault(jni::JNIEnv&); + static jni::Local getLanguage(jni::JNIEnv&, const jni::Object&); + static jni::Local getCountry(jni::JNIEnv&, const jni::Object&); + + static jni::Local> New(jni::JNIEnv&, const jni::String&); + static jni::Local> New(jni::JNIEnv&, const jni::String&, const jni::String&); + + + static void registerNative(jni::JNIEnv&); +}; + +class Collator { +public: + static constexpr auto Name() { return "java/text/Collator"; }; + + static jni::Local> getInstance(jni::JNIEnv&, const jni::Object&); + + static void setStrength(jni::JNIEnv&, const jni::Object&, jni::jint); + + static jni::jint compare(jni::JNIEnv&, const jni::Object&, const jni::String&, const jni::String&); + + + static void registerNative(jni::JNIEnv&); +}; + + +class StringUtils { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/utils/StringUtils"; }; + + static jni::Local unaccent(jni::JNIEnv&, const jni::String&); + + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/src/i18n/number_format.cpp b/src/i18n/number_format.cpp new file mode 100644 index 000000000..c8e0b7056 --- /dev/null +++ b/src/i18n/number_format.cpp @@ -0,0 +1,80 @@ +#include +#include + +#include + +#include "../attach_env.hpp" +#include "number_format_jni.hpp" + +namespace mbgl { +namespace android { + +void NumberFormat::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +jni::Local> NumberFormat::getInstance(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "getInstance"); + return javaClass.Call(env, method, locale); +} + +jni::Local> NumberFormat::getCurrencyInstance(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "getCurrencyInstance"); + return javaClass.Call(env, method, locale); +} + +jni::Local NumberFormat::format(jni::JNIEnv& env, const jni::Object& nf, jni::jdouble number) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "format"); + return nf.Call(env, method, number); +} + +void NumberFormat::setMinimumFractionDigits(jni::JNIEnv& env, const jni::Object& nf, jni::jint value) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "setMinimumFractionDigits"); + return nf.Call(env, method, value); +} + +void NumberFormat::setMaximumFractionDigits(jni::JNIEnv& env, const jni::Object& nf, jni::jint value) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "setMaximumFractionDigits"); + return nf.Call(env, method, value); +} + +} // namespace android + +namespace platform { + +std::string formatNumber(double number, const std::string& localeId, const std::string& currency, + uint8_t minFractionDigits, uint8_t maxFractionDigits) { + + auto env{ android::AttachEnv() }; + + jni::Global> locale; + LanguageTag languageTag = !localeId.empty() ? LanguageTag::fromBCP47(localeId) : LanguageTag(); + if (!languageTag.language) { + locale = jni::NewGlobal(*env, android::Locale::getDefault(*env)); + } else if (!languageTag.region) { + locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make(*env, *languageTag.language))); + } else { + locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make(*env, *languageTag.language), + jni::Make(*env, *languageTag.region))); + } + + jni::Global> formatter; + if (currency.empty()) { + formatter = jni::NewGlobal(*env, android::NumberFormat::getInstance(*env, locale)); + android::NumberFormat::setMinimumFractionDigits(*env, formatter, static_cast(minFractionDigits)); + android::NumberFormat::setMaximumFractionDigits(*env, formatter, static_cast(maxFractionDigits)); + } else { + formatter = jni::NewGlobal(*env, android::NumberFormat::getCurrencyInstance(*env, locale)); + } + + auto result = android::NumberFormat::format(*env, formatter, static_cast(number)); + return jni::Make(*env, result); +} + +} // namespace platform +} // namespace mbgl diff --git a/src/i18n/number_format_jni.hpp b/src/i18n/number_format_jni.hpp new file mode 100644 index 000000000..172003892 --- /dev/null +++ b/src/i18n/number_format_jni.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "collator_jni.hpp" + +/* + android::NumberFormat is the JNI wrapper + of java/text/NumberFormat. + */ + +namespace mbgl { +namespace android { + +class NumberFormat { +public: + static constexpr auto Name() { return "java/text/NumberFormat"; }; + + static jni::Local> getInstance(jni::JNIEnv&, const jni::Object&); + static jni::Local> getCurrencyInstance(jni::JNIEnv&, const jni::Object&); + static jni::Local format(jni::JNIEnv&, const jni::Object&, jni::jdouble); + static void setMinimumFractionDigits(jni::JNIEnv&, const jni::Object&, jni::jint); + static void setMaximumFractionDigits(jni::JNIEnv&, const jni::Object&, jni::jint); + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/src/jni_native.cpp b/src/jni_native.cpp old mode 100755 new mode 100644 index df96ba975..bcbdfcf48 --- a/src/jni_native.cpp +++ b/src/jni_native.cpp @@ -6,8 +6,8 @@ #include "bitmap.hpp" #include "bitmap_factory.hpp" #include "connectivity_listener.hpp" -#include "conversion/conversion.hpp" #include "conversion/collection.hpp" +#include "conversion/conversion.hpp" #include "file_source.hpp" #include "geojson/feature.hpp" #include "geojson/feature_collection.hpp" @@ -32,6 +32,7 @@ #include "java_types.hpp" #include "map_renderer.hpp" #include "map_renderer_runnable.hpp" +#include "mapbox.hpp" #include "native_map_view.hpp" #ifndef MBGL_MODULE_OFFLINE_DISABLE #include "offline/offline_manager.hpp" @@ -50,10 +51,10 @@ #include "snapshotter/map_snapshotter.hpp" #include "snapshotter/map_snapshot.hpp" #endif -#include "text/collator_jni.hpp" -#include "text/local_glyph_rasterizer_jni.hpp" -#include "text/format_number_jni.hpp" +#include "i18n/collator_jni.hpp" +#include "i18n/number_format_jni.hpp" #include "logger.hpp" +#include "text/local_glyph_rasterizer_jni.hpp" namespace mbgl { namespace android { @@ -158,6 +159,9 @@ void registerNatives(JavaVM *vm) { // Logger Logger::registerNative(env); + + // AssetManager + Mapbox::registerNative(env); } } // namespace android diff --git a/src/jni_native.hpp b/src/jni_native.hpp index c8e284a52..1cc9a7e81 100644 --- a/src/jni_native.hpp +++ b/src/jni_native.hpp @@ -7,7 +7,7 @@ namespace mbgl { namespace android { -MBGL_PUBLIC void registerNatives(JavaVM* vm); +MBGL_EXPORT void registerNatives(JavaVM* vm); } // namespace android } // namespace mbgl diff --git a/src/map/camera_position.cpp b/src/map/camera_position.cpp index 03aca79bd..4266b64fd 100644 --- a/src/map/camera_position.cpp +++ b/src/map/camera_position.cpp @@ -44,19 +44,20 @@ mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, const jni static auto tilt = javaClass.GetField(env, "tilt"); static auto zoom = javaClass.GetField(env, "zoom"); static auto paddingField = javaClass.GetField>(env, "padding"); - static auto padding = position.Get(env, paddingField); + auto padding = position.Get(env, paddingField); auto center = LatLng::getLatLng(env, position.Get(env, target)); - return mbgl::CameraOptions { - center, - EdgeInsets {padding.Get(env, 1) * pixelRatio, padding.Get(env, 0) * pixelRatio, - padding.Get(env, 3) * pixelRatio, padding.Get(env, 2) * pixelRatio}, - {}, - position.Get(env, zoom), - position.Get(env, bearing), - position.Get(env, tilt) - }; + return mbgl::CameraOptions{center, + padding && padding.Length(env) == 4 ? EdgeInsets{padding.Get(env, 1) * pixelRatio, + padding.Get(env, 0) * pixelRatio, + padding.Get(env, 3) * pixelRatio, + padding.Get(env, 2) * pixelRatio} + : (EdgeInsets){}, + {}, + position.Get(env, zoom), + position.Get(env, bearing), + position.Get(env, tilt)}; } void CameraPosition::registerNative(jni::JNIEnv &env) { diff --git a/src/map_renderer.cpp b/src/map_renderer.cpp index 6be708b99..0c0e907f1 100644 --- a/src/map_renderer.cpp +++ b/src/map_renderer.cpp @@ -43,7 +43,7 @@ ActorRef MapRenderer::actor() const { return *rendererRef; } -void MapRenderer::schedule(std::weak_ptr scheduled) { +void MapRenderer::schedule(std::function scheduled) { // Create a runnable android::UniqueEnv _env = android::AttachEnv(); auto runnable = std::make_unique(*_env, std::move(scheduled)); diff --git a/src/map_renderer.hpp b/src/map_renderer.hpp index 5a8ddeeb9..664da20a9 100644 --- a/src/map_renderer.hpp +++ b/src/map_renderer.hpp @@ -67,7 +67,7 @@ public: // From Scheduler. Schedules by using callbacks to the // JVM to process the mailbox on the right thread. - void schedule(std::weak_ptr scheduled) override; + void schedule(std::function scheduled) override; void requestRender(); diff --git a/src/map_renderer_runnable.cpp b/src/map_renderer_runnable.cpp index 77c3aa301..227f49ee3 100644 --- a/src/map_renderer_runnable.cpp +++ b/src/map_renderer_runnable.cpp @@ -5,9 +5,8 @@ namespace mbgl { namespace android { -MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr mailbox_) - : mailbox(std::move(mailbox_)) { - +MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::function function_) + : function(std::move(function_)) { // Create the Java peer and hold on to a global reference // Not using a weak reference here as this might oerflow // the weak reference table on some devices @@ -21,7 +20,7 @@ MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr> MapRendererRunnable::peer() { diff --git a/src/map_renderer_runnable.hpp b/src/map_renderer_runnable.hpp index 21c4369b6..24d0f2af4 100644 --- a/src/map_renderer_runnable.hpp +++ b/src/map_renderer_runnable.hpp @@ -24,7 +24,7 @@ public: static void registerNative(jni::JNIEnv&); - MapRendererRunnable(jni::JNIEnv&, std::weak_ptr); + MapRendererRunnable(jni::JNIEnv&, std::function); // Only for jni registration, unused MapRendererRunnable(jni::JNIEnv&) { @@ -40,7 +40,7 @@ public: private: jni::Global> javaPeer; - std::weak_ptr mailbox; + std::function function; }; } // namespace android diff --git a/src/mapbox.cpp b/src/mapbox.cpp new file mode 100644 index 000000000..5246739cf --- /dev/null +++ b/src/mapbox.cpp @@ -0,0 +1,23 @@ +#include "mapbox.hpp" + +namespace mbgl { +namespace android { + +jni::Local> Mapbox::getAssetManager(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); + auto method = javaClass.GetStaticMethod()>(env, "getAssetManager"); + return javaClass.Call(env, method); +} + +jboolean Mapbox::hasInstance(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); + auto method = javaClass.GetStaticMethod(env, "hasInstance"); + return javaClass.Call(env, method); +} + +void Mapbox::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +} // namespace android +} // namespace mbgl diff --git a/src/mapbox.hpp b/src/mapbox.hpp new file mode 100644 index 000000000..813f5bf17 --- /dev/null +++ b/src/mapbox.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "asset_manager.hpp" + +#include + +namespace mbgl { +namespace android { + +class Mapbox { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/Mapbox"; }; + static jboolean hasInstance(jni::JNIEnv&); + static jni::Local> getAssetManager(jni::JNIEnv&); + static void registerNative(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/src/native_map_view.cpp b/src/native_map_view.cpp old mode 100755 new mode 100644 index 8ef757de1..8cb637fa3 --- a/src/native_map_view.cpp +++ b/src/native_map_view.cpp @@ -40,19 +40,19 @@ #include "style/conversion/filter.hpp" #include "geojson/feature.hpp" -#include "jni.hpp" -#include "attach_env.hpp" -#include "map_renderer.hpp" #include "android_renderer_frontend.hpp" -#include "file_source.hpp" +#include "attach_env.hpp" #include "bitmap.hpp" -#include "run_loop_impl.hpp" -#include "java/util.hpp" -#include "geometry/lat_lng_bounds.hpp" -#include "map/camera_position.hpp" -#include "map/image.hpp" -#include "style/light.hpp" #include "bitmap_factory.hpp" +#include "file_source.hpp" +#include "geometry/lat_lng_bounds.hpp" +#include "java/util.hpp" +#include "jni.hpp" +#include "map/camera_position.hpp" +#include "map/image.hpp" +#include "map_renderer.hpp" +#include "run_loop_impl.hpp" +#include "style/light.hpp" namespace mbgl { namespace android { @@ -185,7 +185,7 @@ void NativeMapView::onWillStartRenderingFrame() { } } -void NativeMapView::onDidFinishRenderingFrame(MapObserver::RenderMode mode, bool) { +void NativeMapView::onDidFinishRenderingFrame(MapObserver::RenderFrameStatus status) { assert(vm != nullptr); android::UniqueEnv _env = android::AttachEnv(); @@ -193,7 +193,7 @@ void NativeMapView::onDidFinishRenderingFrame(MapObserver::RenderMode mode, bool static auto onDidFinishRenderingFrame = javaClass.GetMethod(*_env, "onDidFinishRenderingFrame"); auto weakReference = javaPeer.get(*_env); if (weakReference) { - weakReference.Call(*_env, onDidFinishRenderingFrame, (jboolean) (mode != MapObserver::RenderMode::Partial)); + weakReference.Call(*_env, onDidFinishRenderingFrame, (jboolean) (status.mode != MapObserver::RenderMode::Partial)); } } @@ -1050,6 +1050,14 @@ jni::jboolean NativeMapView::getPrefetchTiles(JNIEnv&) { return jni::jboolean(map->getPrefetchZoomDelta() > 0); } +void NativeMapView::setPrefetchZoomDelta(JNIEnv&, jni::jint delta) { + map->setPrefetchZoomDelta(uint8_t(delta)); +} + +jni::jint NativeMapView::getPrefetchZoomDelta(JNIEnv&) { + return jni::jint(map->getPrefetchZoomDelta()); +} + mbgl::Map& NativeMapView::getMap() { return *map; } @@ -1063,90 +1071,99 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, javaClass, "nativePtr", - jni::MakePeer&, const jni::Object&, const jni::Object&, jni::jfloat, jni::jboolean>, - "nativeInitialize", - "nativeDestroy", - METHOD(&NativeMapView::resizeView, "nativeResizeView"), - METHOD(&NativeMapView::getStyleUrl, "nativeGetStyleUrl"), - METHOD(&NativeMapView::setStyleUrl, "nativeSetStyleUrl"), - METHOD(&NativeMapView::getStyleJson, "nativeGetStyleJson"), - METHOD(&NativeMapView::setStyleJson, "nativeSetStyleJson"), - METHOD(&NativeMapView::cancelTransitions, "nativeCancelTransitions"), - METHOD(&NativeMapView::setGestureInProgress, "nativeSetGestureInProgress"), - METHOD(&NativeMapView::moveBy, "nativeMoveBy"), - METHOD(&NativeMapView::jumpTo, "nativeJumpTo"), - METHOD(&NativeMapView::easeTo, "nativeEaseTo"), - METHOD(&NativeMapView::flyTo, "nativeFlyTo"), - METHOD(&NativeMapView::getLatLng, "nativeGetLatLng"), - METHOD(&NativeMapView::setLatLng, "nativeSetLatLng"), - METHOD(&NativeMapView::getCameraForLatLngBounds, "nativeGetCameraForLatLngBounds"), - METHOD(&NativeMapView::getCameraForGeometry, "nativeGetCameraForGeometry"), - METHOD(&NativeMapView::setReachability, "nativeSetReachability"), - METHOD(&NativeMapView::resetPosition, "nativeResetPosition"), - METHOD(&NativeMapView::getPitch, "nativeGetPitch"), - METHOD(&NativeMapView::setPitch, "nativeSetPitch"), - METHOD(&NativeMapView::getZoom, "nativeGetZoom"), - METHOD(&NativeMapView::setZoom, "nativeSetZoom"), - METHOD(&NativeMapView::resetZoom, "nativeResetZoom"), - METHOD(&NativeMapView::setMinZoom, "nativeSetMinZoom"), - METHOD(&NativeMapView::getMinZoom, "nativeGetMinZoom"), - METHOD(&NativeMapView::setMaxZoom, "nativeSetMaxZoom"), - METHOD(&NativeMapView::getMaxZoom, "nativeGetMaxZoom"), - METHOD(&NativeMapView::rotateBy, "nativeRotateBy"), - METHOD(&NativeMapView::setBearing, "nativeSetBearing"), - METHOD(&NativeMapView::setBearingXY, "nativeSetBearingXY"), - METHOD(&NativeMapView::getBearing, "nativeGetBearing"), - METHOD(&NativeMapView::resetNorth, "nativeResetNorth"), - METHOD(&NativeMapView::setVisibleCoordinateBounds, "nativeSetVisibleCoordinateBounds"), - METHOD(&NativeMapView::scheduleSnapshot, "nativeTakeSnapshot"), - METHOD(&NativeMapView::getCameraPosition, "nativeGetCameraPosition"), - METHOD(&NativeMapView::updateMarker, "nativeUpdateMarker"), - METHOD(&NativeMapView::addMarkers, "nativeAddMarkers"), - METHOD(&NativeMapView::setDebug, "nativeSetDebug"), - METHOD(&NativeMapView::cycleDebugOptions, "nativeCycleDebugOptions"), - METHOD(&NativeMapView::getDebug, "nativeGetDebug"), - METHOD(&NativeMapView::isFullyLoaded, "nativeIsFullyLoaded"), - METHOD(&NativeMapView::onLowMemory, "nativeOnLowMemory"), - METHOD(&NativeMapView::getMetersPerPixelAtLatitude, "nativeGetMetersPerPixelAtLatitude"), - METHOD(&NativeMapView::projectedMetersForLatLng, "nativeProjectedMetersForLatLng"), - METHOD(&NativeMapView::pixelForLatLng, "nativePixelForLatLng"), - METHOD(&NativeMapView::latLngForProjectedMeters, "nativeLatLngForProjectedMeters"), - METHOD(&NativeMapView::latLngForPixel, "nativeLatLngForPixel"), - METHOD(&NativeMapView::addPolylines, "nativeAddPolylines"), - METHOD(&NativeMapView::addPolygons, "nativeAddPolygons"), - METHOD(&NativeMapView::updatePolyline, "nativeUpdatePolyline"), - METHOD(&NativeMapView::updatePolygon, "nativeUpdatePolygon"), - METHOD(&NativeMapView::removeAnnotations, "nativeRemoveAnnotations"), - METHOD(&NativeMapView::addAnnotationIcon, "nativeAddAnnotationIcon"), - METHOD(&NativeMapView::removeAnnotationIcon, "nativeRemoveAnnotationIcon"), - METHOD(&NativeMapView::getTopOffsetPixelsForAnnotationSymbol, "nativeGetTopOffsetPixelsForAnnotationSymbol"), - METHOD(&NativeMapView::getTransitionOptions, "nativeGetTransitionOptions"), - METHOD(&NativeMapView::setTransitionOptions, "nativeSetTransitionOptions"), - METHOD(&NativeMapView::queryPointAnnotations, "nativeQueryPointAnnotations"), - METHOD(&NativeMapView::queryShapeAnnotations, "nativeQueryShapeAnnotations"), - METHOD(&NativeMapView::queryRenderedFeaturesForPoint, "nativeQueryRenderedFeaturesForPoint"), - METHOD(&NativeMapView::queryRenderedFeaturesForBox, "nativeQueryRenderedFeaturesForBox"), - METHOD(&NativeMapView::getLight, "nativeGetLight"), - METHOD(&NativeMapView::getLayers, "nativeGetLayers"), - METHOD(&NativeMapView::getLayer, "nativeGetLayer"), - METHOD(&NativeMapView::addLayer, "nativeAddLayer"), - METHOD(&NativeMapView::addLayerAbove, "nativeAddLayerAbove"), - METHOD(&NativeMapView::addLayerAt, "nativeAddLayerAt"), - METHOD(&NativeMapView::removeLayerAt, "nativeRemoveLayerAt"), - METHOD(&NativeMapView::removeLayer, "nativeRemoveLayer"), - METHOD(&NativeMapView::getSources, "nativeGetSources"), - METHOD(&NativeMapView::getSource, "nativeGetSource"), - METHOD(&NativeMapView::addSource, "nativeAddSource"), - METHOD(&NativeMapView::removeSource, "nativeRemoveSource"), - METHOD(&NativeMapView::addImage, "nativeAddImage"), - METHOD(&NativeMapView::addImages, "nativeAddImages"), - METHOD(&NativeMapView::removeImage, "nativeRemoveImage"), - METHOD(&NativeMapView::getImage, "nativeGetImage"), - METHOD(&NativeMapView::setLatLngBounds, "nativeSetLatLngBounds"), - METHOD(&NativeMapView::setPrefetchTiles, "nativeSetPrefetchTiles"), - METHOD(&NativeMapView::getPrefetchTiles, "nativeGetPrefetchTiles") - ); + jni::RegisterNativePeer( + env, + javaClass, + "nativePtr", + jni::MakePeer&, + const jni::Object&, + const jni::Object&, + jni::jfloat, + jni::jboolean>, + "nativeInitialize", + "nativeDestroy", + METHOD(&NativeMapView::resizeView, "nativeResizeView"), + METHOD(&NativeMapView::getStyleUrl, "nativeGetStyleUrl"), + METHOD(&NativeMapView::setStyleUrl, "nativeSetStyleUrl"), + METHOD(&NativeMapView::getStyleJson, "nativeGetStyleJson"), + METHOD(&NativeMapView::setStyleJson, "nativeSetStyleJson"), + METHOD(&NativeMapView::cancelTransitions, "nativeCancelTransitions"), + METHOD(&NativeMapView::setGestureInProgress, "nativeSetGestureInProgress"), + METHOD(&NativeMapView::moveBy, "nativeMoveBy"), + METHOD(&NativeMapView::jumpTo, "nativeJumpTo"), + METHOD(&NativeMapView::easeTo, "nativeEaseTo"), + METHOD(&NativeMapView::flyTo, "nativeFlyTo"), + METHOD(&NativeMapView::getLatLng, "nativeGetLatLng"), + METHOD(&NativeMapView::setLatLng, "nativeSetLatLng"), + METHOD(&NativeMapView::getCameraForLatLngBounds, "nativeGetCameraForLatLngBounds"), + METHOD(&NativeMapView::getCameraForGeometry, "nativeGetCameraForGeometry"), + METHOD(&NativeMapView::setReachability, "nativeSetReachability"), + METHOD(&NativeMapView::resetPosition, "nativeResetPosition"), + METHOD(&NativeMapView::getPitch, "nativeGetPitch"), + METHOD(&NativeMapView::setPitch, "nativeSetPitch"), + METHOD(&NativeMapView::getZoom, "nativeGetZoom"), + METHOD(&NativeMapView::setZoom, "nativeSetZoom"), + METHOD(&NativeMapView::resetZoom, "nativeResetZoom"), + METHOD(&NativeMapView::setMinZoom, "nativeSetMinZoom"), + METHOD(&NativeMapView::getMinZoom, "nativeGetMinZoom"), + METHOD(&NativeMapView::setMaxZoom, "nativeSetMaxZoom"), + METHOD(&NativeMapView::getMaxZoom, "nativeGetMaxZoom"), + METHOD(&NativeMapView::rotateBy, "nativeRotateBy"), + METHOD(&NativeMapView::setBearing, "nativeSetBearing"), + METHOD(&NativeMapView::setBearingXY, "nativeSetBearingXY"), + METHOD(&NativeMapView::getBearing, "nativeGetBearing"), + METHOD(&NativeMapView::resetNorth, "nativeResetNorth"), + METHOD(&NativeMapView::setVisibleCoordinateBounds, "nativeSetVisibleCoordinateBounds"), + METHOD(&NativeMapView::scheduleSnapshot, "nativeTakeSnapshot"), + METHOD(&NativeMapView::getCameraPosition, "nativeGetCameraPosition"), + METHOD(&NativeMapView::updateMarker, "nativeUpdateMarker"), + METHOD(&NativeMapView::addMarkers, "nativeAddMarkers"), + METHOD(&NativeMapView::setDebug, "nativeSetDebug"), + METHOD(&NativeMapView::cycleDebugOptions, "nativeCycleDebugOptions"), + METHOD(&NativeMapView::getDebug, "nativeGetDebug"), + METHOD(&NativeMapView::isFullyLoaded, "nativeIsFullyLoaded"), + METHOD(&NativeMapView::onLowMemory, "nativeOnLowMemory"), + METHOD(&NativeMapView::getMetersPerPixelAtLatitude, "nativeGetMetersPerPixelAtLatitude"), + METHOD(&NativeMapView::projectedMetersForLatLng, "nativeProjectedMetersForLatLng"), + METHOD(&NativeMapView::pixelForLatLng, "nativePixelForLatLng"), + METHOD(&NativeMapView::latLngForProjectedMeters, "nativeLatLngForProjectedMeters"), + METHOD(&NativeMapView::latLngForPixel, "nativeLatLngForPixel"), + METHOD(&NativeMapView::addPolylines, "nativeAddPolylines"), + METHOD(&NativeMapView::addPolygons, "nativeAddPolygons"), + METHOD(&NativeMapView::updatePolyline, "nativeUpdatePolyline"), + METHOD(&NativeMapView::updatePolygon, "nativeUpdatePolygon"), + METHOD(&NativeMapView::removeAnnotations, "nativeRemoveAnnotations"), + METHOD(&NativeMapView::addAnnotationIcon, "nativeAddAnnotationIcon"), + METHOD(&NativeMapView::removeAnnotationIcon, "nativeRemoveAnnotationIcon"), + METHOD(&NativeMapView::getTopOffsetPixelsForAnnotationSymbol, "nativeGetTopOffsetPixelsForAnnotationSymbol"), + METHOD(&NativeMapView::getTransitionOptions, "nativeGetTransitionOptions"), + METHOD(&NativeMapView::setTransitionOptions, "nativeSetTransitionOptions"), + METHOD(&NativeMapView::queryPointAnnotations, "nativeQueryPointAnnotations"), + METHOD(&NativeMapView::queryShapeAnnotations, "nativeQueryShapeAnnotations"), + METHOD(&NativeMapView::queryRenderedFeaturesForPoint, "nativeQueryRenderedFeaturesForPoint"), + METHOD(&NativeMapView::queryRenderedFeaturesForBox, "nativeQueryRenderedFeaturesForBox"), + METHOD(&NativeMapView::getLight, "nativeGetLight"), + METHOD(&NativeMapView::getLayers, "nativeGetLayers"), + METHOD(&NativeMapView::getLayer, "nativeGetLayer"), + METHOD(&NativeMapView::addLayer, "nativeAddLayer"), + METHOD(&NativeMapView::addLayerAbove, "nativeAddLayerAbove"), + METHOD(&NativeMapView::addLayerAt, "nativeAddLayerAt"), + METHOD(&NativeMapView::removeLayerAt, "nativeRemoveLayerAt"), + METHOD(&NativeMapView::removeLayer, "nativeRemoveLayer"), + METHOD(&NativeMapView::getSources, "nativeGetSources"), + METHOD(&NativeMapView::getSource, "nativeGetSource"), + METHOD(&NativeMapView::addSource, "nativeAddSource"), + METHOD(&NativeMapView::removeSource, "nativeRemoveSource"), + METHOD(&NativeMapView::addImage, "nativeAddImage"), + METHOD(&NativeMapView::addImages, "nativeAddImages"), + METHOD(&NativeMapView::removeImage, "nativeRemoveImage"), + METHOD(&NativeMapView::getImage, "nativeGetImage"), + METHOD(&NativeMapView::setLatLngBounds, "nativeSetLatLngBounds"), + METHOD(&NativeMapView::setPrefetchTiles, "nativeSetPrefetchTiles"), + METHOD(&NativeMapView::getPrefetchTiles, "nativeGetPrefetchTiles"), + METHOD(&NativeMapView::setPrefetchZoomDelta, "nativeSetPrefetchZoomDelta"), + METHOD(&NativeMapView::getPrefetchZoomDelta, "nativeGetPrefetchZoomDelta")); } } // namespace android diff --git a/src/native_map_view.hpp b/src/native_map_view.hpp index 26567a003..5a340d128 100755 --- a/src/native_map_view.hpp +++ b/src/native_map_view.hpp @@ -62,7 +62,7 @@ public: void onDidFinishLoadingMap() override; void onDidFailLoadingMap(MapLoadError, const std::string&) override; void onWillStartRenderingFrame() override; - void onDidFinishRenderingFrame(MapObserver::RenderMode, bool) override; + void onDidFinishRenderingFrame(MapObserver::RenderFrameStatus) override; void onWillStartRenderingMap() override; void onDidFinishRenderingMap(MapObserver::RenderMode) override; void onDidBecomeIdle() override; @@ -235,6 +235,10 @@ public: jni::jboolean getPrefetchTiles(JNIEnv&); + void setPrefetchZoomDelta(JNIEnv&, jni::jint); + + jni::jint getPrefetchZoomDelta(JNIEnv&); + mbgl::Map& getMap(); private: diff --git a/src/style/sources/source.cpp b/src/style/sources/source.cpp index be4c0367f..786e5cb58 100644 --- a/src/style/sources/source.cpp +++ b/src/style/sources/source.cpp @@ -133,7 +133,7 @@ namespace android { // Release the peer relationships. These will be re-established when the source is added to a map assert(ownedSource->peer.has_value()); ownedSource->peer.get>().release(); - ownedSource->peer = util::peer(); + ownedSource->peer = mapbox::base::TypeWrapper(); // Release the strong reference to the java peer assert(javaPeer); diff --git a/src/test/version-script b/src/test/version-script new file mode 100644 index 000000000..ebc2c1701 --- /dev/null +++ b/src/test/version-script @@ -0,0 +1,8 @@ +{ +global: + EnsureFrontOfChain; + AddSpecialSignalHandlerFn; + RemoveSpecialSignalHandlerFn; +local: + *; +}; diff --git a/vendor/mapbox-gl-native b/vendor/mapbox-gl-native index 89eaac05e..b4e0224a5 160000 --- a/vendor/mapbox-gl-native +++ b/vendor/mapbox-gl-native @@ -1 +1 @@ -Subproject commit 89eaac05ebc2928e59d3f0404f7b92bdb42b92bb +Subproject commit b4e0224a5786f1d362b2b6b7e7f536be8bb98981