diff options
Diffstat (limited to 'platform/android')
41 files changed, 655 insertions, 251 deletions
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index f0c5b2ff91..398844a64e 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -4,6 +4,34 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to ## master +### Bug fixes + - Fixed the rendering bug caused by redundant pending requests for already requested images [#15864](https://github.com/mapbox/mapbox-gl-native/pull/15864) + +### Performance improvements + - Enable incremental vacuum for the offline database in order to make data removal requests faster and to avoid the excessive disk space usage (creating a backup file on VACUUM call) [#15837](https://github.com/mapbox/mapbox-gl-native/pull/15837) + - Convert GeoJSON features to tiles in a background thread and thus unblock the UI thread on updating the GeoJsonSource [#15871](https://github.com/mapbox/mapbox-gl-native/pull/15871) + +## 8.5.0-alpha.2 - October 10, 2019 +[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.5.0-alpha.1...android-v8.5.0-alpha.2) since [Mapbox Maps SDK for Android v8.5.0-alpha.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.5.0-alpha.1): + +### Features + - Expose pre-fetching zoom delta, allows to granular control the delta on which we prefetch tiles [#15769](https://github.com/mapbox/mapbox-gl-native/pull/15769) + +### Performance improvements + - Improved rendering performance for the styles with multiple sources [#15756](https://github.com/mapbox/mapbox-gl-native/pull/15756) + +### Bug fixes + - Fixed runtime exceptions that occurred when a manually built camera object without padding was serialized. [#15788](https://github.com/mapbox/mapbox-gl-native/pull/15788) + - Keep Mapbox when obfuscating code with proguard [#15762](https://github.com/mapbox/mapbox-gl-native/pull/15762) + +## 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) + - Coalesce requests to the client for the same missing image [#15778](https://github.com/mapbox/mapbox-gl-native/pull/15778) + ## 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): @@ -25,11 +53,18 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to - 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): +[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): diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java index 01c82ddad4..35f7a5975d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java +++ b/platform/android/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/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java index e2341029ff..fb89688e28 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java @@ -30,8 +30,16 @@ public final class CameraPosition implements Parcelable { LatLng target = in.readParcelable(LatLng.class.getClassLoader()); double tilt = in.readDouble(); double zoom = in.readDouble(); - double[] padding = new double[4]; - in.readDoubleArray(padding); + + double[] padding = null; + int paddingSize = in.readInt(); + if (paddingSize > 0) { + padding = new double[paddingSize]; + for (int i = 0; i < paddingSize; i++) { + padding[i] = in.readDouble(); + } + } + return new CameraPosition(target, zoom, tilt, bearing, padding); } @@ -139,7 +147,16 @@ public final class CameraPosition implements Parcelable { out.writeParcelable(target, flags); out.writeDouble(tilt); out.writeDouble(zoom); - out.writeDoubleArray(padding); + + if (padding != null) { + int length = padding.length; + out.writeInt(length); + for (double v : padding) { + out.writeDouble(v); + } + } else { + out.writeInt(-1); + } } /** diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index acd5093dad..8f4cb9438c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/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/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java index 6cd3271d12..8277568707 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java +++ b/platform/android/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,7 +638,9 @@ 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; @@ -641,6 +648,23 @@ public class MapboxMapOptions implements Parcelable { } /** + * 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. * <p> * If set to false, symbol layers will only run collision detection against @@ -721,12 +745,24 @@ 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. * * @return true if 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/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java index 7f3017c7ae..c805dcddb0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java +++ b/platform/android/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/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index 8496160c7e..75ca5edfca 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/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/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index 763c97cca7..07e5b7e16d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/platform/android/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/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml index 60a1efc771..36071cc2a7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml @@ -69,6 +69,7 @@ <public name="mapbox_foregroundLoadColor" type="attr" /> <public name="mapbox_enableTilePrefetch" type="attr" /> + <public name="mapbox_prefetchZoomDelta" type="attr"/> <public name="mapbox_enableZMediaOverlay" type="attr" /> <!-- Exposed content descriptions --> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml index ff8a32ac64..137f72f8d2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml @@ -109,6 +109,7 @@ <attr name="mapbox_foregroundLoadColor" format="color"/> <attr name="mapbox_enableTilePrefetch" format="boolean"/> + <attr name="mapbox_prefetchZoomDelta" format="integer"/> <attr name="mapbox_enableZMediaOverlay" format="boolean"/> <attr name="mapbox_pixelRatio" format="float"/> diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java index 6974705fae..dcf84c87b3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java @@ -117,4 +117,15 @@ public class CameraPositionTest { CameraPosition cameraPosition2 = CameraPosition.CREATOR.createFromParcel(parcel); assertEquals("Parcel should match original object", cameraPosition1, cameraPosition2); } + + @Test + public void testParcelableNulls() { + CameraPosition cameraPosition1 = new CameraPosition(null, 3, 4, 5, null); + Parcel parcel = Parcel.obtain(); + cameraPosition1.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + CameraPosition cameraPosition2 = CameraPosition.CREATOR.createFromParcel(parcel); + assertEquals("Parcel should match original object", cameraPosition1, cameraPosition2); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java index 6978afcf1f..c46e6e3190 100644 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java @@ -168,6 +168,16 @@ public class MapboxMapOptionsTest { } @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 assertTrue(new MapboxMapOptions().getCrossSourceCollisions()); diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt index deb5f603c8..6647fe5595 100644 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt @@ -127,6 +127,18 @@ class MapboxMapTest { } @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() mapboxMap.setLatLngBoundsForCameraTarget(bounds) diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt index b13bb6b796..dc313b5f64 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt @@ -223,6 +223,23 @@ class NativeMapViewTest : AppCenter() { @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() { val expected = doubleArrayOf(1.0, 2.0, 3.0, 4.0) nativeMapView.contentPadding = expected @@ -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/platform/android/core-files.json b/platform/android/core-files.json index 362098dd9b..e21a586e29 100644 --- a/platform/android/core-files.json +++ b/platform/android/core-files.json @@ -34,6 +34,8 @@ "platform/android/src/gson/json_element.cpp", "platform/android/src/gson/json_object.cpp", "platform/android/src/gson/json_primitive.cpp", + "platform/android/src/i18n/collator.cpp", + "platform/android/src/i18n/number_format.cpp", "platform/android/src/image.cpp", "platform/android/src/java/util.cpp", "platform/android/src/java_types.cpp", @@ -41,6 +43,7 @@ "platform/android/src/jni_native.cpp", "platform/android/src/logger.cpp", "platform/android/src/logging_android.cpp", + "platform/android/src/mapbox.cpp", "platform/android/src/map/camera_position.cpp", "platform/android/src/map/image.cpp", "platform/android/src/map_renderer.cpp", @@ -80,19 +83,17 @@ "platform/android/src/style/sources/vector_source.cpp", "platform/android/src/style/transition_options.cpp", "platform/android/src/style/value.cpp", - "platform/android/src/text/collator.cpp", "platform/android/src/text/local_glyph_rasterizer.cpp", - "platform/android/src/text/format_number.cpp", "platform/android/src/gl_functions.cpp", "platform/android/src/thread.cpp", "platform/android/src/timer.cpp", - "platform/android/src/unaccent.cpp", "platform/default/src/mbgl/gfx/headless_backend.cpp", "platform/default/src/mbgl/gfx/headless_frontend.cpp", "platform/default/src/mbgl/gl/headless_backend.cpp", "platform/default/src/mbgl/map/map_snapshotter.cpp", "platform/default/src/mbgl/text/bidi.cpp", "platform/default/src/mbgl/util/compression.cpp", + "platform/default/src/mbgl/util/monotonic_timer.cpp", "platform/default/src/mbgl/util/png_writer.cpp", "platform/default/src/mbgl/util/thread_local.cpp", "platform/default/src/mbgl/util/utf.cpp", @@ -103,8 +104,7 @@ "mbgl/gfx/headless_backend.hpp": "platform/default/include/mbgl/gfx/headless_backend.hpp", "mbgl/gfx/headless_frontend.hpp": "platform/default/include/mbgl/gfx/headless_frontend.hpp", "mbgl/gl/headless_backend.hpp": "platform/default/include/mbgl/gl/headless_backend.hpp", - "mbgl/map/map_snapshotter.hpp": "platform/default/include/mbgl/map/map_snapshotter.hpp", - "mbgl/text/unaccent.hpp": "platform/default/include/mbgl/text/unaccent.hpp" + "mbgl/map/map_snapshotter.hpp": "platform/default/include/mbgl/map/map_snapshotter.hpp" }, "private_headers": { "android_renderer_backend.hpp": "platform/android/src/android_renderer_backend.hpp", @@ -145,7 +145,10 @@ "java_types.hpp": "platform/android/src/java_types.hpp", "jni.hpp": "platform/android/src/jni.hpp", "jni_native.hpp": "platform/android/src/jni_native.hpp", + "i18n/collator_jni.hpp": "platform/android/src/i18n/collator_jni.hpp", + "i18n/number_format_jni.hpp": "platform/android/src/i18n/number_format_jni.hpp", "logger.hpp": "platform/android/src/logger.hpp", + "mapbox.hpp": "platform/android/src/mapbox.hpp", "map/camera_position.hpp": "platform/android/src/map/camera_position.hpp", "map/image.hpp": "platform/android/src/map/image.hpp", "map_renderer.hpp": "platform/android/src/map_renderer.hpp", @@ -187,7 +190,6 @@ "style/sources/vector_source.hpp": "platform/android/src/style/sources/vector_source.hpp", "style/transition_options.hpp": "platform/android/src/style/transition_options.hpp", "style/value.hpp": "platform/android/src/style/value.hpp", - "text/collator_jni.hpp": "platform/android/src/text/collator_jni.hpp", "text/local_glyph_rasterizer_jni.hpp": "platform/android/src/text/local_glyph_rasterizer_jni.hpp" } } diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js index fa814f89af..83fb5c116e 100755 --- a/platform/android/scripts/generate-style-code.js +++ b/platform/android/scripts/generate-style-code.js @@ -72,6 +72,7 @@ global.propertyType = function propertyType(property) { case 'formatted': return 'Formatted'; case 'string': + case 'image': // TODO: replace once we implement image expressions return 'String'; case 'enum': return 'String'; @@ -93,6 +94,7 @@ global.propertyJavaType = function propertyType(property) { case 'formatted': return 'Formatted'; case 'string': + case 'image': // TODO: replace once we implement image expressions return 'String'; case 'enum': return 'String'; @@ -141,6 +143,7 @@ global.propertyNativeType = function (property) { return 'float'; case 'formatted': case 'string': + case 'image': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': if(property['light-property']){ @@ -177,6 +180,7 @@ global.defaultExpressionJava = function(property) { case 'formatted': return 'format'; case 'string': + case 'image': // TODO: replace once we implement image expressions return "string"; case 'enum': return "string"; @@ -203,6 +207,7 @@ global.defaultValueJava = function(property) { case 'formatted': return 'new Formatted(new FormattedSection("default"))' case 'string': + case 'image': // TODO: replace once we implement image expressions return '"' + property['default'] + '"'; case 'enum': return snakeCaseUpper(property.name) + "_" + snakeCaseUpper(Object.keys(property.values)[0]); @@ -335,6 +340,7 @@ global.evaluatedType = function (property) { return 'float'; case 'formatted': case 'string': + case 'image': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': return (isLightProperty(property) ? 'Light' : '') + `${camelize(property.name)}Type`; diff --git a/platform/android/src/async_task.cpp b/platform/android/src/async_task.cpp index 6c14e96fa6..0a4d90a275 100644 --- a/platform/android/src/async_task.cpp +++ b/platform/android/src/async_task.cpp @@ -16,6 +16,7 @@ public: } ~Impl() { + queued = true; loop->removeRunnable(this); } @@ -31,9 +32,11 @@ public: } void runTask() override { - loop->removeRunnable(this); - queued = true; - task(); + if (!queued) { + queued = true; + loop->removeRunnable(this); + task(); + } } private: diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 5f61aadba0..a002d6616f 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -1,5 +1,7 @@ #include "file_source.hpp" + #include "attach_env.hpp" +#include "mapbox.hpp" #include <mbgl/actor/actor.hpp> #include <mbgl/actor/scheduler.hpp> @@ -14,8 +16,15 @@ namespace mbgl { std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) { - auto* assetFileSource = reinterpret_cast<AssetManagerFileSource*>(options.platformContext()); - auto fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), std::unique_ptr<AssetManagerFileSource>(assetFileSource)); + auto env{android::AttachEnv()}; + std::shared_ptr<DefaultFileSource> fileSource; + if (android::Mapbox::hasInstance(*env)) { + auto assetManager = android::Mapbox::getAssetManager(*env); + fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), + std::make_unique<AssetManagerFileSource>(*env, assetManager)); + } else { + fileSource = std::make_shared<DefaultFileSource>(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>& assetManager) { +FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath) { std::string path = jni::Make<std::string>(_env, _cachePath); mapbox::sqlite::setTempPath(path); - resourceOptions - .withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "") - .withCachePath(path + DATABASE_FILE) - .withPlatformContext(reinterpret_cast<void*>(new AssetManagerFileSource(_env, assetManager))); + resourceOptions.withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "") + .withCachePath(path + DATABASE_FILE); // Create a core default file source fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(resourceOptions)); @@ -171,20 +175,20 @@ void FileSource::registerNative(jni::JNIEnv& env) { #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<FileSource>( - env, javaClass, "nativePtr", - jni::MakePeer<FileSource, const jni::String&, const jni::String&, const jni::Object<AssetManager>&>, - "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<FileSource>(env, + javaClass, + "nativePtr", + jni::MakePeer<FileSource, const jni::String&, const jni::String&>, + "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/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index f3ad33eb31..6a9190fa06 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -41,7 +41,7 @@ public: const jni::String&); }; - FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object<AssetManager>&); + FileSource(jni::JNIEnv&, const jni::String&, const jni::String&); ~FileSource(); diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index 8d30404a50..afbf1ee11e 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -10,7 +10,7 @@ namespace geojson { using namespace gson; -mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) { +mbgl::GeoJSONFeature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) { static auto& javaClass = jni::Class<Feature>::Singleton(env); static auto id = javaClass.GetMethod<jni::String ()>(env, "id"); static auto geometry = javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry"); @@ -20,11 +20,9 @@ mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFe using mbid = mapbox::feature::identifier; - return mbgl::Feature { - Geometry::convert(env, jFeature.Call(env, geometry)), - JsonObject::convert(env, jFeature.Call(env, properties)), - jId ? mbid { jni::Make<std::string>(env, jId) } : mbid { mapbox::feature::null_value } - }; + return mbgl::GeoJSONFeature{Geometry::convert(env, jFeature.Call(env, geometry)), + JsonObject::convert(env, jFeature.Call(env, properties)), + jId ? mbid{jni::Make<std::string>(env, jId)} : mbid{mapbox::feature::null_value}}; } /** @@ -50,7 +48,7 @@ public: } }; -jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { +jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::GeoJSONFeature& value) { static auto& javaClass = jni::Class<Feature>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(env, "fromGeometry"); @@ -63,7 +61,18 @@ jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::Fe jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) { auto features = jni::Array<jni::Object<Feature>>::New(env, value.size()); - for (size_t i = 0; i < value.size(); i = i + 1) { + for (size_t i = 0; i < value.size(); ++i) { + features.Set(env, i, convertFeature(env, static_cast<mbgl::GeoJSONFeature>(value.at(i)))); + } + + return features; +} + +jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env, + const std::vector<mbgl::GeoJSONFeature>& value) { + auto features = jni::Array<jni::Object<Feature>>::New(env, value.size()); + + for (size_t i = 0; i < value.size(); ++i) { features.Set(env, i, convertFeature(env, value.at(i))); } diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp index fdf5d977ba..aee45262e3 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -12,8 +12,9 @@ class Feature { public: static constexpr auto Name() { return "com/mapbox/geojson/Feature"; }; - static mbgl::Feature convert(jni::JNIEnv&, const jni::Object<Feature>&); + static mbgl::GeoJSONFeature convert(jni::JNIEnv&, const jni::Object<Feature>&); static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::Feature>&); + static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::GeoJSONFeature>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/i18n/collator.cpp index acb4f36ee1..b3dd8e21b3 100644 --- a/platform/android/src/text/collator.cpp +++ b/platform/android/src/i18n/collator.cpp @@ -1,8 +1,5 @@ -#include <mbgl/style/expression/collator.hpp> +#include <mbgl/i18n/collator.hpp> #include <mbgl/text/language_tag.hpp> -#include <mbgl/util/platform.hpp> - -#include <mbgl/text/unaccent.hpp> #include <jni/jni.hpp> @@ -96,8 +93,7 @@ jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& } // namespace android -namespace style { -namespace expression { +namespace platform { class Collator::Impl { public: @@ -144,12 +140,12 @@ public: // 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<jni::String> jlhs = jni::Make<jni::String>(*env, useUnaccent ? - platform::unaccent(lhs) : - lhs); - jni::Local<jni::String> jrhs = jni::Make<jni::String>(*env, useUnaccent ? - platform::unaccent(rhs) : - rhs); + jni::Local<jni::String> jlhs = useUnaccent + ? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, lhs)) + : jni::Make<jni::String>(*env, lhs); + jni::Local<jni::String> jrhs = useUnaccent + ? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, rhs)) + : jni::Make<jni::String>(*env, rhs); jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs); @@ -194,6 +190,5 @@ std::string Collator::resolvedLocale() const { return impl->resolvedLocale(); } -} // namespace expression -} // namespace style +} // namespace platform } // namespace mbgl diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/i18n/collator_jni.hpp index dd3f845662..612f9b49f3 100644 --- a/platform/android/src/text/collator_jni.hpp +++ b/platform/android/src/i18n/collator_jni.hpp @@ -1,7 +1,5 @@ #pragma once -#include <mbgl/util/image.hpp> - #include <jni/jni.hpp> /* diff --git a/platform/android/src/text/format_number.cpp b/platform/android/src/i18n/number_format.cpp index 3a41175ecc..c8e0b70562 100644 --- a/platform/android/src/text/format_number.cpp +++ b/platform/android/src/i18n/number_format.cpp @@ -1,11 +1,10 @@ -#include <mbgl/style/expression/collator.hpp> +#include <mbgl/i18n/number_format.hpp> #include <mbgl/text/language_tag.hpp> -#include <mbgl/util/platform.hpp> #include <jni/jni.hpp> #include "../attach_env.hpp" -#include "format_number_jni.hpp" +#include "number_format_jni.hpp" namespace mbgl { namespace android { diff --git a/platform/android/src/text/format_number_jni.hpp b/platform/android/src/i18n/number_format_jni.hpp index 1720038925..1720038925 100644 --- a/platform/android/src/text/format_number_jni.hpp +++ b/platform/android/src/i18n/number_format_jni.hpp diff --git a/platform/android/src/jni_native.cpp b/platform/android/src/jni_native.cpp index df96ba9759..bcbdfcf484 100755..100644 --- a/platform/android/src/jni_native.cpp +++ b/platform/android/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/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp index 6be708b994..0c0e907f14 100644 --- a/platform/android/src/map_renderer.cpp +++ b/platform/android/src/map_renderer.cpp @@ -43,7 +43,7 @@ ActorRef<Renderer> MapRenderer::actor() const { return *rendererRef; } -void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) { +void MapRenderer::schedule(std::function<void()> scheduled) { // Create a runnable android::UniqueEnv _env = android::AttachEnv(); auto runnable = std::make_unique<MapRendererRunnable>(*_env, std::move(scheduled)); diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp index 5a8ddeeb91..047f1870c7 100644 --- a/platform/android/src/map_renderer.hpp +++ b/platform/android/src/map_renderer.hpp @@ -67,7 +67,8 @@ public: // From Scheduler. Schedules by using callbacks to the // JVM to process the mailbox on the right thread. - void schedule(std::weak_ptr<Mailbox> scheduled) override; + void schedule(std::function<void()> scheduled) override; + mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); } void requestRender(); @@ -122,6 +123,7 @@ private: std::atomic<bool> destroyed {false}; std::unique_ptr<SnapshotCallback> snapshotCallback; + mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this}; }; } // namespace android diff --git a/platform/android/src/map_renderer_runnable.cpp b/platform/android/src/map_renderer_runnable.cpp index 77c3aa301d..227f49ee3f 100644 --- a/platform/android/src/map_renderer_runnable.cpp +++ b/platform/android/src/map_renderer_runnable.cpp @@ -5,9 +5,8 @@ namespace mbgl { namespace android { -MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr<Mailbox> mailbox_) - : mailbox(std::move(mailbox_)) { - +MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::function<void()> 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<Mailbox MapRendererRunnable::~MapRendererRunnable() = default; void MapRendererRunnable::run(jni::JNIEnv&) { - Mailbox::maybeReceive(mailbox); + if (function) function(); } jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() { diff --git a/platform/android/src/map_renderer_runnable.hpp b/platform/android/src/map_renderer_runnable.hpp index 21c4369b69..24d0f2af49 100644 --- a/platform/android/src/map_renderer_runnable.hpp +++ b/platform/android/src/map_renderer_runnable.hpp @@ -24,7 +24,7 @@ public: static void registerNative(jni::JNIEnv&); - MapRendererRunnable(jni::JNIEnv&, std::weak_ptr<Mailbox>); + MapRendererRunnable(jni::JNIEnv&, std::function<void()>); // Only for jni registration, unused MapRendererRunnable(jni::JNIEnv&) { @@ -40,7 +40,7 @@ public: private: jni::Global<jni::Object<MapRendererRunnable>> javaPeer; - std::weak_ptr<Mailbox> mailbox; + std::function<void()> function; }; } // namespace android diff --git a/platform/android/src/mapbox.cpp b/platform/android/src/mapbox.cpp new file mode 100644 index 0000000000..5246739cf6 --- /dev/null +++ b/platform/android/src/mapbox.cpp @@ -0,0 +1,23 @@ +#include "mapbox.hpp" + +namespace mbgl { +namespace android { + +jni::Local<jni::Object<AssetManager>> Mapbox::getAssetManager(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<Mapbox>::Singleton(env); + auto method = javaClass.GetStaticMethod<jni::Object<AssetManager>()>(env, "getAssetManager"); + return javaClass.Call(env, method); +} + +jboolean Mapbox::hasInstance(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<Mapbox>::Singleton(env); + auto method = javaClass.GetStaticMethod<jboolean()>(env, "hasInstance"); + return javaClass.Call(env, method); +} + +void Mapbox::registerNative(jni::JNIEnv& env) { + jni::Class<Mapbox>::Singleton(env); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/mapbox.hpp b/platform/android/src/mapbox.hpp new file mode 100644 index 0000000000..813f5bf174 --- /dev/null +++ b/platform/android/src/mapbox.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "asset_manager.hpp" + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class Mapbox { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/Mapbox"; }; + static jboolean hasInstance(jni::JNIEnv&); + static jni::Local<jni::Object<AssetManager>> getAssetManager(jni::JNIEnv&); + static void registerNative(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 7b87693cf5..8cb637fa38 100755..100644 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/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 "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/image.hpp" +#include "map_renderer.hpp" +#include "run_loop_impl.hpp" #include "style/light.hpp" -#include "bitmap_factory.hpp" namespace mbgl { namespace android { @@ -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<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<NativeMapView>(env, javaClass, "nativePtr", - jni::MakePeer<NativeMapView, const jni::Object<NativeMapView>&, const jni::Object<FileSource>&, const jni::Object<MapRenderer>&, 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<NativeMapView>( + env, + javaClass, + "nativePtr", + jni::MakePeer<NativeMapView, + const jni::Object<NativeMapView>&, + const jni::Object<FileSource>&, + const jni::Object<MapRenderer>&, + 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/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index ba2178022e..5a340d1287 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -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/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index 5ff4864275..0eece4b1ad 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -44,18 +44,16 @@ namespace android { } GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<>& options) - : Source(env, std::make_unique<mbgl::style::GeoJSONSource>( - jni::Make<std::string>(env, sourceId), - convertGeoJSONOptions(env, options))) - , converter(std::make_unique<Actor<FeatureConverter>>(Scheduler::GetBackground())) { - } + : Source(env, + std::make_unique<mbgl::style::GeoJSONSource>(jni::Make<std::string>(env, sourceId), + convertGeoJSONOptions(env, options))), + converter(std::make_unique<Actor<FeatureConverter>>(Scheduler::GetBackground(), + source.as<style::GeoJSONSource>()->getOptions())) {} - GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, - mbgl::style::Source& coreSource, - AndroidRendererFrontend& frontend) - : Source(env, coreSource, createJavaPeer(env), frontend) - , converter(std::make_unique<Actor<FeatureConverter>>(Scheduler::GetBackground())) { - } + GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend), + converter(std::make_unique<Actor<FeatureConverter>>(Scheduler::GetBackground(), + source.as<style::GeoJSONSource>()->getOptions())) {} GeoJSONSource::~GeoJSONSource() = default; @@ -63,7 +61,7 @@ namespace android { std::shared_ptr<std::string> json = std::make_shared<std::string>(jni::Make<std::string>(env, jString)); - Update::Converter converterFn = [this, json](ActorRef<Callback> _callback) { + Update::Converter converterFn = [this, json](ActorRef<GeoJSONDataCallback> _callback) { converter->self().invoke(&FeatureConverter::convertJson, json, _callback); }; @@ -84,11 +82,11 @@ namespace android { void GeoJSONSource::setURL(jni::JNIEnv& env, const jni::String& url) { // Update the core source - source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url)); + source.as<style::GeoJSONSource>()->setURL(jni::Make<std::string>(env, url)); } jni::Local<jni::String> GeoJSONSource::getURL(jni::JNIEnv& env) { - optional<std::string> url = source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getURL(); + optional<std::string> url = source.as<style::GeoJSONSource>()->getURL(); return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>(); } @@ -166,7 +164,7 @@ namespace android { auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, jObject); auto object = std::make_shared<decltype(global)>(std::move(global)); - Update::Converter converterFn = [this, object](ActorRef<Callback> _callback) { + Update::Converter converterFn = [this, object](ActorRef<GeoJSONDataCallback> _callback) { converter->self().invoke(&FeatureConverter::convertObject<JNIType>, object, _callback); }; @@ -175,25 +173,23 @@ namespace android { void GeoJSONSource::setAsync(Update::Converter converterFn) { awaitingUpdate = std::make_unique<Update>( - std::move(converterFn), - std::make_unique<Actor<Callback>>( - *Scheduler::GetCurrent(), - [this](GeoJSON geoJSON) { - // conversion from Java features to core ones finished - android::UniqueEnv _env = android::AttachEnv(); - - // Update the core source - source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(geoJSON); - - // if there is an awaiting update, execute it, otherwise, release resources - if (awaitingUpdate) { - update = std::move(awaitingUpdate); - update->converterFn(update->callback->self()); - } else { - update.reset(); - } - }) - ); + std::move(converterFn), + std::make_unique<Actor<GeoJSONDataCallback>>( + *Scheduler::GetCurrent(), [this](std::shared_ptr<style::GeoJSONData> geoJSONData) { + // conversion from Java features to core ones finished + android::UniqueEnv _env = android::AttachEnv(); + + // Update the core source + source.as<mbgl::style::GeoJSONSource>()->setGeoJSONData(std::move(geoJSONData)); + + // if there is an awaiting update, execute it, otherwise, release resources + if (awaitingUpdate) { + update = std::move(awaitingUpdate); + update->converterFn(update->callback->self()); + } else { + update.reset(); + } + })); // If another update is running, wait if (update) { @@ -230,12 +226,10 @@ namespace android { ); } - void FeatureConverter::convertJson(std::shared_ptr<std::string> json, - ActorRef<Callback> callback) { + void FeatureConverter::convertJson(std::shared_ptr<std::string> json, ActorRef<GeoJSONDataCallback> callback) { using namespace mbgl::style::conversion; android::UniqueEnv _env = android::AttachEnv(); - // Convert the jni object Error error; optional<GeoJSON> converted = parseGeoJSON(*json, error); @@ -243,23 +237,23 @@ namespace android { mbgl::Log::Error(mbgl::Event::JNI, "Error setting geo json: " + error.message); return; } - - callback.invoke(&Callback::operator(), *converted); + callback.invoke(&GeoJSONDataCallback::operator(), style::GeoJSONData::create(*converted, options)); } template <class JNIType> - void FeatureConverter::convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>> jObject, ActorRef<Callback> callback) { + void FeatureConverter::convertObject( + std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>> jObject, + ActorRef<GeoJSONDataCallback> callback) { using namespace mbgl::android::geojson; android::UniqueEnv _env = android::AttachEnv(); // Convert the jni object auto geometry = JNIType::convert(*_env, *jObject); - callback.invoke(&Callback::operator(), GeoJSON(geometry)); + callback.invoke(&GeoJSONDataCallback::operator(), style::GeoJSONData::create(geometry, options)); } - Update::Update(Converter _converterFn, std::unique_ptr<Actor<Callback>> _callback) - : converterFn(std::move(_converterFn)) - , callback(std::move(_callback)) {} + Update::Update(Converter _converterFn, std::unique_ptr<Actor<GeoJSONDataCallback>> _callback) + : converterFn(std::move(_converterFn)), callback(std::move(_callback)) {} } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index e737e41924..e506191ceb 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -11,22 +11,28 @@ namespace mbgl { namespace android { -using Callback = std::function<void (GeoJSON)>; +using GeoJSONDataCallback = std::function<void(std::shared_ptr<style::GeoJSONData>)>; -struct FeatureConverter { - void convertJson(std::shared_ptr<std::string>, ActorRef<Callback>); +class FeatureConverter { +public: + explicit FeatureConverter(style::GeoJSONOptions options_) : options(std::move(options_)) {} + void convertJson(std::shared_ptr<std::string>, ActorRef<GeoJSONDataCallback>); template <class JNIType> - void convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>>, ActorRef<Callback>); + void convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>>, + ActorRef<GeoJSONDataCallback>); + +private: + style::GeoJSONOptions options; }; struct Update { - using Converter = std::function<void (ActorRef<Callback>)>; + using Converter = std::function<void(ActorRef<GeoJSONDataCallback>)>; Converter converterFn; - std::unique_ptr<Actor<Callback>> callback; + std::unique_ptr<Actor<GeoJSONDataCallback>> callback; - Update(Converter, std::unique_ptr<Actor<Callback>>); + Update(Converter, std::unique_ptr<Actor<GeoJSONDataCallback>>); }; class GeoJSONSource : public Source { diff --git a/platform/android/src/test/render_test_collator.cpp b/platform/android/src/test/render_test_collator.cpp new file mode 100644 index 0000000000..e6e3b27b48 --- /dev/null +++ b/platform/android/src/test/render_test_collator.cpp @@ -0,0 +1,40 @@ +#include <mbgl/i18n/collator.hpp> + +#include <memory> + +namespace mbgl { +namespace platform { + +class Collator::Impl { +public: + Impl(bool caseSensitive_, bool diacriticSensitive_, optional<std::string>) + : caseSensitive(caseSensitive_), diacriticSensitive(diacriticSensitive_) {} + + bool operator==(const Impl& other) const { return true; } + + int compare(const std::string& lhs, const std::string& rhs) const { return 0; } + + std::string resolvedLocale() const { return ""; } + +private: + bool caseSensitive; + bool diacriticSensitive; +}; + +Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale_) + : impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, std::move(locale_))) {} + +int Collator::compare(const std::string& lhs, const std::string& rhs) const { + return impl->compare(lhs, rhs); +} + +bool Collator::operator==(const Collator& other) const { + return *impl == *(other.impl); +} + +std::string Collator::resolvedLocale() const { + return impl->resolvedLocale(); +} + +} // namespace platform +} // namespace mbgl diff --git a/platform/android/src/test/render_test_number_format.cpp b/platform/android/src/test/render_test_number_format.cpp new file mode 100644 index 0000000000..57710c8558 --- /dev/null +++ b/platform/android/src/test/render_test_number_format.cpp @@ -0,0 +1,15 @@ +#include <mbgl/i18n/number_format.hpp> + +namespace mbgl { +namespace platform { + +std::string formatNumber(double /*number*/, + const std::string& /*localeId */, + const std::string& /*currency*/, + uint8_t /*minFractionDigits*/, + uint8_t /*maxFractionDigits*/) { + return ""; +} + +} // namespace platform +} // namespace mbgl diff --git a/platform/android/src/test/render_test_runner.cpp b/platform/android/src/test/render_test_runner.cpp new file mode 100644 index 0000000000..d4554aa9de --- /dev/null +++ b/platform/android/src/test/render_test_runner.cpp @@ -0,0 +1,57 @@ +#include <android_native_app_glue.h> +#include <mbgl/render_test.hpp> +#include "jni.hpp" +#include "logger.hpp" + +#include <string> +#include <vector> + +#include <mbgl/util/logging.hpp> + +#include <android/log.h> + +namespace mbgl { + +namespace { + +int severityToPriority(EventSeverity severity) { + switch (severity) { + case EventSeverity::Debug: + return ANDROID_LOG_DEBUG; + + case EventSeverity::Info: + return ANDROID_LOG_INFO; + + case EventSeverity::Warning: + return ANDROID_LOG_WARN; + + case EventSeverity::Error: + return ANDROID_LOG_ERROR; + + default: + return ANDROID_LOG_VERBOSE; + } +} + +} // namespace + +void Log::platformRecord(EventSeverity severity, const std::string& msg) { + __android_log_print(severityToPriority(severity), "mbgl", "%s", msg.c_str()); +} + +} // namespace mbgl + +void android_main(struct android_app* app) { + mbgl::android::theJVM = app->activity->vm; + JNIEnv* env; + app->activity->vm->AttachCurrentThread(&env, NULL); + + std::vector<std::string> arguments = {"mbgl-render-test-runner", "-p", "/sdcard/render-test/android-manifest.json"}; + std::vector<char*> argv; + for (const auto& arg : arguments) { + argv.push_back((char*)arg.data()); + } + argv.push_back(nullptr); + (void)mbgl::runRenderTests(argv.size() - 1, argv.data()); + app->activity->vm->DetachCurrentThread(); +}
\ No newline at end of file diff --git a/platform/android/src/timer.cpp b/platform/android/src/timer.cpp index a45c48702e..1d3d05c843 100644 --- a/platform/android/src/timer.cpp +++ b/platform/android/src/timer.cpp @@ -3,6 +3,7 @@ #include <mbgl/util/run_loop.hpp> #include <mbgl/util/timer.hpp> +#include <atomic> #include <functional> namespace mbgl { @@ -10,7 +11,7 @@ namespace util { class Timer::Impl : public RunLoop::Impl::Runnable { public: - Impl() = default; + Impl() : active(false) {} ~Impl() { stop(); @@ -25,9 +26,11 @@ public: due = (timeout == Duration::max()) ? std::chrono::time_point<Clock>::max() : Clock::now() + timeout; loop->addRunnable(this); + active = true; } void stop() { + active = false; loop->removeRunnable(this); } @@ -45,8 +48,10 @@ public: } void runTask() override { - reschedule(); - task(); + if (active) { + reschedule(); + task(); + } } private: @@ -56,6 +61,7 @@ private: RunLoop::Impl* loop = reinterpret_cast<RunLoop::Impl*>(RunLoop::getLoopHandle()); std::function<void()> task; + std::atomic<bool> active; }; Timer::Timer() : impl(std::make_unique<Impl>()) { diff --git a/platform/android/src/unaccent.cpp b/platform/android/src/unaccent.cpp deleted file mode 100644 index 8da0ce4931..0000000000 --- a/platform/android/src/unaccent.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include <mbgl/text/unaccent.hpp> -#include <string> -#include "attach_env.hpp" -#include "text/collator_jni.hpp" -#include <jni/jni.hpp> - -namespace mbgl { -namespace platform { - -std::string unaccent(const std::string& str) { - android::UniqueEnv env = android::AttachEnv(); - jni::Local<jni::String> input = jni::Make<jni::String>(*env, str); - jni::Local<jni::String> unaccented = android::StringUtils::unaccent(*env, input); - return jni::Make<std::string>(*env, unaccented); -} - -} // namespace platform -} // namespace mbgl |