From 9c3e78a9b95782e8fbf15cf7a4052f46f27922fd Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Mon, 9 Oct 2017 16:54:32 +0300 Subject: [android] map snapshotter - wrap snapshot in native peer for access to the pointFor functionality --- .../mapbox/mapboxsdk/snapshotter/MapSnapshot.java | 45 +++++++++++++ .../mapboxsdk/snapshotter/MapSnapshotter.java | 33 +++++++--- .../src/main/AndroidManifest.xml | 10 +++ .../activity/snapshot/MapSnapshotterActivity.java | 9 ++- .../snapshot/MapSnapshotterMarkerActivity.java | 77 ++++++++++++++++++++++ .../snapshot/MapSnapshotterReuseActivity.java | 9 ++- .../res/layout/activity_map_snapshotter_marker.xml | 14 ++++ .../src/main/res/values/descriptions.xml | 1 + .../src/main/res/values/titles.xml | 1 + platform/android/config.cmake | 10 ++- platform/android/src/jni.cpp | 2 + platform/android/src/snapshotter/map_snapshot.cpp | 57 ++++++++++++++++ platform/android/src/snapshotter/map_snapshot.hpp | 41 ++++++++++++ .../android/src/snapshotter/map_snapshotter.cpp | 12 ++-- 14 files changed, 293 insertions(+), 28 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshot.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterMarkerActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_snapshotter_marker.xml create mode 100644 platform/android/src/snapshotter/map_snapshot.cpp create mode 100644 platform/android/src/snapshotter/map_snapshot.hpp diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshot.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshot.java new file mode 100644 index 0000000000..2d1412aeda --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshot.java @@ -0,0 +1,45 @@ +package com.mapbox.mapboxsdk.snapshotter; + +import android.graphics.Bitmap; +import android.graphics.PointF; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +/** + * A completed snapshot. + * + * @see MapSnapshotter + */ +public class MapSnapshot { + + private long nativePtr = 0; + private Bitmap bitmap; + + /** + * Created from native side + */ + private MapSnapshot(long nativePtr, Bitmap bitmap) { + this.nativePtr = nativePtr; + this.bitmap = bitmap; + } + + /** + * @return the bitmap + */ + public Bitmap getBitmap() { + return bitmap; + } + + /** + * Calculate the point in pixels on the Image from geographical coordinates. + * + * @param latLng the geographical coordinates + * @return the point on the image + */ + public native PointF pixelForLatLng(LatLng latLng); + + // Unused, needed for peer binding + private native void initialize(); + + protected native void finalize(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java index 8118f9ad92..37d05fc328 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java @@ -12,7 +12,6 @@ import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLngBounds; -import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.storage.FileSource; /** @@ -23,11 +22,27 @@ import com.mapbox.mapboxsdk.storage.FileSource; @UiThread public class MapSnapshotter { + /** + * Get notified on snapshot completion. + * + * @see MapSnapshotter#start(SnapshotReadyCallback, ErrorHandler) + */ + public interface SnapshotReadyCallback { + + /** + * Called when the snapshot is complete. + * + * @param snapshot the snapshot + */ + void onSnapshotReady(MapSnapshot snapshot); + + } + /** * Can be used to get notified of errors * in snapshot generation * - * @see MapSnapshotter#start(MapboxMap.SnapshotReadyCallback, ErrorHandler) + * @see MapSnapshotter#start(SnapshotReadyCallback, ErrorHandler) */ public interface ErrorHandler { @@ -46,7 +61,7 @@ public class MapSnapshotter { private long nativePtr = 0; private final Context context; - private MapboxMap.SnapshotReadyCallback callback; + private SnapshotReadyCallback callback; private ErrorHandler errorHandler; /** @@ -176,7 +191,7 @@ public class MapSnapshotter { * * @param callback the callback to use when the snapshot is ready */ - public void start(@NonNull MapboxMap.SnapshotReadyCallback callback) { + public void start(@NonNull SnapshotReadyCallback callback) { this.start(callback, null); } @@ -187,7 +202,7 @@ public class MapSnapshotter { * @param callback the callback to use when the snapshot is ready * @param errorHandler the error handler to use on snapshot errors */ - public void start(@NonNull MapboxMap.SnapshotReadyCallback callback, ErrorHandler errorHandler) { + public void start(@NonNull SnapshotReadyCallback callback, ErrorHandler errorHandler) { if (this.callback != null) { throw new IllegalStateException("Snapshotter was already started"); } @@ -247,12 +262,12 @@ public class MapSnapshotter { * Called by JNI peer when snapshot is ready. * Always called on the origin (main) thread. * - * @param bitmap the generated snapshot + * @param snapshot the generated snapshot */ - protected void onSnapshotReady(Bitmap bitmap) { + protected void onSnapshotReady(MapSnapshot snapshot) { if (callback != null) { - addOverlay(bitmap); - callback.onSnapshotReady(bitmap); + addOverlay(snapshot.getBitmap()); + callback.onSnapshotReady(snapshot); reset(); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index d6237bc161..7f955cb45c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -387,6 +387,16 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".activity.FeatureOverviewActivity"/> + + + + + + + + + diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml index 94dc669781..a2bf1d8596 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml @@ -61,6 +61,7 @@ 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 Use Android SDK Animators to animate camera position changes Use Android SDK Views as symbols \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml index 4942bcab36..1fb2f6ba7f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml @@ -61,6 +61,7 @@ Bottom sheet Map Snapshotter Map Snapshotter Reuse + Map Snapshot with marker Animator animation SymbolGenerator \ No newline at end of file diff --git a/platform/android/config.cmake b/platform/android/config.cmake index e6813d5a22..47f894f7b9 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -59,7 +59,7 @@ macro(mbgl_platform_core) PRIVATE platform/android/src/android_renderer_frontend.cpp PRIVATE platform/android/src/android_renderer_frontend.hpp - # Snapshots + # Snapshots (core) PRIVATE platform/default/mbgl/gl/headless_backend.cpp PRIVATE platform/default/mbgl/gl/headless_backend.hpp PRIVATE platform/default/mbgl/gl/headless_frontend.cpp @@ -68,8 +68,6 @@ macro(mbgl_platform_core) PRIVATE platform/default/mbgl/map/map_snapshotter.hpp PRIVATE platform/linux/src/headless_backend_egl.cpp PRIVATE platform/linux/src/headless_display_egl.cpp - PRIVATE platform/android/src/snapshotter/map_snapshotter.cpp - PRIVATE platform/android/src/snapshotter/map_snapshotter.hpp ) target_include_directories(mbgl-core @@ -295,6 +293,12 @@ add_library(mbgl-android STATIC platform/android/src/offline/offline_region_status.cpp platform/android/src/offline/offline_region_status.hpp + # Snapshots (SDK) + platform/android/src/snapshotter/map_snapshotter.cpp + platform/android/src/snapshotter/map_snapshotter.hpp + platform/android/src/snapshotter/map_snapshot.cpp + platform/android/src/snapshotter/map_snapshot.hpp + # Main jni bindings platform/android/src/attach_env.cpp platform/android/src/attach_env.hpp diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index f6ddb8b6ee..f4e5734861 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -50,6 +50,7 @@ #include "style/sources/sources.hpp" #include "style/light.hpp" #include "snapshotter/map_snapshotter.hpp" +#include "snapshotter/map_snapshot.hpp" namespace mbgl { namespace android { @@ -186,6 +187,7 @@ void registerNatives(JavaVM *vm) { // Snapshotter MapSnapshotter::registerNative(env); + MapSnapshot::registerNative(env); } } // namespace android diff --git a/platform/android/src/snapshotter/map_snapshot.cpp b/platform/android/src/snapshotter/map_snapshot.cpp new file mode 100644 index 0000000000..09e83bbb8a --- /dev/null +++ b/platform/android/src/snapshotter/map_snapshot.cpp @@ -0,0 +1,57 @@ +#include "map_snapshot.hpp" + +#include "../bitmap.hpp" + +#include + +namespace mbgl { +namespace android { + +MapSnapshot::MapSnapshot(float pixelRatio_, MapSnapshot::PointForFn pointForFn_) + : pixelRatio(pixelRatio_) + , pointForFn(std::move(pointForFn_)) { +} + +MapSnapshot::~MapSnapshot() = default; + +jni::Object MapSnapshot::pixelForLatLng(jni::JNIEnv& env, jni::Object jLatLng) { + ScreenCoordinate point = pointForFn(LatLng::getLatLng(env, jLatLng)); + return PointF::New(env, point.x * pixelRatio, point.y * pixelRatio); +} + + +// Static methods // + +jni::Object MapSnapshot::New(JNIEnv& env, + PremultipliedImage&& image, + float pixelRatio, + mbgl::MapSnapshotter::PointForFn pointForFn) { + // Create the bitmap + auto bitmap = Bitmap::CreateBitmap(env, std::move(image)); + + // Create the Mapsnapshot peers + static auto constructor = javaClass.GetConstructor>(env); + auto nativePeer = std::make_unique(pixelRatio, pointForFn); + return javaClass.New(env, constructor, reinterpret_cast(nativePeer.release()), bitmap); +} + +jni::Class MapSnapshot::javaClass; + +void MapSnapshot::registerNative(jni::JNIEnv& env) { + // Lookup the class + MapSnapshot::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + +#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) + + // Register the peer + jni::RegisterNativePeer(env, MapSnapshot::javaClass, + "nativePtr", + std::make_unique, + "initialize", + "finalize", + METHOD(&MapSnapshot::pixelForLatLng, "pixelForLatLng") + ); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/snapshotter/map_snapshot.hpp b/platform/android/src/snapshotter/map_snapshot.hpp new file mode 100644 index 0000000000..6d60d49728 --- /dev/null +++ b/platform/android/src/snapshotter/map_snapshot.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include + +#include "../geometry/lat_lng.hpp" +#include "../graphics/pointf.hpp" + +namespace mbgl { +namespace android { + +class MapSnapshot { +public: + + using PointForFn = mbgl::MapSnapshotter::PointForFn; + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/snapshotter/MapSnapshot"; }; + + static void registerNative(jni::JNIEnv&); + + static jni::Object New(JNIEnv& env, + PremultipliedImage&& image, + float pixelRatio, + PointForFn pointForFn); + + MapSnapshot(jni::JNIEnv&) {}; + MapSnapshot(float pixelRatio, PointForFn); + ~MapSnapshot(); + + jni::Object pixelForLatLng(jni::JNIEnv&, jni::Object); + +private: + static jni::Class javaClass; + + float pixelRatio; + mbgl::MapSnapshotter::PointForFn pointForFn; +}; + +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp index 74e43c70a1..a13e91ccd3 100644 --- a/platform/android/src/snapshotter/map_snapshotter.cpp +++ b/platform/android/src/snapshotter/map_snapshotter.cpp @@ -8,7 +8,7 @@ #include #include "../attach_env.hpp" -#include "../bitmap.hpp" +#include "map_snapshot.hpp" namespace mbgl { namespace android { @@ -58,7 +58,7 @@ MapSnapshotter::~MapSnapshotter() = default; void MapSnapshotter::start(JNIEnv&) { MBGL_VERIFY_THREAD(tid); - snapshotCallback = std::make_unique>(*Scheduler::GetCurrent(), [this](std::exception_ptr err, PremultipliedImage image) { + snapshotCallback = std::make_unique>(*Scheduler::GetCurrent(), [this](std::exception_ptr err, PremultipliedImage image, mbgl::MapSnapshotter::PointForFn pointForFn) { MBGL_VERIFY_THREAD(tid); android::UniqueEnv _env = android::AttachEnv(); @@ -67,12 +67,12 @@ void MapSnapshotter::start(JNIEnv&) { static auto onSnapshotFailed = javaClass.GetMethod(*_env, "onSnapshotFailed"); javaPeer->Call(*_env, onSnapshotFailed, jni::Make(*_env, util::toString(err))); } else { - // Create the bitmap - auto bitmap = Bitmap::CreateBitmap(*_env, std::move(image)); + // Create the wrapper + auto mapSnapshot = android::MapSnapshot::New(*_env, std::move(image), pixelRatio, pointForFn); // invoke callback - static auto onSnapshotReady = javaClass.GetMethod)>(*_env, "onSnapshotReady"); - javaPeer->Call(*_env, onSnapshotReady, bitmap); + static auto onSnapshotReady = javaClass.GetMethod)>(*_env, "onSnapshotReady"); + javaPeer->Call(*_env, onSnapshotReady, mapSnapshot); } }); -- cgit v1.2.1