From 6984dbf155c6a1f26388481a2d8ab0979978dfa6 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Wed, 25 Mar 2020 07:42:23 -0400 Subject: [PATCH] Add getLayer and getSource snapshotter methods (#292) * Expose snapshotter layer and source objects * Add example snapshotter + within activity * Bump vendor/mapbox-gl-native --- .../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 class MapSnapshotter { 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 class MapSnapshotter { 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 @@ public class MapSnapshotter { } } } + + 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 @@ public class 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 3538be8af..66435115e 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 c49c93fb7..f90653ffe 100644 --- a/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml +++ b/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml @@ -28,6 +28,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 91f487ee2..637d3b774 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