From 08d1398b70769268a809a767c1bd22e37d164c6f Mon Sep 17 00:00:00 2001
From: Kevin Li
Date: Wed, 25 Mar 2020 09:59:38 +0800
Subject: [PATCH 1/5] Add runtime styling APIs on MapSnapshotter (#268)
* Add styleable snapshotter.
* Add style API for snapshotter
* Add observer interface to snapshotter
* WIP Add styling to snapshotter activity
* Update interface and implement addlayer functions.
* Deprecate methods instead of removing
* Implement addSource functions.
* Implement addImage function
* Still use the previous callback interface.
* Expose onStyleDidloaded interface
* Add setStyle method
* Start native snapshotter from start method
* Fix snapshotter test.
* Fix check style
* Keep the original interface
* Update gl-native
* Add demo for snapshotter heatmap layer
* bump gl-native
Co-authored-by: Alexander Shalamov
(cherry picked from commit da6d8a2b06e61bc9a5f72774a6ca5eeddd717329)
---
.../java/com/mapbox/mapboxsdk/maps/Image.java | 2 +-
.../com/mapbox/mapboxsdk/maps/MapboxMap.java | 20 +-
.../com/mapbox/mapboxsdk/maps/NativeMap.java | 2 +
.../mapbox/mapboxsdk/maps/NativeMapView.java | 8 +
.../java/com/mapbox/mapboxsdk/maps/Style.java | 56 +++--
.../mapboxsdk/snapshotter/MapSnapshotter.java | 204 +++++++++++++++---
.../mapboxsdk/style/layers/CustomLayer.java | 17 +-
.../snapshotter/MapSnapshotterTest.kt | 14 +-
.../src/main/AndroidManifest.xml | 18 +-
.../customlayer/CustomLayerActivity.java | 4 +-
.../activity/render/RenderTestDefinition.java | 3 +-
.../snapshot/MapSnapshotterActivity.java | 96 ++++++++-
... MapSnapshotterBitMapOverlayActivity.java} | 17 +-
.../MapSnapshotterHeatMapActivity.java | 174 +++++++++++++++
.../MapSnapshotterLocalStyleActivity.java | 3 +-
.../snapshot/MapSnapshotterReuseActivity.java | 7 +-
.../src/main/res/values/descriptions.xml | 3 +-
.../src/main/res/values/titles.xml | 3 +-
vendor/mapbox-gl-native | 2 +-
19 files changed, 565 insertions(+), 88 deletions(-)
rename MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/{MapSnapshotterMarkerActivity.java => MapSnapshotterBitMapOverlayActivity.java} (92%)
create mode 100644 MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterHeatMapActivity.java
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
index 73ead3bc0..380f78b07 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
@@ -3,7 +3,7 @@
import androidx.annotation.Keep;
@Keep
-class Image {
+public class Image {
private final byte[] buffer;
private final float pixelRatio;
private final String name;
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 286e48fe8..f50b1a394 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
@@ -5,12 +5,6 @@
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Bundle;
-import androidx.annotation.FloatRange;
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.Size;
-import androidx.annotation.UiThread;
import android.text.TextUtils;
import android.view.View;
@@ -44,6 +38,13 @@
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.Size;
+import androidx.annotation.UiThread;
+
/**
* The general class to interact with in the Android Mapbox SDK. It exposes the entry point for all
* methods related to the MapView. You cannot instantiate {@link MapboxMap} object directly, rather,
@@ -93,6 +94,13 @@ public final class MapboxMap {
this.developerAnimationStartedListeners = developerAnimationStartedListeners;
}
+ /**
+ * Trigger the mapview to repaint.
+ */
+ public void triggerRepaint() {
+ nativeMapView.triggerRepaint();
+ }
+
void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) {
transform.initialise(this, options);
uiSettings.initialise(context, options);
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 81ff438c6..2b93fa8c6 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java
@@ -237,6 +237,8 @@ List queryRenderedFeatures(@NonNull RectF coordinates,
float getPixelRatio();
+ void triggerRepaint();
+
//
// Deprecated Annotations API
//
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 05ebf36d6..8ff484f10 100755
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -1003,6 +1003,11 @@ public float getPixelRatio() {
return pixelRatio;
}
+ @Override
+ public void triggerRepaint() {
+ nativeTriggerRepaint();
+ }
+
@NonNull
@Override
public RectF getDensityDependantRectangle(final RectF rectangle) {
@@ -1476,6 +1481,9 @@ public long getNativePtr() {
return nativePtr;
}
+ @Keep
+ private native void nativeTriggerRepaint();
+
//
// Snapshot
//
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
index 31c1ae982..fe88e081a 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
@@ -340,7 +340,7 @@ public void addImage(@NonNull String name, @NonNull Drawable drawable) {
*/
public void addImage(@NonNull final String name, @NonNull Bitmap bitmap, boolean sdf) {
validateState("addImage");
- nativeMap.addImages(new Image[]{toImage(new Builder.ImageWrapper(name, bitmap, sdf))});
+ nativeMap.addImages(new Image[] {toImage(new Builder.ImageWrapper(name, bitmap, sdf))});
}
/**
@@ -932,23 +932,23 @@ public Builder withBitmapImages(boolean sdf, @NonNull Pair... va
return this;
}
- String getUri() {
+ public String getUri() {
return styleUri;
}
- String getJson() {
+ public String getJson() {
return styleJson;
}
- List
+ *
* @param fontFamily font family for local ideograph generation.
* @return the mutated {@link Options}
*/
@@ -204,6 +231,7 @@ public Options withLocalIdeographFontFamily(String fontFamily) {
* '/system/etc/fonts.xml'. Default font for local ideograph font family is
* {@link MapboxConstants#DEFAULT_FONT}.
*
+ *
* @param fontFamilies font families for local ideograph generation.
* @return the mutated {@link Options}
*/
@@ -274,14 +302,22 @@ public LatLngBounds getRegion() {
*/
@Deprecated
public String getStyleUrl() {
- return styleUri;
+ return builder == null ? Style.MAPBOX_STREETS : builder.getUri();
}
/**
* @return the style uri
*/
public String getStyleUri() {
- return styleUri;
+ return builder == null ? Style.MAPBOX_STREETS : builder.getUri();
+ }
+
+ /**
+ * @return the style json
+ */
+ @Nullable
+ public String getStyleJson() {
+ return builder == null ? null : builder.getJson();
}
/**
@@ -329,6 +365,7 @@ public String getApiBaseUri() {
public MapSnapshotter(@NonNull Context context, @NonNull Options options) {
checkThread();
this.context = context.getApplicationContext();
+ this.options = options;
TelemetryDefinition telemetry = Mapbox.getTelemetry();
if (telemetry != null) {
telemetry.onAppUserTurnstileEvent();
@@ -340,10 +377,11 @@ public MapSnapshotter(@NonNull Context context, @NonNull Options options) {
}
nativeInitialize(this, fileSource, options.pixelRatio, options.width,
- options.height, options.styleUri, options.styleJson, options.region, options.cameraPosition,
+ options.height, options.getStyleUri(), options.getStyleJson(), options.region, options.cameraPosition,
options.showLogo, options.localIdeographFontFamily);
}
+
/**
* Starts loading and rendering the snapshot. The callback will be fired
* on the calling thread.
@@ -412,6 +450,57 @@ public void start(@NonNull SnapshotReadyCallback callback, ErrorHandler errorHan
@Keep
public native void setStyleJson(String styleJson);
+ /**
+ * Adds the layer to the map. The layer must be newly created and not added to the snapshotter before
+ *
+ * @param layer the layer to add
+ * @param below the layer id to add this layer before
+ */
+ private void addLayerBelow(Layer layer, String below) {
+ nativeAddLayerBelow(layer.getNativePtr(), below);
+ }
+
+ /**
+ * Adds the layer to the map. The layer must be newly created and not added to the snapshotter before
+ *
+ * @param layer the layer to add
+ * @param above the layer id to add this layer above
+ */
+ private void addLayerAbove(@NonNull Layer layer, @NonNull String above) {
+ nativeAddLayerAbove(layer.getNativePtr(), above);
+ }
+
+ /**
+ * Adds the layer to the snapshotter at the specified index. The layer must be newly
+ * created and not added to the snapshotter before
+ *
+ * @param layer the layer to add
+ * @param index the index to insert the layer at
+ */
+ private void addLayerAt(Layer layer, int index) {
+ nativeAddLayerAt(layer.getNativePtr(), index);
+ }
+
+ /**
+ * Adds the source to the map. The source must be newly created and not added to the map before
+ *
+ * @param source the source to add
+ */
+ private void addSource(Source source) {
+ nativeAddSource(source, source.getNativePtr());
+ }
+
+ /**
+ * Adds an image to be used in the snapshotter's style
+ *
+ * @param name the name of the image
+ * @param bitmap the pre-multiplied Bitmap
+ * @param sdf the flag indicating image is an SDF or template image
+ */
+ private void addImage(@NonNull final String name, @NonNull Bitmap bitmap, boolean sdf) {
+ nativeAddImages(new Image[] {toImage(new Style.Builder.ImageWrapper(name, bitmap, sdf))});
+ }
+
/**
* Must be called in on the thread
* the object was created on.
@@ -609,6 +698,54 @@ protected void onSnapshotFailed(String reason) {
}
}
+ /**
+ * Called by JNI peer when snapshot style is ready.
+ */
+ @Keep
+ protected void onDidFailLoadingStyle(String reason) {
+ onSnapshotFailed(reason);
+ }
+
+ /**
+ * Called by JNI peer when snapshot style is loaded.
+ */
+ @Keep
+ protected void onDidFinishLoadingStyle() {
+ if (!fullyLoaded) {
+ fullyLoaded = true;
+ Style.Builder builder = options.getBuilder();
+ if (builder != null) {
+ for (Source source : builder.getSources()) {
+ nativeAddSource(source, source.getNativePtr());
+ }
+
+ for (Style.Builder.LayerWrapper layerWrapper : builder.getLayers()) {
+ if (layerWrapper instanceof Style.Builder.LayerAtWrapper) {
+ addLayerAt(layerWrapper.getLayer(), ((Style.Builder.LayerAtWrapper) layerWrapper).getIndex());
+ } else if (layerWrapper instanceof Style.Builder.LayerAboveWrapper) {
+ addLayerAbove(layerWrapper.getLayer(), ((Style.Builder.LayerAboveWrapper) layerWrapper).getAboveLayer());
+ } else if (layerWrapper instanceof Style.Builder.LayerBelowWrapper) {
+ addLayerBelow(layerWrapper.getLayer(), ((Style.Builder.LayerBelowWrapper) layerWrapper).getBelowLayer());
+ } else {
+ addLayerBelow(layerWrapper.getLayer(), MapboxConstants.LAYER_ID_ANNOTATIONS);
+ }
+ }
+
+ for (Style.Builder.ImageWrapper image : builder.getImages()) {
+ addImage(image.getId(), image.getBitmap(), image.isSdf());
+ }
+ }
+ }
+ }
+
+ /**
+ * Called by JNI peer when snapshot style image is missing.
+ */
+ @Keep
+ protected void onStyleImageMissing(String imageName) {
+ onSnapshotFailed("style image is missing: " + imageName);
+ }
+
private void checkThread() {
ThreadUtils.checkThread(TAG);
}
@@ -631,6 +768,21 @@ protected native void nativeInitialize(MapSnapshotter mapSnapshotter,
@Keep
protected native void nativeCancel();
+ @Keep
+ private native void nativeAddLayerBelow(long layerPtr, String below);
+
+ @Keep
+ private native void nativeAddLayerAbove(long layerPtr, String above);
+
+ @Keep
+ private native void nativeAddLayerAt(long layerPtr, int index);
+
+ @Keep
+ private native void nativeAddSource(Source source, long sourcePtr);
+
+ @Keep
+ private native void nativeAddImages(Image[] images);
+
@Override
@Keep
protected native void finalize() throws Throwable;
@@ -640,7 +792,7 @@ private class Logo {
private Bitmap small;
private float scale;
- public Logo(Bitmap large, Bitmap small, float scale) {
+ Logo(Bitmap large, Bitmap small, float scale) {
this.large = large;
this.small = small;
this.scale = scale;
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java
index 0dd0df0b2..1e5669f59 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java
@@ -15,20 +15,23 @@ public CustomLayer(String id,
initialize(id, host);
}
+ /**
+ * Triggers map re-paint.
+ *
+ * @deprecated Use {@link MapboxMap#triggerRepaint()} instead.
+ */
+ @Deprecated
@Keep
- CustomLayer(long nativePtr) {
- super(nativePtr);
- }
-
public void update() {
- nativeUpdate();
}
@Keep
- protected native void initialize(String id, long host);
+ CustomLayer(long nativePtr) {
+ super(nativePtr);
+ }
@Keep
- protected native void nativeUpdate();
+ protected native void initialize(String id, long host);
@Override
@Keep
diff --git a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt
index 167656610..b87cc4b6f 100644
--- a/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt
+++ b/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt
@@ -5,13 +5,14 @@ import androidx.test.rule.ActivityTestRule
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.style.layers.BackgroundLayer
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import junit.framework.Assert.assertNotNull
import org.junit.Assert
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -20,7 +21,6 @@ import org.junit.runner.RunWith
* Integration test that validates if a snapshotter creation
*/
@RunWith(AndroidJUnit4::class)
-@Ignore("Ignored until https://github.com/mapbox/mapbox-gl-native/issues/11669 is resolved.")
class MapSnapshotterTest {
@Rule
@@ -31,18 +31,22 @@ class MapSnapshotterTest {
@Test
fun mapSnapshotter() {
+ var mapSnapshotter: MapSnapshotter?
rule.activity.runOnUiThread {
+ val bg = BackgroundLayer("rand_tint")
+ bg.setProperties(PropertyFactory.backgroundColor("rgba(255,128,0,0.7)"))
val options = MapSnapshotter.Options(512, 512)
.withPixelRatio(1.0f)
- .withStyle(Style.SATELLITE_STREETS)
+ .withStyleBuilder(Style.Builder().fromUri(Style.SATELLITE_STREETS)
+ .withLayerAbove(bg, "country-label"))
.withCameraPosition(
CameraPosition.Builder()
.zoom(12.0)
.target(LatLng(51.145495, 5.742234))
.build()
)
- val mapSnapshotter = MapSnapshotter(rule.activity, options)
- mapSnapshotter.start({
+ mapSnapshotter = MapSnapshotter(rule.activity, options)
+ mapSnapshotter!!.start({
assertNotNull(it)
assertNotNull(it.bitmap)
countDownLatch.countDown()
diff --git a/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index ee239a6d5..7e2f59d3e 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -363,9 +363,21 @@
android:value=".activity.FeatureOverviewActivity" />
+ android:name=".activity.snapshot.MapSnapshotterBitMapOverlayActivity"
+ android:description="@string/description_map_snapshotter_bitmap_overlay"
+ android:label="@string/activity_map_snapshotter_bitmap_overlay">
+
+
+
+
diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
index 514d362c2..92ee75c20 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
+++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
@@ -68,8 +68,8 @@ private void swapCustomLayer() {
}
private void updateLayer() {
- if (customLayer != null) {
- customLayer.update();
+ if (mapboxMap != null) {
+ mapboxMap.triggerRepaint();
}
}
diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestDefinition.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestDefinition.java
index 3cff4cad5..fbd8251be 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestDefinition.java
+++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestDefinition.java
@@ -1,5 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.render;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
public class RenderTestDefinition {
@@ -75,7 +76,7 @@ public RenderTestStyleDefinition.Test getTest() {
public MapSnapshotter.Options toOptions() {
return new MapSnapshotter
.Options(getWidth(), getHeight())
- .withStyleJson(styleJson)
+ .withStyleBuilder(new Style.Builder().fromJson(styleJson))
.withPixelRatio(getPixelRatio())
.withLogo(false);
}
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 c15cf4f25..c01254862 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
@@ -1,31 +1,64 @@
package com.mapbox.mapboxsdk.testapp.activity.snapshot;
+import android.graphics.Bitmap;
+import android.graphics.Color;
import android.os.Bundle;
-import androidx.appcompat.app.AppCompatActivity;
import android.view.ViewTreeObserver;
import android.widget.GridLayout;
import android.widget.ImageView;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.mapbox.geojson.Feature;
+import com.mapbox.geojson.FeatureCollection;
+import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
+import com.mapbox.mapboxsdk.style.layers.Property;
+import com.mapbox.mapboxsdk.style.layers.RasterLayer;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.style.sources.RasterSource;
+import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.utils.BitmapUtils;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Random;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
import timber.log.Timber;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toBool;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
+
/**
* Test activity showing how to use a the {@link com.mapbox.mapboxsdk.snapshotter.MapSnapshotter}
*/
public class MapSnapshotterActivity extends AppCompatActivity {
-
- private GridLayout grid;
+ private static final String ID_FEATURE_PROPERTY = "id";
+ private static final String SELECTED_FEATURE_PROPERTY = "selected";
+ private static final String TITLE_FEATURE_PROPERTY = "title";
+ // layer & source constants
+ private static final String MARKER_SOURCE = "marker-source";
+ private static final String MARKER_LAYER = "marker-layer";
+
+ public GridLayout grid;
private List snapshotters = new ArrayList<>();
@Override
@@ -58,6 +91,9 @@ private void addSnapshots() {
}
private void startSnapShot(final int row, final int column) {
+ // Optionally the style
+ Style.Builder builder = new Style.Builder()
+ .fromUri((column + row) % 2 == 0 ? Style.MAPBOX_STREETS : Style.DARK);
// Define the dimensions
MapSnapshotter.Options options = new MapSnapshotter.Options(
@@ -66,9 +102,6 @@ private void startSnapShot(final int row, final int column) {
)
// Optionally the pixel ratio
.withPixelRatio(1)
-
- // Optionally the style
- .withStyle((column + row) % 2 == 0 ? Style.MAPBOX_STREETS : Style.DARK)
.withLocalIdeographFontFamily(MapboxConstants.DEFAULT_FONT);
// Optionally the visible region
@@ -88,14 +121,52 @@ private void startSnapShot(final int row, final int column) {
: new LatLng(randomInRange(-80, 80), randomInRange(-160, 160)))
.bearing(randomInRange(0, 360))
.tilt(randomInRange(0, 60))
- .zoom(randomInRange(0, 20))
+ .zoom(randomInRange(0, 10))
+ .padding(1, 1, 1, 1)
+ .build()
+ );
+ }
+ if (row == 0 && column == 0) {
+ // Add a source
+ Source source = new RasterSource("my-raster-source", "mapbox://mapbox.satellite", 512);
+ builder.withLayerAbove(new RasterLayer("satellite-layer", "my-raster-source"), "country-label");
+ builder.withSource(source);
+ } else if (row == 0 && column == 2) {
+
+ Bitmap carBitmap = BitmapUtils.getBitmapFromDrawable(
+ getResources().getDrawable(R.drawable.ic_directions_car_black));
+
+ // marker source
+ FeatureCollection markerCollection = FeatureCollection.fromFeatures(new Feature[] {
+ Feature.fromGeometry(Point.fromLngLat(4.91638, 52.34673), featureProperties("2", "Car"))
+ });
+ Source markerSource = new GeoJsonSource(MARKER_SOURCE, markerCollection);
+
+ // marker layer
+ SymbolLayer markerSymbolLayer = new SymbolLayer(MARKER_LAYER, MARKER_SOURCE)
+ .withProperties(
+ iconImage(get(TITLE_FEATURE_PROPERTY)),
+ iconIgnorePlacement(true),
+ iconAllowOverlap(true),
+ iconSize(switchCase(toBool(get(SELECTED_FEATURE_PROPERTY)), literal(1.5f), literal(1.0f))),
+ iconAnchor(Property.ICON_ANCHOR_BOTTOM),
+ iconColor(Color.BLUE)
+ );
+
+ builder.withImage("Car", Objects.requireNonNull(carBitmap), false)
+ .withSources(markerSource)
+ .withLayers(markerSymbolLayer);
+ options.withCameraPosition(new CameraPosition.Builder()
+ .target(new LatLng(5.537109374999999,
+ 52.07950600379697))
+ .zoom(1)
.padding(1, 1, 1, 1)
.build()
);
}
+ options.withStyleBuilder(builder);
MapSnapshotter snapshotter = new MapSnapshotter(MapSnapshotterActivity.this, options);
-
snapshotter.start(snapshot -> {
Timber.i("Got the snapshot");
ImageView imageView = new ImageView(MapSnapshotterActivity.this);
@@ -125,4 +196,11 @@ public static float randomInRange(float min, float max) {
return (random.nextFloat() * (max - min)) + min;
}
+ private JsonObject featureProperties(@NonNull String id, @NonNull String title) {
+ JsonObject object = new JsonObject();
+ object.add(ID_FEATURE_PROPERTY, new JsonPrimitive(id));
+ object.add(TITLE_FEATURE_PROPERTY, new JsonPrimitive(title));
+ object.add(SELECTED_FEATURE_PROPERTY, new JsonPrimitive(false));
+ return object;
+ }
}
diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterMarkerActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterBitMapOverlayActivity.java
similarity index 92%
rename from MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterMarkerActivity.java
rename to MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterBitMapOverlayActivity.java
index 5190bce90..d2ab581a9 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterMarkerActivity.java
+++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterBitMapOverlayActivity.java
@@ -6,26 +6,29 @@
import android.graphics.Canvas;
import android.graphics.PointF;
import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
+
import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
import com.mapbox.mapboxsdk.testapp.R;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AppCompatActivity;
import timber.log.Timber;
/**
* Test activity showing how to use a the {@link MapSnapshotter} and overlay
* {@link android.graphics.Bitmap}s on top.
*/
-public class MapSnapshotterMarkerActivity extends AppCompatActivity implements MapSnapshotter.SnapshotReadyCallback {
+public class MapSnapshotterBitMapOverlayActivity extends AppCompatActivity
+ implements MapSnapshotter.SnapshotReadyCallback {
private MapSnapshotter mapSnapshotter;
private MapSnapshot mapSnapshot;
@@ -49,10 +52,10 @@ public void onGlobalLayout() {
getApplicationContext(),
new MapSnapshotter
.Options(Math.min(container.getMeasuredWidth(), 1024), Math.min(container.getMeasuredHeight(), 1024))
- .withStyle(Style.OUTDOORS)
+ .withStyleBuilder(new Style.Builder().fromUri(Style.OUTDOORS))
.withCameraPosition(new CameraPosition.Builder().target(new LatLng(52.090737, 5.121420)).zoom(15).build())
);
- mapSnapshotter.start(MapSnapshotterMarkerActivity.this);
+ mapSnapshotter.start(MapSnapshotterBitMapOverlayActivity.this);
}
});
}
diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterHeatMapActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterHeatMapActivity.java
new file mode 100644
index 000000000..77e698b02
--- /dev/null
+++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterHeatMapActivity.java
@@ -0,0 +1,174 @@
+package com.mapbox.mapboxsdk.testapp.activity.snapshot;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.widget.ImageView;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.Style;
+import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
+import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
+import com.mapbox.mapboxsdk.style.layers.HeatmapLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.style.sources.Source;
+import com.mapbox.mapboxsdk.testapp.R;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import androidx.appcompat.app.AppCompatActivity;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.heatmapDensity;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapIntensity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapRadius;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapWeight;
+
+/**
+ * Test activity showing how to use a the {@link MapSnapshotter} and heatmap layer on it.
+ */
+public class MapSnapshotterHeatMapActivity extends AppCompatActivity implements MapSnapshotter.SnapshotReadyCallback {
+ private static final String EARTHQUAKE_SOURCE_URL = "https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson";
+ private static final String EARTHQUAKE_SOURCE_ID = "earthquakes";
+ private static final String HEATMAP_LAYER_ID = "earthquakes-heat";
+ private static final String HEATMAP_LAYER_SOURCE = "earthquakes";
+ private MapSnapshotter mapSnapshotter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_snapshotter_marker);
+
+ final View container = findViewById(R.id.container);
+ container.getViewTreeObserver()
+ .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ //noinspection deprecation
+ container.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+
+ Timber.i("Starting snapshot");
+
+ Style.Builder builder = new Style.Builder().fromUri(Style.OUTDOORS)
+ .withSource(getEarthquakeSource())
+ .withLayerAbove(getHeatmapLayer(), "waterway-label");
+
+ mapSnapshotter = new MapSnapshotter(
+ getApplicationContext(),
+ new MapSnapshotter
+ .Options(container.getMeasuredWidth(), container.getMeasuredHeight())
+ .withStyleBuilder(builder)
+ .withCameraPosition(new CameraPosition.Builder()
+ .target(new LatLng(15, -94))
+ .zoom(5)
+ .padding(1, 1, 1, 1)
+ .build()
+ )
+ );
+ mapSnapshotter.start(MapSnapshotterHeatMapActivity.this);
+ }
+ });
+ }
+
+ @NotNull
+ private HeatmapLayer getHeatmapLayer() {
+ HeatmapLayer layer = new HeatmapLayer(HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID);
+ layer.setMaxZoom(9);
+ layer.setSourceLayer(HEATMAP_LAYER_SOURCE);
+ layer.setProperties(
+
+ // Color ramp for heatmap. Domain is 0 (low) to 1 (high).
+ // Begin color ramp at 0-stop with a 0-transparency color
+ // to create a blur-like effect.
+ heatmapColor(
+ interpolate(
+ linear(), heatmapDensity(),
+ literal(0), rgba(33, 102, 172, 0),
+ literal(0.2), rgb(103, 169, 207),
+ literal(0.4), rgb(209, 229, 240),
+ literal(0.6), rgb(253, 219, 199),
+ literal(0.8), rgb(239, 138, 98),
+ literal(1), rgb(178, 24, 43)
+ )
+ ),
+
+ // Increase the heatmap weight based on frequency and property magnitude
+ heatmapWeight(
+ interpolate(
+ linear(), get("mag"),
+ stop(0, 0),
+ stop(6, 1)
+ )
+ ),
+
+ // Increase the heatmap color weight weight by zoom level
+ // heatmap-intensity is a multiplier on top of heatmap-weight
+ heatmapIntensity(
+ interpolate(
+ linear(), zoom(),
+ stop(0, 1),
+ stop(9, 3)
+ )
+ ),
+
+ // Adjust the heatmap radius by zoom level
+ heatmapRadius(
+ interpolate(
+ linear(), zoom(),
+ stop(0, 2),
+ stop(9, 20)
+ )
+ ),
+
+ // Transition from heatmap to circle layer by zoom level
+ heatmapOpacity(
+ interpolate(
+ linear(), zoom(),
+ stop(7, 1),
+ stop(9, 0)
+ )
+ )
+ );
+ return layer;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapSnapshotter.cancel();
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public void onSnapshotReady(MapSnapshot snapshot) {
+ Timber.i("Snapshot ready");
+ ImageView imageView = findViewById(R.id.snapshot_image);
+ imageView.setImageBitmap(snapshot.getBitmap());
+ }
+
+ private Source getEarthquakeSource() {
+ Source source = null;
+ try {
+ source = new GeoJsonSource(EARTHQUAKE_SOURCE_ID, new URI(EARTHQUAKE_SOURCE_URL));
+ } catch (URISyntaxException uriSyntaxException) {
+ Timber.e(uriSyntaxException, "That's not an url... ");
+ }
+ return source;
+ }
+
+}
diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterLocalStyleActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterLocalStyleActivity.java
index 1dda9f655..3b8c9ae72 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterLocalStyleActivity.java
+++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterLocalStyleActivity.java
@@ -7,6 +7,7 @@
import android.widget.ImageView;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
import com.mapbox.mapboxsdk.testapp.R;
@@ -48,7 +49,7 @@ public void onGlobalLayout() {
getApplicationContext(),
new MapSnapshotter
.Options(Math.min(container.getMeasuredWidth(), 1024), Math.min(container.getMeasuredHeight(), 1024))
- .withStyleJson(styleJson)
+ .withStyleBuilder(new Style.Builder().fromJson(styleJson))
.withCameraPosition(new CameraPosition.Builder().target(new LatLng(52.090737, 5.121420)).zoom(18).build())
);
mapSnapshotter.start(MapSnapshotterLocalStyleActivity.this, error -> Timber.e(error));
diff --git a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java
index 6b54ff9d5..198727277 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java
+++ b/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java
@@ -1,20 +1,21 @@
package com.mapbox.mapboxsdk.testapp.activity.snapshot;
import android.os.Bundle;
-import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
import com.mapbox.mapboxsdk.testapp.R;
import java.util.Random;
+import androidx.appcompat.app.AppCompatActivity;
+
/**
* Test activity showing how to use a the {@link MapSnapshotter}
*/
@@ -49,7 +50,7 @@ protected void onCreate(Bundle savedInstanceState) {
mapSnapshotter = new MapSnapshotter(
getApplicationContext(),
- new MapSnapshotter.Options(512, 512)
+ new MapSnapshotter.Options(512, 512).withStyleBuilder(new Style.Builder().fromUri(getRandomStyle()))
);
mapSnapshotter.start(MapSnapshotterReuseActivity.this);
diff --git a/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
index 075949be5..cc6a5ab80 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
+++ b/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
@@ -60,7 +60,8 @@
Show 2 MapView on screen with a bottom sheet
Show a static bitmap taken with the MapSnapshotter
Show how to reuse a MapSnapshotter instance
- Show how to add a marker to a Snapshot
+ Show how to add a bitmap overlay to a Snapshot
+ Show how to add a heatmap layer to a Snapshot
Show how to load a local style with a Snapshot
Use Android SDK Animators to animate camera position changes
Use Android SDK Views as symbols
diff --git a/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
index 0a0166945..75647878f 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
+++ b/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
@@ -59,7 +59,8 @@
Bottom sheet
Map Snapshotter
Map Snapshotter Reuse
- Map Snapshot with marker
+ Map Snapshot with bitmap overlay
+ Map Snapshot with heatmap layer
Map Snapshot with local style
Animator animation
SymbolGenerator
diff --git a/vendor/mapbox-gl-native b/vendor/mapbox-gl-native
index a601f9474..3f45b0a24 160000
--- a/vendor/mapbox-gl-native
+++ b/vendor/mapbox-gl-native
@@ -1 +1 @@
-Subproject commit a601f94743eb812847fbb58944df7240b088f7e2
+Subproject commit 3f45b0a24b5b608dfa75c84308d1ab0deb6159ee
From 0ad363c834165808ef5e4dfe05c8d37f55e7a1b0 Mon Sep 17 00:00:00 2001
From: Alexander Shalamov
Date: Wed, 25 Mar 2020 07:42:23 -0400
Subject: [PATCH 2/5] Add getLayer and getSource snapshotter methods (#292)
* Expose snapshotter layer and source objects
* Add example snapshotter + within activity
* Bump vendor/mapbox-gl-native
(cherry picked from commit 6984dbf155c6a1f26388481a2d8ab0979978dfa6)
---
.../mapboxsdk/snapshotter/MapSnapshotter.java | 62 ++++
.../src/main/AndroidManifest.xml | 11 +
.../turf/MapSnapshotterWithinExpression.kt | 274 ++++++++++++++++++
...ivity_mapsnapshotter_within_expression.xml | 30 ++
.../src/main/res/values/descriptions.xml | 1 +
.../src/main/res/values/titles.xml | 1 +
vendor/mapbox-gl-native | 2 +-
7 files changed, 380 insertions(+), 1 deletion(-)
create mode 100644 MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/turf/MapSnapshotterWithinExpression.kt
create mode 100644 MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapsnapshotter_within_expression.xml
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 26af5157a..dcbcb22b9 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
@@ -64,6 +64,8 @@ public class MapSnapshotter {
private SnapshotReadyCallback callback;
@Nullable
private ErrorHandler errorHandler;
+ @Nullable
+ private Observer observer;
/**
* Get notified on snapshot completion.
@@ -97,6 +99,20 @@ public interface ErrorHandler {
void onError(String error);
}
+ /**
+ * Can be used to get notified on snapshotter style loading
+ * completion.
+ *
+ * @see MapSnapshotter#setObserver(Observer)
+ */
+ public interface Observer {
+
+ /**
+ * Called when snapshotter finishes loading it's style.
+ */
+ void onDidFinishLoadingStyle();
+ }
+
/**
* MapSnapshotter options
*/
@@ -511,6 +527,16 @@ public void cancel() {
nativeCancel();
}
+ /**
+ * Sets observer for a snapshotter
+ *
+ * @param observer an Observer object
+ */
+ public void setObserver(@Nullable Observer observer) {
+ checkThread();
+ this.observer = observer;
+ }
+
/**
* Draw an overlay on the map snapshot.
*
@@ -736,6 +762,34 @@ protected void onDidFinishLoadingStyle() {
}
}
}
+
+ if (observer != null) {
+ observer.onDidFinishLoadingStyle();
+ }
+ }
+
+ /**
+ * Returns Layer of a style that is used by a snapshotter
+ *
+ * @param layerId the id of a Layer
+ * @return the Layer object if Layer with layerId exists, null otherwise
+ */
+ @Nullable
+ public Layer getLayer(@NonNull String layerId) {
+ checkThread();
+ return fullyLoaded ? nativeGetLayer(layerId) : null;
+ }
+
+ /**
+ * Returns Source of a style that is used by a snapshotter
+ *
+ * @param sourceId the id of a Source
+ * @return the Source object if a Source with sourceId exists, null otherwise
+ */
+ @Nullable
+ public Source getSource(@NonNull String sourceId) {
+ checkThread();
+ return fullyLoaded ? nativeGetSource(sourceId) : null;
}
/**
@@ -783,6 +837,14 @@ protected native void nativeInitialize(MapSnapshotter mapSnapshotter,
@Keep
private native void nativeAddImages(Image[] images);
+ @NonNull
+ @Keep
+ private native Layer nativeGetLayer(String layerId);
+
+ @NonNull
+ @Keep
+ private native Source nativeGetSource(String sourceId);
+
@Override
@Keep
protected native void finalize() throws Throwable;
diff --git a/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 7e2f59d3e..97f93f9bb 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -396,6 +396,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
+
+
+
+
+ mapboxMap = map
+
+ // Setup camera position above Georgetown
+ mapboxMap.cameraPosition = CameraPosition.Builder()
+ .target(LatLng(38.90628988399711, -77.06574689337494))
+ .zoom(15.5)
+ .build()
+
+ // Wait for the map to become idle before manipulating the style and camera of the map
+ mapView.addOnDidBecomeIdleListener(object : MapView.OnDidBecomeIdleListener {
+ override fun onDidBecomeIdle() {
+ mapboxMap.easeCamera(
+ CameraUpdateFactory.newCameraPosition(
+ CameraPosition.Builder()
+ .zoom(16.0)
+ .target(LatLng(38.905156245642814, -77.06535338052844))
+ .bearing(80.68015859462369)
+ .tilt(55.0)
+ .build()
+ ), 1000
+ )
+ mapView.removeOnDidBecomeIdleListener(this)
+ }
+ })
+ // Load mapbox streets and add lines and circles
+ setupStyle()
+ }
+ }
+
+ private fun setupStyle() {
+ // Assume the route is represented by an array of coordinates.
+ val coordinates = listOf(
+ Point.fromLngLat(
+ -77.06866264343262,
+ 38.90506061276737
+ ),
+ Point.fromLngLat(
+ -77.06283688545227,
+ 38.905194197410545
+ ),
+ Point.fromLngLat(
+ -77.06285834312439,
+ 38.906429843444094
+ ),
+ Point.fromLngLat(
+ -77.0630407333374,
+ 38.90680554236621
+ )
+ )
+
+ // Setup style with additional layers,
+ // using Style.MAPBOX_STREETS as a base style
+ mapboxMap.setStyle(
+ Style.Builder()
+ .fromUri(Style.MAPBOX_STREETS)
+ ) {
+ mapView.addOnCameraDidChangeListener(cameraListener)
+ }
+
+ val options = MapSnapshotter.Options(imageView.measuredWidth / 2, imageView.measuredHeight / 2)
+ .withCameraPosition(mapboxMap.cameraPosition)
+ .withPixelRatio(2.0f)
+ .withStyleBuilder(Style.Builder()
+ .fromUri(Style.MAPBOX_STREETS)
+ .withSources(
+ GeoJsonSource(
+ POINT_ID, LineString.fromLngLats(coordinates)
+ ),
+ GeoJsonSource(
+ FILL_ID,
+ FeatureCollection.fromFeature(Feature.fromGeometry(bufferLineStringGeometry())),
+ GeoJsonOptions().withBuffer(0).withTolerance(0.0f)
+ )
+ )
+ .withLayerBelow(
+ LineLayer(LINE_ID, POINT_ID)
+ .withProperties(lineWidth(7.5f), lineColor(Color.LTGRAY)),
+ "poi-label"
+ )
+ .withLayerBelow(
+ CircleLayer(POINT_ID, POINT_ID)
+ .withProperties(
+ circleRadius(7.5f),
+ circleColor(Color.DKGRAY),
+ circleOpacity(0.75f)
+ ), "poi-label"
+ ).withLayerBelow(
+ FillLayer(FILL_ID, FILL_ID)
+ .withProperties(
+ fillOpacity(0.12f),
+ fillColor(Color.YELLOW)
+ ), LINE_ID
+ ))
+ snapshotter = MapSnapshotter(this, options)
+ snapshotter.setObserver(snapshotterObserver)
+ }
+
+ override fun onStart() {
+ super.onStart()
+ mapView.onStart()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mapView.onResume()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ mapView.onPause()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ mapView.onStop()
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ mapView.onLowMemory()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mapView.onDestroy()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
+ super.onSaveInstanceState(outState, outPersistentState)
+ outState?.let {
+ mapView.onSaveInstanceState(it)
+ }
+ }
+
+ private fun bufferLineStringGeometry(): Polygon {
+ // TODO replace static data by Turf#Buffer: mapbox-java/issues/987
+ return FeatureCollection.fromJson(
+ """
+ {
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [
+ [
+ [
+ -77.06867337226866,
+ 38.90467655551809
+ ],
+ [
+ -77.06233263015747,
+ 38.90479344272695
+ ],
+ [
+ -77.06234335899353,
+ 38.906463238984344
+ ],
+ [
+ -77.06290125846863,
+ 38.907206285691615
+ ],
+ [
+ -77.06364154815674,
+ 38.90684728656818
+ ],
+ [
+ -77.06326603889465,
+ 38.90637140121084
+ ],
+ [
+ -77.06321239471436,
+ 38.905561553883246
+ ],
+ [
+ -77.0691454410553,
+ 38.905436318935635
+ ],
+ [
+ -77.06912398338318,
+ 38.90466820642439
+ ],
+ [
+ -77.06867337226866,
+ 38.90467655551809
+ ]
+ ]
+ ]
+ }
+ }
+ ]
+ }
+ """.trimIndent()
+ ).features()!![0].geometry() as Polygon
+ }
+
+ companion object {
+ const val POINT_ID = "point"
+ const val FILL_ID = "fill"
+ const val LINE_ID = "line"
+ }
+}
\ No newline at end of file
diff --git a/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapsnapshotter_within_expression.xml b/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapsnapshotter_within_expression.xml
new file mode 100644
index 000000000..121af0e14
--- /dev/null
+++ b/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapsnapshotter_within_expression.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
index cc6a5ab80..2ff1bf157 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
+++ b/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
@@ -27,6 +27,7 @@
Add a polygon to a map
Scroll with pixels in x,y direction
Example to make a snapshot of the map
+ Example of snapshotter with within expression
2 maps in a view hierarchy
Learn how to create a dynamic custom InfoWindow
Use SupportMapFragments in a ViewPager
diff --git a/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
index 75647878f..00a416b04 100644
--- a/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
+++ b/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
@@ -21,6 +21,7 @@
Scroll By Method
Double Map Activity
Snapshot Activity
+ Snapshot with within expression
Custom Layer
Map Padding
Debug Mode
diff --git a/vendor/mapbox-gl-native b/vendor/mapbox-gl-native
index 3f45b0a24..fd1f8703c 160000
--- a/vendor/mapbox-gl-native
+++ b/vendor/mapbox-gl-native
@@ -1 +1 @@
-Subproject commit 3f45b0a24b5b608dfa75c84308d1ab0deb6159ee
+Subproject commit fd1f8703cdd73420f23cb8617ffb6f5c42f8a32d
From adceb7351921cf67d045e36ec09b55f71566fe0e Mon Sep 17 00:00:00 2001
From: Tobrun
Date: Wed, 25 Mar 2020 14:58:59 +0100
Subject: [PATCH 3/5] [glyph] rework local glyph generation to use RGB values
vs alpha (#289)
(cherry picked from commit 4b0cd4025f88423ddc615314ab947b29b6db5dea)
---
.../java/com/mapbox/mapboxsdk/text/LocalGlyphRasterizer.java | 3 +--
vendor/mapbox-gl-native | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/LocalGlyphRasterizer.java b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/LocalGlyphRasterizer.java
index d698fb181..7d83884cc 100644
--- a/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/LocalGlyphRasterizer.java
+++ b/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/LocalGlyphRasterizer.java
@@ -4,7 +4,6 @@
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
import android.graphics.Typeface;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
@@ -52,7 +51,7 @@ of the bitmap (y: 20) with some buffer around the edge
@WorkerThread
protected Bitmap drawGlyphBitmap(String fontFamily, boolean bold, char glyphID) {
paint.setTypeface(Typeface.create(fontFamily, bold ? Typeface.BOLD : Typeface.NORMAL));
- canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ canvas.drawColor(Color.WHITE);
canvas.drawText(String.valueOf(glyphID), 0, 20, paint);
return bitmap;
}
diff --git a/vendor/mapbox-gl-native b/vendor/mapbox-gl-native
index fd1f8703c..d4db3b112 160000
--- a/vendor/mapbox-gl-native
+++ b/vendor/mapbox-gl-native
@@ -1 +1 @@
-Subproject commit fd1f8703cdd73420f23cb8617ffb6f5c42f8a32d
+Subproject commit d4db3b11267d9ac22fc53991a383f95f95e607ea
From a05b44a62dc9372221d7372d1e7f35b1c9ad77f4 Mon Sep 17 00:00:00 2001
From: Kevin Li
Date: Thu, 26 Mar 2020 16:24:55 +0800
Subject: [PATCH 4/5] bump telemetry to 5.0.0, core to 2.0.0 (#293)
(cherry picked from commit fbea14a8bc7253f448c3346e7019d4a9f0e54779)
---
gradle/dependencies.gradle | 4 ++--
vendor/mapbox-events-android | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index daca6ecbc..f82887222 100644
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -8,8 +8,8 @@ ext {
versions = [
mapboxServices : '5.0.0',
- mapboxTelemetry : '4.7.3',
- mapboxCore : '1.4.1',
+ mapboxTelemetry : '5.0.0',
+ mapboxCore : '2.0.0',
mapboxGestures : '0.6.0',
mapboxAccounts : '0.7.0',
appCompat : '1.0.0',
diff --git a/vendor/mapbox-events-android b/vendor/mapbox-events-android
index 7945e61bc..0b46d29ef 160000
--- a/vendor/mapbox-events-android
+++ b/vendor/mapbox-events-android
@@ -1 +1 @@
-Subproject commit 7945e61bccc1df3b04ca2e80cb25459dfeea01dd
+Subproject commit 0b46d29efd23d870e1f084f0591091a16169c800
From fff28b0a2ac9c09325cce58a2356c43c301d9d3d Mon Sep 17 00:00:00 2001
From: Kevin Li
Date: Fri, 27 Mar 2020 12:54:53 +0800
Subject: [PATCH 5/5] Bump gl-native to 1.5.0 (#296)
(cherry picked from commit 585253ed0dbd321e02dda7d27c91c2036c17f9a8)
---
vendor/mapbox-gl-native | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vendor/mapbox-gl-native b/vendor/mapbox-gl-native
index d4db3b112..77466d23d 160000
--- a/vendor/mapbox-gl-native
+++ b/vendor/mapbox-gl-native
@@ -1 +1 @@
-Subproject commit d4db3b11267d9ac22fc53991a383f95f95e607ea
+Subproject commit 77466d23d6b2f524c104373d546ac458035b0ec0