diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index 4caa6d4d8..7330f2f3a 100644 --- a/cmake/mason-dependencies.cmake +++ b/cmake/mason-dependencies.cmake @@ -19,7 +19,7 @@ mason_use(cheap-ruler VERSION 2.5.3 HEADER_ONLY) mason_use(vector-tile VERSION 1.0.2 HEADER_ONLY) if(MBGL_PLATFORM STREQUAL "android") - mason_use(jni.hpp VERSION 3.0.0 HEADER_ONLY) + mason_use(jni.hpp VERSION 4.0.0-rc8 HEADER_ONLY) elseif(MBGL_PLATFORM STREQUAL "ios") mason_use(icu VERSION 58.1-min-size) elseif(MBGL_PLATFORM STREQUAL "linux") diff --git a/platform/android/core-files.txt b/platform/android/core-files.txt index eca7529c0..9a57e7680 100644 --- a/platform/android/core-files.txt +++ b/platform/android/core-files.txt @@ -137,8 +137,6 @@ platform/android/src/map_renderer_runnable.cpp platform/android/src/map_renderer_runnable.hpp # Java core classes -platform/android/src/java/lang.cpp -platform/android/src/java/lang.hpp platform/android/src/java/util.cpp platform/android/src/java/util.hpp diff --git a/platform/android/src/annotation/marker.cpp b/platform/android/src/annotation/marker.cpp index a1fe436db..b9a8c714a 100644 --- a/platform/android/src/annotation/marker.cpp +++ b/platform/android/src/annotation/marker.cpp @@ -3,29 +3,21 @@ namespace mbgl { namespace android { -jni::Class Marker::javaClass; - mbgl::Point Marker::getPosition(jni::JNIEnv& env, jni::Object marker) { - static auto positionField = Marker::javaClass.GetField>(env, "position"); - auto jPosition = marker.Get(env, positionField); - auto position = LatLng::getGeometry(env, jPosition); - jni::DeleteLocalRef(env, jPosition); - return position; + static auto javaClass = jni::Class::Singleton(env); + static auto positionField = javaClass.GetField>(env, "position"); + return LatLng::getGeometry(env, *jni::SeizeLocal(env, marker.Get(env, positionField))); } std::string Marker::getIconId(jni::JNIEnv& env, jni::Object marker) { - static auto iconIdField = Marker::javaClass.GetField(env, "iconId"); - auto jIconId = marker.Get(env, iconIdField); - auto iconId = jni::Make(env, jIconId); - jni::DeleteLocalRef(env, jIconId); - return iconId; + static auto javaClass = jni::Class::Singleton(env); + static auto iconIdField = javaClass.GetField(env, "iconId"); + return jni::Make(env, *jni::SeizeLocal(env, marker.Get(env, iconIdField))); } void Marker::registerNative(jni::JNIEnv& env) { - // Lookup the class - Marker::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/annotation/marker.hpp b/platform/android/src/annotation/marker.hpp index b11a22524..d03c24492 100644 --- a/platform/android/src/annotation/marker.hpp +++ b/platform/android/src/annotation/marker.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; }; - static jni::Class javaClass; - static mbgl::Point getPosition(jni::JNIEnv&, jni::Object); static std::string getIconId(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp index e1152dfd6..1a6b94526 100644 --- a/platform/android/src/annotation/multi_point.hpp +++ b/platform/android/src/annotation/multi_point.hpp @@ -15,25 +15,17 @@ protected: template static Geometry toGeometry(JNIEnv& env, jni::Object pointsList) { - NullCheck(env, &pointsList); - auto jarray = java::util::List::toArray(env, pointsList); - NullCheck(env, &jarray); + auto jarray = jni::SeizeLocal(env, java::util::List::toArray(env, pointsList)); - std::size_t size = jarray.Length(env); + std::size_t size = jarray->Length(env); Geometry geometry; geometry.reserve(size); for (std::size_t i = 0; i < size; i++) { - auto latLng = jarray.Get(env, i); - NullCheck(env, &latLng); - - geometry.push_back(LatLng::getGeometry(env, latLng)); - - jni::DeleteLocalRef(env, latLng); + geometry.push_back(LatLng::getGeometry(env, *jni::SeizeLocal(env, jarray->Get(env, i)))); } - jni::DeleteLocalRef(env, jarray); return geometry; } }; diff --git a/platform/android/src/annotation/polygon.cpp b/platform/android/src/annotation/polygon.cpp index fbd849432..f049911be 100644 --- a/platform/android/src/annotation/polygon.cpp +++ b/platform/android/src/annotation/polygon.cpp @@ -5,63 +5,60 @@ namespace mbgl { namespace android { -jni::Class Polygon::javaClass; - mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object polygon) { - auto points = Polygon::getPoints(env, polygon); - auto holes = Polygon::getHoles(env, polygon); + auto points = jni::SeizeLocal(env, Polygon::getPoints(env, polygon)); + auto holes = jni::SeizeLocal(env, Polygon::getHoles(env, polygon)); - mbgl::Polygon geometry { MultiPoint::toGeometry>(env, points) }; + mbgl::Polygon geometry { MultiPoint::toGeometry>(env, *points) }; - auto jHoleListsArray = java::util::List::toArray(env, holes); - std::size_t jHoleListsSize = jHoleListsArray.Length(env); + auto jHoleListsArray = jni::SeizeLocal(env, java::util::List::toArray(env, *holes)); + std::size_t jHoleListsSize = jHoleListsArray->Length(env); for (std::size_t i = 0; i < jHoleListsSize; i++) { - auto jHoleList = jHoleListsArray.Get(env, i); - geometry.push_back(MultiPoint::toGeometry>(env, jHoleList)); - jni::DeleteLocalRef(env, jHoleList); + geometry.push_back(MultiPoint::toGeometry>(env, + *jni::SeizeLocal(env, jHoleListsArray->Get(env, i)))); } - jni::DeleteLocalRef(env, jHoleListsArray); mbgl::FillAnnotation annotation { geometry }; annotation.opacity = { Polygon::getOpacity(env, polygon) }; annotation.color = { Polygon::getFillColor(env, polygon) }; annotation.outlineColor = { Polygon::getOutlineColor(env, polygon) }; - jni::DeleteLocalRef(env, points); - jni::DeleteLocalRef(env, holes); - return annotation; } jni::Object Polygon::getPoints(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField>(env, "points"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField>(env, "points"); return polygon.Get(env, field); } jni::Object Polygon::getHoles(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField>(env, "holes"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField>(env, "holes"); return polygon.Get(env, field); } float Polygon::getOpacity(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField(env, "alpha"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "alpha"); return polygon.Get(env, field); } mbgl::Color Polygon::getFillColor(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField(env, "fillColor"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "fillColor"); return *conversion::convert(env, polygon.Get(env, field)); } mbgl::Color Polygon::getOutlineColor(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField(env, "strokeColor"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "strokeColor"); return *conversion::convert(env, polygon.Get(env, field)); } void Polygon::registerNative(jni::JNIEnv& env) { - Polygon::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/annotation/polygon.hpp b/platform/android/src/annotation/polygon.hpp index a98b2822c..f7cc015c8 100644 --- a/platform/android/src/annotation/polygon.hpp +++ b/platform/android/src/annotation/polygon.hpp @@ -18,8 +18,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; }; - static jni::Class javaClass; - static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index 3723dc187..22d25a0f7 100644 --- a/platform/android/src/annotation/polyline.cpp +++ b/platform/android/src/annotation/polyline.cpp @@ -5,45 +5,44 @@ namespace mbgl { namespace android { -jni::Class Polyline::javaClass; - mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object polyline) { - auto points = Polyline::getPoints(env, polyline); + auto points = jni::SeizeLocal(env, Polyline::getPoints(env, polyline)); - mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, points) }; + mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, *points) }; annotation.opacity = { Polyline::getOpacity(env, polyline) }; annotation.color = { Polyline::getColor(env, polyline) }; annotation.width = { Polyline::getWidth(env, polyline) }; - jni::DeleteLocalRef(env, points); - return annotation; } jni::Object Polyline::getPoints(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField>(env, "points"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField>(env, "points"); return polyline.Get(env, field); } float Polyline::getOpacity(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField(env, "alpha"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "alpha"); return polyline.Get(env, field); } mbgl::Color Polyline::getColor(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField(env, "color"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "color"); return *conversion::convert(env, polyline.Get(env, field)); } float Polyline::getWidth(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField(env, "width"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "width"); return polyline.Get(env, field); } void Polyline::registerNative(jni::JNIEnv& env) { - Polyline::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/annotation/polyline.hpp b/platform/android/src/annotation/polyline.hpp index bcc616a5f..69f5d19c1 100644 --- a/platform/android/src/annotation/polyline.hpp +++ b/platform/android/src/annotation/polyline.hpp @@ -18,8 +18,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; }; - static jni::Class javaClass; - static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/asset_manager_file_source.hpp b/platform/android/src/asset_manager_file_source.hpp index dcad95664..bb0809a44 100644 --- a/platform/android/src/asset_manager_file_source.hpp +++ b/platform/android/src/asset_manager_file_source.hpp @@ -22,7 +22,7 @@ public: private: class Impl; - jni::UniqueObject assetManager; + jni::Global> assetManager; std::unique_ptr> impl; }; diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp index 0d3670b66..53136b868 100644 --- a/platform/android/src/bitmap.cpp +++ b/platform/android/src/bitmap.cpp @@ -15,6 +15,7 @@ public: throw std::runtime_error("bitmap decoding: could not lock pixels"); } } + ~PixelGuard() { const int result = AndroidBitmap_unlockPixels(&env, jni::Unwrap(*bitmap)); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { @@ -26,23 +27,14 @@ public: return address; } - const auto* get() const { - return address; - } - private: jni::JNIEnv& env; jni::Object bitmap; uint8_t* address; }; -void Bitmap::Config::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Bitmap::Config::_class; - jni::Object Bitmap::Config::Create(jni::JNIEnv& env, Value value) { + static auto _class = jni::Class::Singleton(env); switch (value) { case ALPHA_8: return _class.Get(env, @@ -62,18 +54,17 @@ jni::Object Bitmap::Config::Create(jni::JNIEnv& env, Value value } void Bitmap::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); - Config::registerNative(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); } -jni::Class Bitmap::_class; - jni::Object Bitmap::CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, jni::Object config) { - using Signature = jni::Object(jni::jint, jni::jint, jni::Object); - auto method = _class.GetStaticMethod(env, "createBitmap"); + static auto _class = jni::Class::Singleton(env); + static auto method = _class.GetStaticMethod (jni::jint, jni::jint, jni::Object)>(env, "createBitmap"); + return _class.Call(env, method, width, height, config); } @@ -106,15 +97,13 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object bitmap AndroidBitmapInfo info; const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { - // TODO: more specific information throw std::runtime_error("bitmap decoding: couldn't get bitmap info"); } - if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { - bitmap = Bitmap::Copy(env, bitmap); + return Bitmap::GetImage(env, Bitmap::Copy(env, bitmap)); } - const PixelGuard guard(env, bitmap); + PixelGuard guard(env, bitmap); // Copy the Android Bitmap into the PremultipliedImage. auto pixels = @@ -129,10 +118,10 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object bitmap } jni::Object Bitmap::Copy(jni::JNIEnv& env, jni::Object bitmap) { - using Signature = jni::Object(jni::Object, jni::jboolean); - auto static method = _class.GetMethod(env, "copy"); - auto config = Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888); - return bitmap.Call(env, method, config, (jni::jboolean) false); + static auto klass = jni::Class::Singleton(env); + static auto copy = klass.GetMethod (jni::Object, jni::jboolean)>(env, "copy"); + + return bitmap.Call(env, copy, Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888), jni::jni_false); } } // namespace android diff --git a/platform/android/src/bitmap.hpp b/platform/android/src/bitmap.hpp index c4e41db1e..2266bc0e6 100644 --- a/platform/android/src/bitmap.hpp +++ b/platform/android/src/bitmap.hpp @@ -11,10 +11,7 @@ class Bitmap { public: class Config { public: - static constexpr auto Name() { - return "android/graphics/Bitmap$Config"; - }; - static void registerNative(jni::JNIEnv&); + static constexpr auto Name() { return "android/graphics/Bitmap$Config"; }; enum Value { ALPHA_8, @@ -24,18 +21,14 @@ public: }; static jni::Object Create(jni::JNIEnv&, Value); - - private: - static jni::Class _class; }; - static constexpr auto Name() { - return "android/graphics/Bitmap"; - }; + static constexpr auto Name() { return "android/graphics/Bitmap"; }; static void registerNative(jni::JNIEnv&); static jni::Object CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, jni::Object); + static jni::Object CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, Config::Value config) { return CreateBitmap(env, width, height, Config::Create(env, config)); @@ -44,9 +37,6 @@ public: static PremultipliedImage GetImage(jni::JNIEnv&, jni::Object); static jni::Object CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); static jni::Object Copy(jni::JNIEnv&, jni::Object); - -private: - static jni::Class _class; }; } // namespace android diff --git a/platform/android/src/bitmap_factory.cpp b/platform/android/src/bitmap_factory.cpp index 7d9b068b2..79cdc913a 100644 --- a/platform/android/src/bitmap_factory.cpp +++ b/platform/android/src/bitmap_factory.cpp @@ -4,20 +4,20 @@ namespace mbgl { namespace android { void BitmapFactory::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class BitmapFactory::_class; - jni::Object BitmapFactory::DecodeByteArray(jni::JNIEnv& env, jni::Array data, jni::jint offset, jni::jint length) { + static auto _class = jni::Class::Singleton(env); // Images are loaded with ARGB_8888 config, and premultiplied by default, which is exactly // what we want, so we're not providing a BitmapFactory.Options object. - using Signature = jni::Object(jni::Array, jni::jint, jni::jint); - auto method = _class.GetStaticMethod(env, "decodeByteArray"); + using Signature = jni::Object (jni::Array, jni::jint, jni::jint); + static auto method = _class.GetStaticMethod(env, "decodeByteArray"); + return _class.Call(env, method, data, offset, length); } diff --git a/platform/android/src/bitmap_factory.hpp b/platform/android/src/bitmap_factory.hpp index b0e719826..6e019d017 100644 --- a/platform/android/src/bitmap_factory.hpp +++ b/platform/android/src/bitmap_factory.hpp @@ -9,16 +9,11 @@ namespace android { class BitmapFactory { public: - static constexpr auto Name() { - return "android/graphics/BitmapFactory"; - }; + static constexpr auto Name() { return "android/graphics/BitmapFactory"; }; static void registerNative(jni::JNIEnv&); static jni::Object DecodeByteArray(jni::JNIEnv&, jni::Array data, jni::jint offset, jni::jint length); - -private: - static jni::Class _class; }; } // namespace android diff --git a/platform/android/src/connectivity_listener.cpp b/platform/android/src/connectivity_listener.cpp index 5b1c0a86e..3fcc580aa 100644 --- a/platform/android/src/connectivity_listener.cpp +++ b/platform/android/src/connectivity_listener.cpp @@ -19,18 +19,16 @@ namespace android { NetworkStatus::Set(connected ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline); } - jni::Class ConnectivityListener::javaClass; - void ConnectivityListener::registerNative(jni::JNIEnv& env) { // Lookup the class - ConnectivityListener::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, - ConnectivityListener::javaClass, + javaClass, "nativePtr", std::make_unique, "initialize", diff --git a/platform/android/src/connectivity_listener.hpp b/platform/android/src/connectivity_listener.hpp index b0d655d02..a09507c0f 100644 --- a/platform/android/src/connectivity_listener.hpp +++ b/platform/android/src/connectivity_listener.hpp @@ -12,8 +12,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/net/NativeConnectivityListener"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); /* diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp index 6775228e1..3195458aa 100644 --- a/platform/android/src/conversion/collection.cpp +++ b/platform/android/src/conversion/collection.cpp @@ -11,24 +11,17 @@ std::vector toVector(JNIEnv& env, jni::Array array) { vector.reserve(len); for (std::size_t i = 0; i < len; i++) { - jni::String jstr = array.Get(env, i); - vector.push_back(*convert(env, jstr)); - jni::DeleteLocalRef(env, jstr); + vector.push_back(*convert(env, *jni::SeizeLocal(env, array.Get(env, i)))); } return vector; } jni::Array toArray(JNIEnv& env, const std::vector& vector) { - static auto clazz = *jni::Class::Find(env).NewGlobalRef(env).release(); - auto result = jni::Array::New(env, vector.size(), clazz); + auto result = jni::Array::New(env, vector.size()); - std::size_t index = 0; - for (auto&& item : vector) { - auto element = jni::Make(env, item); - result.Set(env, index, element); - DeleteLocalRef(env, element); - index++; + for (std::size_t i = 0; i < vector.size(); i++) { + result.Set(env, i, *jni::SeizeLocal(env, jni::Make(env, vector.at(i)))); } return result; diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 2a6cac3b0..32c304b90 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -51,7 +51,7 @@ void FileSource::setResourceTransform(jni::JNIEnv& env, jni::Object(transformCallback.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter())] + [callback = std::shared_ptr(transformCallback.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter())] (mbgl::Resource::Kind kind, const std::string&& url_) { android::UniqueEnv _env = android::AttachEnv(); return FileSource::ResourceTransformCallback::onURL(*_env, jni::Object(*callback), int(kind), url_); @@ -92,10 +92,9 @@ jni::jboolean FileSource::isResumed(jni::JNIEnv&) { return (jboolean) false; } -jni::Class FileSource::javaClass; - FileSource* FileSource::getNativePeer(jni::JNIEnv& env, jni::Object jFileSource) { - static auto field = FileSource::javaClass.GetField(env, "nativePtr"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "nativePtr"); return reinterpret_cast(jFileSource.Get(env, field)); } @@ -106,15 +105,18 @@ mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, jni: } void FileSource::registerNative(jni::JNIEnv& env) { - //Register classes - FileSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - FileSource::ResourceTransformCallback::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + // Ensure the class for ResourceTransformCallback is cached. If it's requested for the + // first time on a background thread, Android's class loader heuristics will fail. + // https://developer.android.com/training/articles/perf-jni#faq_FindClass + jni::Class::Singleton(env); + + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, FileSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", @@ -131,16 +133,13 @@ void FileSource::registerNative(jni::JNIEnv& env) { // FileSource::ResourceTransformCallback // -jni::Class FileSource::ResourceTransformCallback::javaClass; - std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, jni::Object callback, int kind, std::string url_) { - static auto method = FileSource::ResourceTransformCallback::javaClass.GetMethod(env, "onURL"); - auto url = jni::Make(env, url_); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "onURL"); - url = callback.Call(env, method, kind, url); - auto urlStr = jni::Make(env, url); - jni::DeleteLocalRef(env, url); - return urlStr; + return jni::Make(env, + *jni::SeizeLocal(env, callback.Call(env, method, kind, + *jni::SeizeLocal(env, jni::Make(env, url_))))); } } // namespace android diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index e4295e1b8..f1b11c754 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -25,8 +25,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; } static std::string onURL(jni::JNIEnv&, jni::Object, int, std::string); - - static jni::Class javaClass; }; FileSource(jni::JNIEnv&, jni::String, jni::String, jni::Object); @@ -47,8 +45,6 @@ public: jni::jboolean isResumed(jni::JNIEnv&); - static jni::Class javaClass; - static FileSource* getNativePeer(jni::JNIEnv&, jni::Object); static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/geojson/conversion/feature.cpp b/platform/android/src/geojson/conversion/feature.cpp index 3cb6d37b1..7386e29df 100644 --- a/platform/android/src/geojson/conversion/feature.cpp +++ b/platform/android/src/geojson/conversion/feature.cpp @@ -1,13 +1,13 @@ #include "feature.hpp" -#include "../../conversion/constant.hpp" -#include "../../conversion/conversion.hpp" -#include "../../jni/local_object.hpp" +#include "../../gson/json_object.hpp" namespace mbgl { namespace android { namespace conversion { +using namespace gson; + /** * Turn feature identifier into std::string */ @@ -29,158 +29,22 @@ public: }; -/** - * Turn properties into Java GSON JsonObject's - */ -class PropertyValueEvaluator { -public: - jni::JNIEnv& env; +jni::Object convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { + using namespace mbgl::android::geojson; - /** - * null - */ - jni::jobject* operator()(const mapbox::geometry::null_value_t &) const { - return (jni::jobject*) nullptr; - } - - /** - * Boolean primitive - */ - jni::jobject* operator()(const bool& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/Boolean;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted); - - return object; - } - - /** - * String primitive - */ - jni::jobject* operator()(const std::string& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/String;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - /** - * Number primitives - */ - template - jni::jobject* operator()(const Number& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/Number;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - - /** - * Json Array - */ - jni::jobject* operator()(const std::vector &values) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V"); - - // Create json array - jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor); - - // Add values - for (const auto &v : values) { - jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this)); - jni::CallMethod(env, jarray, *add, converted.get()); - } - - return jarray; - } - - /** - * Json Object - */ - jni::jobject* operator()(const std::unordered_map &value) const { - // TODO: clean up duplication here - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); - - // Create json object - jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); - - // Add items - for (auto &item : value) { - jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this)); - jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); - jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); - } - - return jsonObject; - } -}; - -Result Converter>::operator()(jni::JNIEnv& env, const std::unordered_map& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); - - // Create json object - jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); - - // Add items - PropertyValueEvaluator evaluator {env}; - for (auto &item : value) { - jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator)); - jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); - jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); - } - - return {jsonObject}; -} - -Result> Converter, mbgl::Feature>::operator()(jni::JNIEnv& env, const mbgl::Feature& value) const { - - // Convert Id - FeatureIdVisitor idEvaluator; - std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : ""; - auto jid = jni::Make(env, id); - - // Convert properties - auto properties = jni::Object(*convert(env, value.properties)); - - // Convert geometry - auto geometry = android::geojson::Geometry::New(env, value.geometry); - - // Create feature - auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid); - - //Cleanup - jni::DeleteLocalRef(env, jid); - jni::DeleteLocalRef(env, geometry); - jni::DeleteLocalRef(env, properties); - - return feature; + return Feature::fromGeometry(env, + *jni::SeizeLocal(env, Geometry::New(env, value.geometry)), + *jni::SeizeLocal(env, JsonObject::New(env, value.properties)), + *jni::SeizeLocal(env, jni::Make(env, value.id ? value.id.value().match(FeatureIdVisitor()) : ""))); } Result>> Converter>, std::vector>::operator()(jni::JNIEnv& env, const std::vector& value) const { using namespace mbgl::android::geojson; - auto features = jni::Array>::New(env, value.size(), Feature::javaClass); - for(size_t i = 0; i < value.size(); i = i + 1) { - auto converted = *convert, mbgl::Feature>(env, value.at(i)); - features.Set(env, i, converted); - jni::DeleteLocalRef(env, converted); + auto features = jni::Array>::New(env, value.size()); + + for (size_t i = 0; i < value.size(); i = i + 1) { + features.Set(env, i, *jni::SeizeLocal(env, convertFeature(env, value.at(i)))); } return {features}; diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp index 031449cd2..d9fc0a0b6 100644 --- a/platform/android/src/geojson/conversion/feature.hpp +++ b/platform/android/src/geojson/conversion/feature.hpp @@ -7,22 +7,11 @@ #include #include -#include namespace mbgl { namespace android { namespace conversion { -template <> -struct Converter> { - Result operator()(jni::JNIEnv& env, const std::unordered_map& value) const; -}; - -template <> -struct Converter, mbgl::Feature> { - Result> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const; -}; - template <> struct Converter>, std::vector> { Result>> operator()(jni::JNIEnv& env, const std::vector& value) const; diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index d8a4e829e..1e02c756e 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -7,57 +7,50 @@ namespace android { namespace geojson { mbgl::Feature Feature::convert(jni::JNIEnv& env, jni::Object jFeature) { - // Convert - auto jGeometry = geometry(env, jFeature); - auto jProperties = Feature::properties(env, jFeature); + auto jGeometry = jni::SeizeLocal(env, geometry(env, jFeature)); + auto jProperties = jni::SeizeLocal(env, Feature::properties(env, jFeature)); std::experimental::optional id; - auto jId = Feature::id(env, jFeature); + auto jId = jni::SeizeLocal(env, Feature::id(env, jFeature)); if (jId) { - id = { jni::Make(env, jId) }; + id = { jni::Make(env, *jId) }; } - auto feature = mbgl::Feature { - Geometry::convert(env, jGeometry), - gson::JsonObject::convert(env, jProperties), - id + return mbgl::Feature { + Geometry::convert(env, *jGeometry), + gson::JsonObject::convert(env, *jProperties), + id }; - - // Cleanup - jni::DeleteLocalRef(env, jGeometry); - jni::DeleteLocalRef(env, jProperties); - jni::DeleteLocalRef(env, jId); - - return feature; } jni::Object Feature::geometry(jni::JNIEnv& env, jni::Object jFeature) { - static auto method = Feature::javaClass.GetMethod ()>(env, "geometry"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "geometry"); return jFeature.Call(env, method); } jni::Object Feature::properties(jni::JNIEnv& env, jni::Object jFeature) { - static auto method = Feature::javaClass.GetMethod ()>(env, "properties"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "properties"); return jFeature.Call(env, method); } jni::String Feature::id(jni::JNIEnv& env, jni::Object jFeature) { - static auto method = Feature::javaClass.GetMethod(env, "id"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "id"); return jFeature.Call(env, method); } jni::Object Feature::fromGeometry(jni::JNIEnv& env, jni::Object geometry, jni::Object properties, jni::String id) { - static auto method = Feature::javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); - return Feature::javaClass.Call(env, method, geometry, properties, id); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); + return javaClass.Call(env, method, geometry, properties, id); } void Feature::registerNative(jni::JNIEnv& env) { - // Lookup the class - Feature::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Feature::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp index ab59d783e..de38e9b1e 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -28,10 +28,7 @@ public: static jni::Object properties(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; } // namespace geojson diff --git a/platform/android/src/geojson/feature_collection.cpp b/platform/android/src/geojson/feature_collection.cpp index 18a41d48f..c2825e037 100644 --- a/platform/android/src/geojson/feature_collection.cpp +++ b/platform/android/src/geojson/feature_collection.cpp @@ -10,35 +10,28 @@ mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, jni::Object auto collection = mbgl::FeatureCollection(); if (jCollection) { - auto jFeatureList = FeatureCollection::features(env, jCollection); - auto jFeatures = java::util::List::toArray(env, jFeatureList); - auto size = size_t(jFeatures.Length(env)); + auto jFeatureList = jni::SeizeLocal(env, FeatureCollection::features(env, jCollection)); + auto jFeatures = jni::SeizeLocal(env, java::util::List::toArray(env, *jFeatureList)); + auto size = size_t(jFeatures->Length(env)); collection.reserve(size); for (size_t i = 0; i < size; i++) { - auto jFeature = jFeatures.Get(env, i); - collection.push_back(Feature::convert(env, jFeature)); - jni::DeleteLocalRef(env, jFeature); + collection.push_back(Feature::convert(env, *jni::SeizeLocal(env, jFeatures->Get(env, i)))); } - - jni::DeleteLocalRef(env, jFeatures); - jni::DeleteLocalRef(env, jFeatureList); } return collection; } jni::Object FeatureCollection::features(jni::JNIEnv& env, jni::Object jCollection) { - static auto method = FeatureCollection::javaClass.GetMethod ()>(env, "features"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "features"); return jCollection.Call(env, method); } void FeatureCollection::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class FeatureCollection::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/feature_collection.hpp b/platform/android/src/geojson/feature_collection.hpp index 259ffab37..1b45cca5d 100644 --- a/platform/android/src/geojson/feature_collection.hpp +++ b/platform/android/src/geojson/feature_collection.hpp @@ -19,8 +19,6 @@ public: static jni::Object features(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp index 5635b5a0f..4262b4ee6 100644 --- a/platform/android/src/geojson/geometry.cpp +++ b/platform/android/src/geojson/geometry.cpp @@ -23,31 +23,31 @@ public: jni::JNIEnv& env; jni::Object operator()(const mbgl::Point &geometry) const { - return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass); + return Point::New(env, geometry); } jni::Object operator()(const mbgl::LineString &geometry) const { - return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass); + return LineString::New(env, geometry); } jni::Object operator()(const mbgl::MultiLineString &geometry) const { - return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass); + return MultiLineString::New(env, geometry); } jni::Object operator()(const mbgl::MultiPoint &geometry) const { - return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass); + return MultiPoint::New(env, geometry); } jni::Object operator()(const mbgl::Polygon &geometry) const { - return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass); + return Polygon::New(env, geometry); } jni::Object operator()(const mbgl::MultiPolygon &geometry) const { - return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass); + return MultiPolygon::New(env, geometry); } jni::Object operator()(const mapbox::geometry::geometry_collection &geometry) const { - return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass); + return GeometryCollection::New(env, geometry); } }; @@ -78,20 +78,15 @@ mbgl::Geometry Geometry::convert(jni::JNIEnv &env, jni::Object } std::string Geometry::getType(jni::JNIEnv &env, jni::Object jGeometry) { - static auto method = Geometry::javaClass.GetMethod(env, "type"); - auto jType = jGeometry.Call(env, method); - auto type = jni::Make(env, jType); - jni::DeleteLocalRef(env, jType); - return type; + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "type"); + return jni::Make(env, *jni::SeizeLocal(env, jGeometry.Call(env, method))); } void Geometry::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Geometry::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/geometry.hpp b/platform/android/src/geojson/geometry.hpp index a1bb88668..836c3bd5a 100644 --- a/platform/android/src/geojson/geometry.hpp +++ b/platform/android/src/geojson/geometry.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include "../java/util.hpp" @@ -11,7 +10,7 @@ namespace mbgl { namespace android { namespace geojson { -class Geometry : private mbgl::util::noncopyable { +class Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; }; @@ -21,8 +20,6 @@ public: static std::string getType(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry_collection.cpp b/platform/android/src/geojson/geometry_collection.cpp index 770cb9a5d..ad0af7121 100644 --- a/platform/android/src/geojson/geometry_collection.cpp +++ b/platform/android/src/geojson/geometry_collection.cpp @@ -7,57 +7,43 @@ namespace geojson { jni::Object GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection& collection) { // Create an array of geometries - auto jarray = jni::Array>::New(env, collection.size(), Geometry::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array>::New(env, collection.size())); for (size_t i = 0; i < collection.size(); i++) { - auto& geometry = collection.at(i); - auto jGeometry = Geometry::New(env, geometry); - jarray.Set(env, i, jGeometry); - jni::DeleteLocalRef(env, jGeometry); + jarray->Set(env, i, *jni::SeizeLocal(env, Geometry::New(env, collection.at(i)))); } - // Turn into array list - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - // create the GeometryCollection + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromGeometries"); - auto jCollection = javaClass.Call(env, method, jList); - - jni::DeleteLocalRef(env, jList); - return jCollection; + return javaClass.Call(env, method, *jni::SeizeLocal(env, java::util::Arrays::asList(env, *jarray))); } mapbox::geometry::geometry_collection GeometryCollection::convert(jni::JNIEnv &env, jni::Object jCollection) { // Get geometries + static auto javaClass = jni::Class::Singleton(env); static auto getGeometries = javaClass.GetMethod ()>(env, "geometries"); - auto jList = jCollection.Call(env, getGeometries); // Turn into array - auto jarray = java::util::List::toArray(env, jList); - jni::DeleteLocalRef(env, jList); + auto jarray = jni::SeizeLocal(env, + java::util::List::toArray(env, + *jni::SeizeLocal(env, jCollection.Call(env, getGeometries)))); // Convert each geometry mapbox::geometry::geometry_collection collection{}; - auto size = jarray.Length(env); + auto size = jarray->Length(env); for (jni::jsize i = 0; i < size; i++) { - auto element = jarray.Get(env, i); - collection.push_back(Geometry::convert(env, element)); - jni::DeleteLocalRef(env, element); + collection.push_back(Geometry::convert(env, *jni::SeizeLocal(env, jarray->Get(env, i)))); } - jni::DeleteLocalRef(env, jarray); return collection; } void GeometryCollection::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class GeometryCollection::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/geometry_collection.hpp b/platform/android/src/geojson/geometry_collection.hpp index 9ed9953b0..a301d8693 100644 --- a/platform/android/src/geojson/geometry_collection.hpp +++ b/platform/android/src/geojson/geometry_collection.hpp @@ -18,8 +18,6 @@ public: static mapbox::geometry::geometry_collection convert(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/line_string.cpp b/platform/android/src/geojson/line_string.cpp index a5f1a468c..5a18a02bb 100644 --- a/platform/android/src/geojson/line_string.cpp +++ b/platform/android/src/geojson/line_string.cpp @@ -8,22 +8,18 @@ namespace android { namespace geojson { jni::Object LineString::New(jni::JNIEnv& env, const mbgl::LineString& lineString) { - auto jList = asPointsList(env, lineString); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod(jni::Object)>(env, "fromLngLats"); - auto jLineString = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jLineString; + return javaClass.Call(env, method, + *jni::SeizeLocal(env, asPointsList(env, lineString))); } mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object jLineString) { mapbox::geojson::line_string lineString; if (jLineString) { - auto jPointList = LineString::coordinates(env, jLineString); - lineString = LineString::convert(env, jPointList); - jni::DeleteLocalRef(env, jPointList); + lineString = LineString::convert(env, *jni::SeizeLocal(env, LineString::coordinates(env, jLineString))); } return lineString; @@ -33,34 +29,28 @@ mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object(env, jPointList); - auto size = jPointArray.Length(env); + auto jPointArray = jni::SeizeLocal(env, java::util::List::toArray(env, jPointList)); + auto size = jPointArray->Length(env); lineString.reserve(size); for (std::size_t i = 0; i < size; i++) { - auto jPoint = jPointArray.Get(env, i); - lineString.push_back(Point::convert(env, jPoint)); - jni::DeleteLocalRef(env, jPoint); + lineString.push_back(Point::convert(env, *jni::SeizeLocal(env, jPointArray->Get(env, i)))); } - - jni::DeleteLocalRef(env, jPointArray); } return lineString; } jni::Object LineString::coordinates(jni::JNIEnv &env, jni::Object jLineString) { - static auto method = LineString::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jLineString.Call(env, method); } void LineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class LineString::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/line_string.hpp b/platform/android/src/geojson/line_string.hpp index 98dc41464..4df934918 100644 --- a/platform/android/src/geojson/line_string.hpp +++ b/platform/android/src/geojson/line_string.hpp @@ -28,8 +28,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_line_string.cpp b/platform/android/src/geojson/multi_line_string.cpp index 4a6ea37dd..0a0974062 100644 --- a/platform/android/src/geojson/multi_line_string.cpp +++ b/platform/android/src/geojson/multi_line_string.cpp @@ -8,22 +8,19 @@ namespace android { namespace geojson { jni::Object MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString& multiLineString) { - auto jList = asPointsListsList(env, multiLineString); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - auto jMultiLineString = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jMultiLineString; + return javaClass.Call(env, method, + *jni::SeizeLocal(env, asPointsListsList(env, multiLineString))); } mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object jMultiLineString) { mapbox::geojson::multi_line_string multiLineString; if (jMultiLineString) { - auto jPointListsList = MultiLineString::coordinates(env, jMultiLineString); - multiLineString = MultiLineString::convert(env, jPointListsList); - jni::DeleteLocalRef(env, jPointListsList); + multiLineString = MultiLineString::convert(env, + *jni::SeizeLocal(env, MultiLineString::coordinates(env, jMultiLineString))); } return multiLineString; @@ -33,35 +30,29 @@ mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jn mapbox::geojson::multi_line_string multiLineString; if (jPointListsList) { - auto jPositionListsArray = java::util::List::toArray(env, jPointListsList); + auto jPositionListsArray = jni::SeizeLocal(env, java::util::List::toArray(env, jPointListsList)); - auto size = jPositionListsArray.Length(env); + auto size = jPositionListsArray->Length(env); multiLineString.reserve(size); for (std::size_t i = 0; i < size; i++) { - auto jPointsList = jPositionListsArray.Get(env, i); - multiLineString.push_back(LineString::convert(env, jPointsList)); - jni::DeleteLocalRef(env, jPointsList); + multiLineString.push_back(LineString::convert(env, *jni::SeizeLocal(env, jPositionListsArray->Get(env, i)))); } - - jni::DeleteLocalRef(env, jPositionListsArray); } return multiLineString; } jni::Object MultiLineString::coordinates(jni::JNIEnv &env, jni::Object jLineString) { - static auto method = MultiLineString::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jLineString.Call(env, method); } void MultiLineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class MultiLineString::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_line_string.hpp b/platform/android/src/geojson/multi_line_string.hpp index 934a0cb6b..c66aadaf0 100644 --- a/platform/android/src/geojson/multi_line_string.hpp +++ b/platform/android/src/geojson/multi_line_string.hpp @@ -26,8 +26,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_point.cpp b/platform/android/src/geojson/multi_point.cpp index 6f6254120..5f51058f3 100644 --- a/platform/android/src/geojson/multi_point.cpp +++ b/platform/android/src/geojson/multi_point.cpp @@ -9,39 +9,33 @@ namespace android { namespace geojson { jni::Object MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint& multiPoint) { - auto jList = asPointsList(env, multiPoint); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod(jni::Object)>(env, "fromLngLats"); - auto jMultiPoint = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jMultiPoint; + return javaClass.Call(env, method, *jni::SeizeLocal(env, asPointsList(env, multiPoint))); } mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object jMultiPoint) { mapbox::geojson::multi_point multiPoint; if (jMultiPoint) { - auto jPointListsList = MultiPoint::coordinates(env, jMultiPoint); - multiPoint = convertExplicit(LineString::convert(env, jPointListsList)); - jni::DeleteLocalRef(env, jPointListsList); + multiPoint = convertExplicit( + LineString::convert(env, *jni::SeizeLocal(env, MultiPoint::coordinates(env, jMultiPoint)))); } return multiPoint; } jni::Object MultiPoint::coordinates(jni::JNIEnv &env, jni::Object jMultiPoint) { - static auto method = MultiPoint::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jMultiPoint.Call(env, method); } void MultiPoint::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class MultiPoint::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_point.hpp b/platform/android/src/geojson/multi_point.hpp index cfe80cd34..0df16bfd6 100644 --- a/platform/android/src/geojson/multi_point.hpp +++ b/platform/android/src/geojson/multi_point.hpp @@ -25,8 +25,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_polygon.cpp b/platform/android/src/geojson/multi_polygon.cpp index cc872d495..109ac714c 100644 --- a/platform/android/src/geojson/multi_polygon.cpp +++ b/platform/android/src/geojson/multi_polygon.cpp @@ -8,62 +8,48 @@ namespace android { namespace geojson { jni::Object MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon& multiPolygon) { - auto jarray = jni::Array>::New(env, multiPolygon.size(), java::util::List::javaClass); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); + + auto jarray = jni::SeizeLocal(env, + jni::Array>::New(env, multiPolygon.size())); for (size_t i = 0; i < multiPolygon.size(); i++) { - auto& geometry = multiPolygon.at(i); - auto jPolygon = asPointsListsList(env, geometry); - jarray.Set(env, i, jPolygon); - jni::DeleteLocalRef(env, jPolygon); + jarray->Set(env, i, *jni::SeizeLocal(env, asPointsListsList(env, multiPolygon.at(i)))); } - // Turn into array list - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - - // create the MultiPolygon - static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - auto jMultiPolygon = javaClass.Call(env, method, jList); - - jni::DeleteLocalRef(env, jList); - return jMultiPolygon; + return javaClass.Call(env, method, + *jni::SeizeLocal(env, java::util::Arrays::asList(env, *jarray))); } mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object jMultiPolygon) { mapbox::geojson::multi_polygon multiPolygon; if (jMultiPolygon) { - auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon); - auto jPointListsListArray = java::util::List::toArray(env, jPointListsListList); + auto jPointListsListList = jni::SeizeLocal(env, MultiPolygon::coordinates(env, jMultiPolygon)); + auto jPointListsListArray = jni::SeizeLocal(env, java::util::List::toArray(env, *jPointListsListList)); - auto size = jPointListsListArray.Length(env); + auto size = jPointListsListArray->Length(env); multiPolygon.reserve(size); for (size_t i = 0; i < size; i++) { - auto jPositionListsList = jPointListsListArray.Get(env, i); - multiPolygon.push_back(Polygon::convert(env, jPositionListsList)); - jni::DeleteLocalRef(env, jPositionListsList); + multiPolygon.push_back(Polygon::convert(env, *jni::SeizeLocal(env, jPointListsListArray->Get(env, i)))); } - - jni::DeleteLocalRef(env, jPointListsListArray); - jni::DeleteLocalRef(env, jPointListsListList); } return multiPolygon; } jni::Object MultiPolygon::coordinates(jni::JNIEnv &env, jni::Object jPolygon) { - static auto method = MultiPolygon::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jPolygon.Call(env, method); } void MultiPolygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class MultiPolygon::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_polygon.hpp b/platform/android/src/geojson/multi_polygon.hpp index b4657af09..3477e989e 100644 --- a/platform/android/src/geojson/multi_polygon.hpp +++ b/platform/android/src/geojson/multi_polygon.hpp @@ -24,8 +24,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index 8a9656ea1..69da99725 100644 --- a/platform/android/src/geojson/point.cpp +++ b/platform/android/src/geojson/point.cpp @@ -8,6 +8,7 @@ namespace android { namespace geojson { jni::Object Point::New(jni::JNIEnv& env, const mbgl::Point& point) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::jdouble, jni::jdouble)>(env, "fromLngLat"); return javaClass.Call(env, method, point.x, point.y); } @@ -16,9 +17,7 @@ mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object jPoin mapbox::geojson::point point; if (jPoint) { - auto jDoubleList = Point::coordinates(env, jPoint); - point = Point::convert(env, jDoubleList); - jni::DeleteLocalRef(env, jDoubleList); + point = Point::convert(env, *jni::SeizeLocal(env, Point::coordinates(env, jPoint))); } return point; @@ -28,35 +27,29 @@ mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object(env, jDoubleList); + auto jDoubleArray = jni::SeizeLocal(env, java::util::List::toArray(env, jDoubleList)); - auto lonObject = jDoubleArray.Get(env, 0); - auto latObject = jDoubleArray.Get(env, 1); + auto lonObject = jni::SeizeLocal(env, jDoubleArray->Get(env, 0)); + auto latObject = jni::SeizeLocal(env, jDoubleArray->Get(env, 1)); - point.x = jni::CallMethod(env, lonObject, + point.x = jni::CallMethod(env, *lonObject, *java::Number::doubleValueMethodId); - point.y = jni::CallMethod(env, latObject, + point.y = jni::CallMethod(env, *latObject, *java::Number::doubleValueMethodId); - - jni::DeleteLocalRef(env, lonObject); - jni::DeleteLocalRef(env, latObject); - jni::DeleteLocalRef(env, jDoubleArray); } return point; } jni::Object Point::coordinates(jni::JNIEnv &env, jni::Object jPoint) { - static auto method = Point::javaClass.GetMethod ()>(env, "coordinates"); - return jPoint.Call(env, method); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); + return jPoint.Call(env, method); } void Point::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Point::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp index 627bd1b64..3a852a3e7 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -26,8 +26,6 @@ public: static jni::Object coordinates(JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp index 96058b63b..add843e29 100644 --- a/platform/android/src/geojson/polygon.cpp +++ b/platform/android/src/geojson/polygon.cpp @@ -9,22 +9,17 @@ namespace android { namespace geojson { jni::Object Polygon::New(jni::JNIEnv& env, const mbgl::Polygon& polygon) { - auto jList = asPointsListsList(env, polygon); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - auto jPolygon = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jPolygon; + return javaClass.Call(env, method, *jni::SeizeLocal(env, asPointsListsList(env, polygon))); } mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object jPolygon) { mapbox::geojson::polygon polygon; if (jPolygon) { - auto jPositionListsList = Polygon::coordinates(env, jPolygon); - polygon = Polygon::convert(env, jPositionListsList); - jni::DeleteLocalRef(env, jPositionListsList); + polygon = Polygon::convert(env, *jni::SeizeLocal(env, Polygon::coordinates(env, jPolygon))); } return polygon; @@ -46,17 +41,15 @@ mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object Polygon::coordinates(jni::JNIEnv &env, jni::Object jPolygon) { - static auto method = Polygon::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jPolygon.Call(env, method); } void Polygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Polygon::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/polygon.hpp b/platform/android/src/geojson/polygon.hpp index f3c23b4d7..adfa60df4 100644 --- a/platform/android/src/geojson/polygon.hpp +++ b/platform/android/src/geojson/polygon.hpp @@ -27,8 +27,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv &); }; diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp index 5e6d90a95..e889931c5 100644 --- a/platform/android/src/geojson/util.hpp +++ b/platform/android/src/geojson/util.hpp @@ -24,17 +24,13 @@ To convertExplicit(From&& src) { */ template static jni::Object asPointsList(jni::JNIEnv& env, const T& pointsList) { - auto jarray = jni::Array>::New(env, pointsList.size(), Point::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array>::New(env, pointsList.size())); for (jni::jsize i = 0; i < pointsList.size(); i++) { - auto jPoint = Point::New(env, pointsList.at(i)); - jarray.Set(env, i, jPoint); - jni::DeleteLocalRef(env, jPoint); + jarray->Set(env, i, *jni::SeizeLocal(env, Point::New(env, pointsList.at(i)))); } - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - return jList; + return java::util::Arrays::asList(env, *jarray); } /** @@ -42,17 +38,13 @@ static jni::Object asPointsList(jni::JNIEnv& env, const T& poi */ template static jni::Object asPointsListsList(JNIEnv& env, SHAPE value) { - auto jarray = jni::Array>::New(env, value.size(), java::util::List::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array>::New(env, value.size())); - for (size_t i = 0; i < value.size(); i = i + 1) { - auto pointsList = asPointsList(env, value[i]); - jarray.Set(env, i, pointsList); - jni::DeleteLocalRef(env, pointsList); + for (size_t i = 0; i < value.size(); i++) { + jarray->Set(env, i, *jni::SeizeLocal(env, asPointsList(env, value[i]))); } - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - return jList; + return java::util::Arrays::asList(env, *jarray); } } // namespace geojson diff --git a/platform/android/src/geometry/lat_lng.cpp b/platform/android/src/geometry/lat_lng.cpp index 0bf6ea7ad..135755d67 100644 --- a/platform/android/src/geometry/lat_lng.cpp +++ b/platform/android/src/geometry/lat_lng.cpp @@ -4,13 +4,15 @@ namespace mbgl { namespace android { jni::Object LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { - static auto constructor = LatLng::javaClass.GetConstructor(env); - return LatLng::javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); } mbgl::Point LatLng::getGeometry(jni::JNIEnv& env, jni::Object latLng) { - static auto latitudeField = LatLng::javaClass.GetField(env, "latitude"); - static auto longitudeField = LatLng::javaClass.GetField(env, "longitude"); + static auto javaClass = jni::Class::Singleton(env); + static auto latitudeField = javaClass.GetField(env, "latitude"); + static auto longitudeField = javaClass.GetField(env, "longitude"); return mbgl::Point(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField)); } @@ -20,12 +22,8 @@ mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, jni::Object latLng) { } void LatLng::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLng::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class LatLng::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/lat_lng.hpp b/platform/android/src/geometry/lat_lng.hpp index b2f12c8dc..4431f1c73 100644 --- a/platform/android/src/geometry/lat_lng.hpp +++ b/platform/android/src/geometry/lat_lng.hpp @@ -20,10 +20,8 @@ public: static mbgl::LatLng getLatLng(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/geometry/lat_lng_bounds.cpp b/platform/android/src/geometry/lat_lng_bounds.cpp index 827ee52e9..583120cb6 100644 --- a/platform/android/src/geometry/lat_lng_bounds.cpp +++ b/platform/android/src/geometry/lat_lng_bounds.cpp @@ -4,15 +4,17 @@ namespace mbgl { namespace android { jni::Object LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { - static auto constructor = LatLngBounds::javaClass.GetConstructor(env); - return LatLngBounds::javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); } mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object bounds) { - static auto swLatField = LatLngBounds::javaClass.GetField(env, "latitudeSouth"); - static auto swLonField = LatLngBounds::javaClass.GetField(env, "longitudeWest"); - static auto neLatField = LatLngBounds::javaClass.GetField(env, "latitudeNorth"); - static auto neLonField = LatLngBounds::javaClass.GetField(env, "longitudeEast"); + static auto javaClass = jni::Class::Singleton(env); + static auto swLatField = javaClass.GetField(env, "latitudeSouth"); + static auto swLonField = javaClass.GetField(env, "longitudeWest"); + static auto neLatField = javaClass.GetField(env, "latitudeNorth"); + static auto neLonField = javaClass.GetField(env, "longitudeEast"); mbgl::LatLng sw = { bounds.Get(env, swLatField), bounds.Get(env, swLonField) }; mbgl::LatLng ne = { bounds.Get(env, neLatField), bounds.Get(env, neLonField) }; @@ -23,12 +25,8 @@ mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class LatLngBounds::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/lat_lng_bounds.hpp b/platform/android/src/geometry/lat_lng_bounds.hpp index 1c853e4b6..751e0babd 100644 --- a/platform/android/src/geometry/lat_lng_bounds.hpp +++ b/platform/android/src/geometry/lat_lng_bounds.hpp @@ -18,10 +18,7 @@ public: static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/geometry/lat_lng_quad.cpp b/platform/android/src/geometry/lat_lng_quad.cpp index 2b36139e1..5530a2290 100644 --- a/platform/android/src/geometry/lat_lng_quad.cpp +++ b/platform/android/src/geometry/lat_lng_quad.cpp @@ -5,8 +5,9 @@ namespace mbgl { namespace android { jni::Object LatLngQuad::New(jni::JNIEnv& env, std::array coordinates) { - static auto quadConstructor = LatLngQuad::javaClass.GetConstructor, jni::Object, jni::Object, jni::Object>(env); - return LatLngQuad::javaClass.New(env, quadConstructor, + static auto javaClass = jni::Class::Singleton(env); + static auto quadConstructor = javaClass.GetConstructor, jni::Object, jni::Object, jni::Object>(env); + return javaClass.New(env, quadConstructor, LatLng::New(env, coordinates[0]), LatLng::New(env, coordinates[1]), LatLng::New(env, coordinates[2]), @@ -14,10 +15,11 @@ jni::Object LatLngQuad::New(jni::JNIEnv& env, std::array LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Object quad) { - static auto topLeftField = LatLngQuad::javaClass.GetField >(env, "topLeft"); - static auto topRightField = LatLngQuad::javaClass.GetField >(env, "topRight"); - static auto bottomRightField = LatLngQuad::javaClass.GetField >(env, "bottomRight"); - static auto bottomLeftField = LatLngQuad::javaClass.GetField >(env, "bottomLeft"); + static auto javaClass = jni::Class::Singleton(env); + static auto topLeftField = javaClass.GetField >(env, "topLeft"); + static auto topRightField = javaClass.GetField >(env, "topRight"); + static auto bottomRightField = javaClass.GetField >(env, "bottomRight"); + static auto bottomLeftField = javaClass.GetField >(env, "bottomLeft"); return std::array < mbgl::LatLng, 4 > {{ LatLng::getLatLng(env, quad.Get(env, topLeftField)), @@ -28,12 +30,8 @@ std::array LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Ob } void LatLngQuad::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLngQuad::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class LatLngQuad::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/lat_lng_quad.hpp b/platform/android/src/geometry/lat_lng_quad.hpp index 8f8c9abee..ca1430ffb 100644 --- a/platform/android/src/geometry/lat_lng_quad.hpp +++ b/platform/android/src/geometry/lat_lng_quad.hpp @@ -19,10 +19,7 @@ public: static std::array getLatLngArray(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/geometry/projected_meters.cpp b/platform/android/src/geometry/projected_meters.cpp index f3d9d1b0e..4dfd7b57b 100644 --- a/platform/android/src/geometry/projected_meters.cpp +++ b/platform/android/src/geometry/projected_meters.cpp @@ -4,17 +4,14 @@ namespace mbgl { namespace android { jni::Object ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { - static auto constructor = ProjectedMeters::javaClass.GetConstructor(env); - return ProjectedMeters::javaClass.New(env, constructor, northing, easting); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, northing, easting); } void ProjectedMeters::registerNative(jni::JNIEnv& env) { - // Lookup the class - ProjectedMeters::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class ProjectedMeters::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/projected_meters.hpp b/platform/android/src/geometry/projected_meters.hpp index 9b70967b5..5279e6bef 100644 --- a/platform/android/src/geometry/projected_meters.hpp +++ b/platform/android/src/geometry/projected_meters.hpp @@ -10,17 +10,12 @@ namespace android { class ProjectedMeters : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; }; static jni::Object New(jni::JNIEnv&, double, double); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/graphics/pointf.cpp b/platform/android/src/graphics/pointf.cpp index 3f854da2e..eceb65b07 100644 --- a/platform/android/src/graphics/pointf.cpp +++ b/platform/android/src/graphics/pointf.cpp @@ -5,23 +5,21 @@ namespace mbgl { namespace android { jni::Object PointF::New(jni::JNIEnv& env, float x, float y) { - static auto constructor = PointF::javaClass.GetConstructor(env); - return PointF::javaClass.New(env, constructor, x, y); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, x, y); } mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, jni::Object point) { - static auto xField = PointF::javaClass.GetField(env, "x"); - static auto yField = PointF::javaClass.GetField(env, "y"); + static auto javaClass = jni::Class::Singleton(env); + static auto xField = javaClass.GetField(env, "x"); + static auto yField = javaClass.GetField(env, "y"); return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)}; } void PointF::registerNative(jni::JNIEnv& env) { - // Lookup the class - PointF::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class PointF::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/graphics/pointf.hpp b/platform/android/src/graphics/pointf.hpp index e3ef24dd6..27bd49138 100644 --- a/platform/android/src/graphics/pointf.hpp +++ b/platform/android/src/graphics/pointf.hpp @@ -16,10 +16,7 @@ public: static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/graphics/rectf.cpp b/platform/android/src/graphics/rectf.cpp index 1b375dad1..9f05728b4 100644 --- a/platform/android/src/graphics/rectf.cpp +++ b/platform/android/src/graphics/rectf.cpp @@ -4,32 +4,32 @@ namespace mbgl { namespace android { float RectF::getLeft(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "left"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "left"); return rectf.Get(env, field); } float RectF::getTop(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "top"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "top"); return rectf.Get(env, field); } float RectF::getRight(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "right"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "right"); return rectf.Get(env, field); } float RectF::getBottom(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "bottom"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "bottom"); return rectf.Get(env, field); } void RectF::registerNative(jni::JNIEnv& env) { - // Lookup the class - RectF::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class RectF::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/graphics/rectf.hpp b/platform/android/src/graphics/rectf.hpp index 0f3a7756d..db836e78b 100644 --- a/platform/android/src/graphics/rectf.hpp +++ b/platform/android/src/graphics/rectf.hpp @@ -20,10 +20,7 @@ public: static float getBottom(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp index e8852d77e..333b402aa 100644 --- a/platform/android/src/gson/json_array.cpp +++ b/platform/android/src/gson/json_array.cpp @@ -7,15 +7,14 @@ namespace android { namespace gson { jni::Object JsonArray::New(jni::JNIEnv& env, const std::vector& values){ - static auto constructor = JsonArray::javaClass.GetConstructor(env); - static auto addMethod = JsonArray::javaClass.GetMethod)>(env, "add"); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod)>(env, "add"); - auto jsonArray = JsonArray::javaClass.New(env, constructor); + auto jsonArray = javaClass.New(env, constructor); for (const auto &v : values) { - auto jsonElement = JsonElement::New(env, v); - jsonArray.Call(env, addMethod, jsonElement); - jni::DeleteLocalRef(env, jsonElement); + jsonArray.Call(env, addMethod, *jni::SeizeLocal(env, JsonElement::New(env, v))); } return jsonArray; @@ -25,18 +24,18 @@ std::vector JsonArray::convert(jni::JNIEnv& env, const std::vector values; if (jsonArray) { - static auto getMethod = JsonArray::javaClass.GetMethod (jni::jint)>(env, "get"); - static auto sizeMethod = JsonArray::javaClass.GetMethod(env, "size"); + static auto javaClass = jni::Class::Singleton(env); + static auto getMethod = javaClass.GetMethod (jni::jint)>(env, "get"); + static auto sizeMethod = javaClass.GetMethod(env, "size"); int size = jsonArray.Call(env, sizeMethod); values.reserve(uint(size)); for (int i = 0; i < size; i++) { - auto entry = jsonArray.Call(env, getMethod, i); - if (entry) { - values.push_back(JsonElement::convert(env, entry)); + auto entry = jni::SeizeLocal(env, jsonArray.Call(env, getMethod, i)); + if (*entry) { + values.push_back(JsonElement::convert(env, *entry)); } - jni::DeleteLocalRef(env, entry); } } @@ -44,12 +43,9 @@ std::vector JsonArray::convert(jni::JNIEnv& env, const } void JsonArray::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class JsonArray::javaClass; - } // namespace gson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp index c9ae98692..e74b92176 100644 --- a/platform/android/src/gson/json_array.hpp +++ b/platform/android/src/gson/json_array.hpp @@ -1,7 +1,8 @@ #pragma once +#include "json_element.hpp" + #include -#include #include @@ -9,16 +10,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonArray : private mbgl::util::noncopyable { +class JsonArray : public JsonElement { public: static constexpr auto Name() { return "com/google/gson/JsonArray"; }; static jni::Object New(jni::JNIEnv&, const std::vector&); - static std::vector convert(JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp index 5eaaf531f..d5304ed67 100644 --- a/platform/android/src/gson/json_element.cpp +++ b/platform/android/src/gson/json_element.cpp @@ -20,17 +20,16 @@ public: jni::JNIEnv& env; jni::Object operator()(const JsonPrimitive::value value) const { - return jni::Cast(env, JsonPrimitive::New(env, value), JsonElement::javaClass); + return JsonPrimitive::New(env, value); } jni::Object operator()(const std::vector &values) const { - return jni::Cast(env, JsonArray::New(env, values), JsonElement::javaClass); + return JsonArray::New(env, values); } jni::Object operator()(const std::unordered_map &values) const { - return jni::Cast(env, JsonObject::New(env, values), JsonElement::javaClass); + return JsonObject::New(env, values); } - }; @@ -44,13 +43,16 @@ mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object::Singleton(env); + auto primitive = JsonPrimitive::convert(env, jni::Cast(env, primitiveClass, jsonElement)); value = mapbox::util::apply_visitor([](auto t) { return mapbox::geometry::value { t }; }, primitive); } else if (isJsonObject(env, jsonElement)) { - mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, jsonElement, JsonObject::javaClass)); + static auto objectClass = jni::Class::Singleton(env); + mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, objectClass, jsonElement)); value = mapbox::util::recursive_wrapper> { map } ; } else if (isJsonArray(env, jsonElement)) { - value = JsonArray::convert(env, jni::Cast(env, jsonElement, JsonArray::javaClass)); + static auto arrayClass = jni::Class::Singleton(env); + value = JsonArray::convert(env, jni::Cast(env, arrayClass, jsonElement)); } else { value = mapbox::geometry::null_value; } @@ -59,32 +61,33 @@ mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonObject"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonObject"); return jsonElement.Call(env, method); } bool JsonElement::isJsonArray(JNIEnv& env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonArray"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonArray"); return jsonElement.Call(env, method); } bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonPrimitive"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonPrimitive"); return jsonElement.Call(env, method); } bool JsonElement::isJsonNull(JNIEnv& env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonNull"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonNull"); return jsonElement.Call(env, method); } void JsonElement::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class JsonElement::javaClass; - } // namespace gson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp index d850caa52..5c6893487 100644 --- a/platform/android/src/gson/json_element.hpp +++ b/platform/android/src/gson/json_element.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include @@ -9,24 +8,18 @@ namespace mbgl { namespace android { namespace gson { -class JsonElement : private mbgl::util::noncopyable { +class JsonElement : public jni::ObjectTag { public: static constexpr auto Name() { return "com/google/gson/JsonElement"; }; static jni::Object New(jni::JNIEnv&, const mapbox::geometry::value&); - static mapbox::geometry::value convert(JNIEnv&, jni::Object); static bool isJsonObject(JNIEnv&, jni::Object); - static bool isJsonArray(JNIEnv&, jni::Object); - static bool isJsonPrimitive(JNIEnv&, jni::Object); - static bool isJsonNull(JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp index 61b55f8b9..4a2ec0756 100644 --- a/platform/android/src/gson/json_object.cpp +++ b/platform/android/src/gson/json_object.cpp @@ -10,17 +10,16 @@ namespace gson { jni::Object JsonObject::New(jni::JNIEnv& env, const std::unordered_map& values) { - static auto constructor = JsonObject::javaClass.GetConstructor(env); - static auto addMethod = JsonObject::javaClass.GetMethod)>(env, "add"); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod)>(env, "add"); - jni::Object jsonObject = JsonObject::javaClass.New(env, constructor); + jni::Object jsonObject = javaClass.New(env, constructor); for (auto &item : values) { - jni::Object jsonElement = JsonElement::New(env, item.second); - jni::String key = jni::Make(env, item.first); - jsonObject.Call(env, addMethod, key, jsonElement); - jni::DeleteLocalRef(env, jsonElement); - jni::DeleteLocalRef(env, key); + jsonObject.Call(env, addMethod, + *jni::SeizeLocal(env, jni::Make(env, item.first)), + *jni::SeizeLocal(env, JsonElement::New(env, item.second))); } return jsonObject; @@ -29,32 +28,22 @@ jni::Object JsonObject::New(jni::JNIEnv& env, const std::unordered_m template // void (jni::String, jni::Object) static void iterateEntrySet(jni::JNIEnv& env, jni::Object jsonObject, F callback) { // Get Set> - static auto method = JsonObject::javaClass.GetMethod ()>(env, "entrySet"); - auto entrySet = jsonObject.Call(env, method); - jni::Array> entryArray = java::util::Set::toArray(env, entrySet); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "entrySet"); - size_t size = entryArray.Length(env); + auto entryArray = + jni::SeizeLocal(env, java::util::Set::toArray(env, + *jni::SeizeLocal(env, jsonObject.Call(env, method)))); + + size_t size = entryArray->Length(env); for (size_t i = 0; i < size; i++) { - auto entry = entryArray.Get(env, i); + auto entry = jni::SeizeLocal(env, entryArray->Get(env, i)); if (entry) { - // Convert - auto jKey = java::util::Map::Entry::getKey(env, entry); - auto jKeyString = jni::String(reinterpret_cast(jKey.Get())); - auto jValue = java::util::Map::Entry::getValue(env, entry); - - // Callback - callback(jKeyString, jValue); - - // Cleanup - // Skip jKey as it points to the same as jKeyString - jni::DeleteLocalRef(env, jKeyString); - jni::DeleteLocalRef(env, jValue); + callback( + *jni::SeizeLocal(env, java::util::Map::Entry::getKey(env, *entry)), + *jni::SeizeLocal(env, java::util::Map::Entry::getValue(env, *entry))); } - jni::DeleteLocalRef(env, entry); } - - jni::DeleteLocalRef(env, entrySet); - jni::DeleteLocalRef(env, entryArray); } mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object jsonObject) { @@ -70,12 +59,9 @@ mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object } void JsonObject::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class JsonObject::javaClass; - } // namespace gson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp index 4bc61e51a..85e8828d9 100644 --- a/platform/android/src/gson/json_object.hpp +++ b/platform/android/src/gson/json_object.hpp @@ -1,7 +1,8 @@ #pragma once +#include "json_element.hpp" + #include -#include #include @@ -9,16 +10,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonObject : private mbgl::util::noncopyable { +class JsonObject : public JsonElement { public: static constexpr auto Name() { return "com/google/gson/JsonObject"; }; static jni::Object New(jni::JNIEnv&, const std::unordered_map&); - static mapbox::geometry::property_map convert(JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_primitive.cpp b/platform/android/src/gson/json_primitive.cpp index 4e171c484..2b0362913 100644 --- a/platform/android/src/gson/json_primitive.cpp +++ b/platform/android/src/gson/json_primitive.cpp @@ -1,5 +1,4 @@ #include "json_primitive.hpp" -#include "../java/lang.hpp" namespace mbgl { namespace android { @@ -24,58 +23,55 @@ public: * Create a primitive containing a string value */ jni::Object operator()(const std::string value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor(env); - auto jvalue = jni::Make(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, jvalue); - jni::DeleteLocalRef(env, jvalue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Make(env, value))); } /** * Create a primitive containing a number value with type double */ jni::Object operator()(const double value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(env); - auto boxedValue = java::lang::Double::valueOf(env, value); - auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); } /** * Create a primitive containing a number value with type long */ jni::Object operator()(const int64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(env); - auto boxedValue = java::lang::Long::valueOf(env, value); - auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); } /** * Create a primitive containing a number value with type long */ jni::Object operator()(const uint64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(env); - auto boxedValue = java::lang::Long::valueOf(env, value); - auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, int64_t(value))))); // TODO: should use BigInteger } /** * Create a primitive containing a boolean value */ jni::Object operator()(const bool value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(env); - auto boxedValue = java::lang::Boolean::valueOf(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, boxedValue); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Box(env, value ? jni::jni_true : jni::jni_false))); } }; @@ -102,45 +98,45 @@ JsonPrimitive::value JsonPrimitive::convert(jni::JNIEnv &env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "isBoolean"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isBoolean"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::isString(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "isString"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isString"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "isNumber"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isNumber"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsBoolean"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getAsBoolean"); return jsonPrimitive.Call(env, method); } std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsString"); - auto jString = jsonPrimitive.Call(env, method); - auto string = jni::Make(env, jString); - jni::DeleteLocalRef(env, jString); - return string; + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getAsString"); + return jni::Make(env, *jni::SeizeLocal(env, jsonPrimitive.Call(env, method))); } double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsDouble"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getAsDouble"); return jsonPrimitive.Call(env, method); } void JsonPrimitive::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class JsonPrimitive::javaClass; - } // namespace gson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp index c418e0ebe..d9e90507f 100644 --- a/platform/android/src/gson/json_primitive.hpp +++ b/platform/android/src/gson/json_primitive.hpp @@ -1,7 +1,8 @@ #pragma once +#include "json_element.hpp" + #include -#include #include @@ -9,30 +10,23 @@ namespace mbgl { namespace android { namespace gson { -class JsonPrimitive : private mbgl::util::noncopyable { +class JsonPrimitive : public JsonElement { public: using value = mapbox::util::variant; static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; static jni::Object New(jni::JNIEnv&, const value&); - static value convert(JNIEnv&, jni::Object); static bool isBoolean(JNIEnv&, jni::Object); - static bool isString(JNIEnv&, jni::Object); - static bool isNumber(JNIEnv&, jni::Object); static bool getAsBoolean(JNIEnv&, jni::Object); - static std::string getAsString(JNIEnv&, jni::Object); - static double getAsDouble(JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index fc7ffbec8..6b359aab8 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -32,8 +32,7 @@ public: jni::String retryAfter, jni::String xRateLimitReset, jni::Array body); - static jni::Class javaClass; - jni::UniqueObject javaRequest; + jni::Global> javaRequest; private: Resource resource; @@ -52,16 +51,14 @@ private: static const int permanentError = 2; }; -jni::Class HTTPRequest::javaClass; - namespace android { void RegisterNativeHTTPRequest(jni::JNIEnv& env) { - HTTPRequest::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) - jni::RegisterNativePeer(env, HTTPRequest::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", METHOD(&HTTPRequest::onFailure, "nativeOnFailure"), METHOD(&HTTPRequest::onResponse, "nativeOnResponse")); } @@ -82,6 +79,7 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10); + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); @@ -95,6 +93,7 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource HTTPRequest::~HTTPRequest() { android::UniqueEnv env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*env); static auto cancel = javaClass.GetMethod(*env, "cancel"); javaRequest->Call(*env, cancel); diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp index 045638157..a85e9aeaa 100644 --- a/platform/android/src/image.cpp +++ b/platform/android/src/image.cpp @@ -11,17 +11,12 @@ namespace mbgl { PremultipliedImage decodeImage(const std::string& string) { auto env{ android::AttachEnv() }; - auto array = jni::Array::New(*env, string.size()); - jni::SetArrayRegion(*env, *array, 0, string.size(), + auto array = jni::SeizeLocal(*env, jni::Array::New(*env, string.size())); + jni::SetArrayRegion(*env, **array, 0, string.size(), reinterpret_cast(string.data())); - auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size()); - jni::DeleteLocalRef(*env, array); - - auto image = android::Bitmap::GetImage(*env, bitmap); - jni::DeleteLocalRef(*env, bitmap); - - return image; + return android::Bitmap::GetImage(*env, + *jni::SeizeLocal(*env, android::BitmapFactory::DecodeByteArray(*env, *array, 0, string.size()))); } } // namespace mbgl diff --git a/platform/android/src/java/lang.cpp b/platform/android/src/java/lang.cpp deleted file mode 100644 index 3c9573716..000000000 --- a/platform/android/src/java/lang.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "lang.hpp" - -namespace mbgl { -namespace android { -namespace java { -namespace lang { - -// Float - -jni::Object Float::valueOf(JNIEnv &env, jfloat value) { - static auto method = javaClass.GetStaticMethod (jni::jfloat)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Float::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Float::javaClass; - -// Long - -jni::Object Long::valueOf(JNIEnv &env, jlong value) { - static auto method = javaClass.GetStaticMethod (jni::jlong)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Long::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Long::javaClass; - -// Double - -jni::Object Double::valueOf(JNIEnv &env, jdouble value) { - static auto method = javaClass.GetStaticMethod (jni::jdouble)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Double::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Double::javaClass; - -// Boolean - -jni::Object Boolean::valueOf(JNIEnv &env, jboolean value) { - static auto method = javaClass.GetStaticMethod (jni::jboolean)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Boolean::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Boolean::javaClass; - -// Number - -void Number::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Number::javaClass; - -} // namespace lang -} // namespace java -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/java/lang.hpp b/platform/android/src/java/lang.hpp deleted file mode 100644 index 981e3b14b..000000000 --- a/platform/android/src/java/lang.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include - -namespace mbgl { -namespace android { -namespace java { -namespace lang { - -class Float : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Float"; }; - - static jni::Object valueOf(JNIEnv&, jfloat); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Double : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Double"; }; - - static jni::Object valueOf(JNIEnv&, jdouble); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Long : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Long"; }; - - static jni::Object valueOf(JNIEnv&, jlong); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Boolean : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Boolean"; }; - - static jni::Object valueOf(JNIEnv&, jboolean); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Number : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Number"; }; - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -} // namespace lang -} // namespace java -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/java/util.cpp b/platform/android/src/java/util.cpp index 89c4c7779..b3aebb36c 100644 --- a/platform/android/src/java/util.cpp +++ b/platform/android/src/java/util.cpp @@ -5,21 +5,14 @@ namespace android { namespace java { namespace util { -jni::Class Arrays::javaClass; -jni::Class List::javaClass; -jni::Class Set::javaClass; -jni::Class Map::javaClass; -jni::Class Map::Entry::javaClass; - void registerNative(jni::JNIEnv& env) { - Arrays::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - List::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - Set::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - Map::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - Map::Entry::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); } - } // namespace util } // namespace java } // namespace android diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp index c6b07acac..808f14be1 100644 --- a/platform/android/src/java/util.hpp +++ b/platform/android/src/java/util.hpp @@ -11,51 +11,43 @@ namespace util { class List : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/List"; }; template static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { - static auto toArray = List::javaClass.GetMethod> ()>(env, "toArray"); + static auto javaClass = jni::Class::Singleton(env); + static auto toArray = javaClass.GetMethod> ()>(env, "toArray"); return (jni::Array>) list.Call(env, toArray); }; - - static jni::Class javaClass; - }; class Arrays : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Arrays"; }; template static jni::Object asList(jni::JNIEnv& env, jni::Array> array) { - static auto asList = Arrays::javaClass.GetStaticMethod(jni::Array>)>(env, "asList"); + static auto javaClass = jni::Class::Singleton(env); + static auto asList = javaClass.GetStaticMethod(jni::Array>)>(env, "asList"); return javaClass.Call(env, asList, (jni::Array>) array); } - - static jni::Class javaClass; - }; class Set : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Set"; }; template static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { - static auto toArray = Set::javaClass.GetMethod> ()>(env, "toArray"); + static auto javaClass = jni::Class::Singleton(env); + static auto toArray = javaClass.GetMethod> ()>(env, "toArray"); return (jni::Array>) list.Call(env, toArray); }; - - static jni::Class javaClass; - }; class Map : private mbgl::util::noncopyable { public: + static constexpr auto Name() { return "java/util/Map"; }; class Entry : private mbgl::util::noncopyable { public: @@ -63,27 +55,22 @@ public: template static jni::Object getKey(jni::JNIEnv& env, jni::Object entry) { - static auto method = Entry::javaClass.GetMethod ()>(env, "getKey"); - return (jni::Object) entry.Call(env, method); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "getKey"); + return jni::Cast(env, jni::Class::Singleton(env), entry.Call(env, method)); } template static jni::Object getValue(jni::JNIEnv& env, jni::Object entry) { - static auto method = Entry::javaClass.GetMethod ()>(env, "getValue"); - return (jni::Object) entry.Call(env, method).Get(); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "getValue"); + return jni::Cast(env, jni::Class::Singleton(env), entry.Call(env, method)); } - - static jni::Class javaClass; }; - - static constexpr auto Name() { return "java/util/Map"; }; - - static jni::Class javaClass; }; void registerNative(jni::JNIEnv&); - } // namespace util } // namespace java } // namespace android diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 872d8bc89..abea7f450 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -48,7 +48,6 @@ #include "snapshotter/map_snapshot.hpp" #include "text/collator_jni.hpp" #include "text/local_glyph_rasterizer_jni.hpp" -#include "java/lang.hpp" #include "logger.hpp" namespace mbgl { @@ -115,11 +114,6 @@ void registerNatives(JavaVM *vm) { java::util::registerNative(env); PointF::registerNative(env); RectF::registerNative(env); - java::lang::Number::registerNative(env); - java::lang::Float::registerNative(env); - java::lang::Boolean::registerNative(env); - java::lang::Double::registerNative(env); - java::lang::Long::registerNative(env); // GeoJSON geojson::Feature::registerNative(env); diff --git a/platform/android/src/jni/generic_global_ref_deleter.hpp b/platform/android/src/jni/generic_global_ref_deleter.hpp index 7239e361a..b865ee9f8 100644 --- a/platform/android/src/jni/generic_global_ref_deleter.hpp +++ b/platform/android/src/jni/generic_global_ref_deleter.hpp @@ -12,39 +12,33 @@ namespace android { struct GenericGlobalRefDeleter { void operator()(jni::jobject* p) const { if (p) { - auto env = AttachEnv(); - env->DeleteGlobalRef(jni::Unwrap(p)); + AttachEnv()->DeleteGlobalRef(jni::Unwrap(p)); } } }; - -template < class TagType > -class GenericWeakObjectRefDeleter; - -template < class TagType = jni::ObjectTag > -using GenericUniqueWeakObject = std::unique_ptr< const jni::Object, GenericWeakObjectRefDeleter >; - -template < class TagType > -class GenericWeakObjectRefDeleter -{ -public: - using pointer = jni::PointerToValue< jni::Object >; - - void operator()(pointer p) const - { - if (p) - { - auto env = AttachEnv(); - env->DeleteWeakGlobalRef(jni::Unwrap(p->Get())); +struct GenericWeakGlobalRefDeleter { + void operator()(jni::jobject* p) const { + if (p) { + AttachEnv()->DeleteWeakGlobalRef(jni::Unwrap(p)); } } }; -template < class TagType > -GenericUniqueWeakObject SeizeGenericWeakRef(JNIEnv&, jni::Object&& object) -{ - return GenericUniqueWeakObject(jni::PointerToValue>(std::move(object)), GenericWeakObjectRefDeleter()); +template < class T > +using GenericGlobal = jni::UniquePointerlike< T, GenericGlobalRefDeleter >; + +template < class T > +using GenericWeak = jni::UniquePointerlike< T, GenericWeakGlobalRefDeleter >; + +template < class T > +GenericGlobal SeizeGenericGlobal(T&& t) { + return GenericGlobal(std::move(t), GenericGlobalRefDeleter()); +}; + +template < class T > +GenericWeak SeizeGenericWeak(T&& t) { + return GenericWeak(std::move(t), GenericWeakGlobalRefDeleter()); }; } // namespace android diff --git a/platform/android/src/jni/local_object.hpp b/platform/android/src/jni/local_object.hpp deleted file mode 100644 index 00fc4a193..000000000 --- a/platform/android/src/jni/local_object.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -namespace jni { - - class LocalRefDeleter { - private: - JNIEnv* env = nullptr; - - public: - LocalRefDeleter() = default; - LocalRefDeleter(JNIEnv& e) : env(&e) {} - - void operator()(jobject* object) const { - if (object) { - assert(env); - DeleteLocalRef(*env, object); - } - } - }; - - template < class T > - using LocalObject = std::unique_ptr< T, LocalRefDeleter >; - - /** - * Use a LocalObject to discard of local references as soon as possible - */ - template < class T > - LocalObject NewLocalObject(JNIEnv& env, T* t) { - return LocalObject(t, LocalRefDeleter(env)); - } -} diff --git a/platform/android/src/logger.cpp b/platform/android/src/logger.cpp index 0ade91460..ddc4d8452 100644 --- a/platform/android/src/logger.cpp +++ b/platform/android/src/logger.cpp @@ -5,32 +5,29 @@ namespace mbgl { namespace android { void Logger::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Logger::_class; - void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) { - auto tag = jni::Make(env, "Mbgl"); - auto message = jni::Make(env, msg); + static auto _class = jni::Class::Singleton(env); + + auto tag = jni::SeizeLocal(env, jni::Make(env, "Mbgl")); + auto message = jni::SeizeLocal(env, jni::Make(env, msg)); using Signature = void(jni::String, jni::String); if (severity == EventSeverity::Debug) { auto static debug = _class.GetStaticMethod(env, "d"); - _class.Call(env, debug, tag, message); + _class.Call(env, debug, *tag, *message); } else if (severity == EventSeverity::Info) { auto static info = _class.GetStaticMethod(env, "i"); - _class.Call(env, info, tag, message); + _class.Call(env, info, *tag, *message); } else if(severity == EventSeverity::Warning) { auto static warning = _class.GetStaticMethod(env, "w"); - _class.Call(env, warning, tag, message); + _class.Call(env, warning, *tag, *message); } else { auto static error = _class.GetStaticMethod(env, "e"); - _class.Call(env, error, tag, message); + _class.Call(env, error, *tag, *message); } - - DeleteLocalRef(env, tag); - DeleteLocalRef(env, message); } } // namespace android diff --git a/platform/android/src/logger.hpp b/platform/android/src/logger.hpp index d4805fccd..7481ecb26 100644 --- a/platform/android/src/logger.hpp +++ b/platform/android/src/logger.hpp @@ -15,9 +15,6 @@ public: static void registerNative(jni::JNIEnv&); static void log(jni::JNIEnv&, EventSeverity severity, const std::string &msg); - -private: - static jni::Class _class; }; } // namespace android diff --git a/platform/android/src/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp index 01ffc6530..5700341d6 100644 --- a/platform/android/src/map/camera_position.cpp +++ b/platform/android/src/map/camera_position.cpp @@ -5,7 +5,8 @@ namespace mbgl { namespace android { jni::Object CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { - static auto constructor = CameraPosition::javaClass.GetConstructor, double, double, double>(env); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor, double, double, double>(env); // wrap LatLng values coming from core auto center = options.center.value(); @@ -24,18 +25,17 @@ jni::Object CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOp // convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60 double tilt_degrees = options.pitch.value_or(0) * util::RAD2DEG; - return CameraPosition::javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees); + return javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees); } mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, jni::Object position) { - static auto bearing = CameraPosition::javaClass.GetField(env, "bearing"); - static auto target = CameraPosition::javaClass.GetField>(env, "target"); - static auto tilt = CameraPosition::javaClass.GetField(env, "tilt"); - static auto zoom = CameraPosition::javaClass.GetField(env, "zoom"); + static auto javaClass = jni::Class::Singleton(env); + static auto bearing = javaClass.GetField(env, "bearing"); + static auto target = javaClass.GetField>(env, "target"); + static auto tilt = javaClass.GetField(env, "tilt"); + static auto zoom = javaClass.GetField(env, "zoom"); - auto jtarget = position.Get(env, target); - auto center = LatLng::getLatLng(env, jtarget); - jni::DeleteLocalRef(env, jtarget); + auto center = LatLng::getLatLng(env, *jni::SeizeLocal(env, position.Get(env, target))); return mbgl::CameraOptions { center, @@ -48,13 +48,9 @@ mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, jni::Obje } void CameraPosition::registerNative(jni::JNIEnv &env) { - // Lookup the class - CameraPosition::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class CameraPosition::javaClass; - - } // namespace android } // namespace mb diff --git a/platform/android/src/map/camera_position.hpp b/platform/android/src/map/camera_position.hpp index 4eee8be75..d57781191 100644 --- a/platform/android/src/map/camera_position.hpp +++ b/platform/android/src/map/camera_position.hpp @@ -10,19 +10,14 @@ namespace android { class CameraPosition : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/camera/CameraPosition"; }; static jni::Object New(jni::JNIEnv&, mbgl::CameraOptions); static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/map/image.cpp b/platform/android/src/map/image.cpp index ce89e22d7..ee3c7012a 100644 --- a/platform/android/src/map/image.cpp +++ b/platform/android/src/map/image.cpp @@ -6,43 +6,36 @@ namespace mbgl { namespace android { mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object image) { - static auto widthField = Image::javaClass.GetField(env, "width"); - static auto heightField = Image::javaClass.GetField(env, "height"); - static auto pixelRatioField = Image::javaClass.GetField(env, "pixelRatio"); - static auto bufferField = Image::javaClass.GetField>(env, "buffer"); - static auto nameField = Image::javaClass.GetField(env, "name"); - static auto sdfField = Image::javaClass.GetField(env, "sdf"); + static auto javaClass = jni::Class::Singleton(env); + static auto widthField = javaClass.GetField(env, "width"); + static auto heightField = javaClass.GetField(env, "height"); + static auto pixelRatioField = javaClass.GetField(env, "pixelRatio"); + static auto bufferField = javaClass.GetField>(env, "buffer"); + static auto nameField = javaClass.GetField(env, "name"); + static auto sdfField = javaClass.GetField(env, "sdf"); auto height = image.Get(env, heightField); auto width = image.Get(env, widthField); auto pixelRatio = image.Get(env, pixelRatioField); - auto pixels = image.Get(env, bufferField); - auto jName = image.Get(env, nameField); - auto name = jni::Make(env, jName); + auto pixels = jni::SeizeLocal(env, image.Get(env, bufferField)); + auto name = jni::Make(env, *jni::SeizeLocal(env, image.Get(env, nameField))); auto sdf = (bool) image.Get(env, sdfField); - jni::DeleteLocalRef(env, jName); - jni::NullCheck(env, &pixels); - std::size_t size = pixels.Length(env); + jni::NullCheck(env, pixels->Get()); + std::size_t size = pixels->Length(env); mbgl::PremultipliedImage premultipliedImage({ static_cast(width), static_cast(height) }); if (premultipliedImage.bytes() != uint32_t(size)) { throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch"); } - jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast(premultipliedImage.data.get())); - jni::DeleteLocalRef(env, pixels); + jni::GetArrayRegion(env, **pixels, 0, size, reinterpret_cast(premultipliedImage.data.get())); return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio, sdf}; } void Image::registerNative(jni::JNIEnv &env) { - // Lookup the class - Image::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Image::javaClass; - - } // namespace android } // namespace mb - diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp index 1513e13ee..17ed4cbef 100644 --- a/platform/android/src/map/image.hpp +++ b/platform/android/src/map/image.hpp @@ -10,17 +10,12 @@ namespace android { class Image : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; }; static mbgl::style::Image getImage(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp index ba6fdc63b..1f8c82ac0 100644 --- a/platform/android/src/map_renderer.cpp +++ b/platform/android/src/map_renderer.cpp @@ -18,7 +18,8 @@ MapRenderer::MapRenderer(jni::JNIEnv& _env, jni::Object obj, jni::Object _fileSource, jni::jfloat pixelRatio_, jni::String programCacheDir_, jni::String localIdeographFontFamily_) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object(jni::NewWeakGlobalRef(_env, obj.Get()).release()))), pixelRatio(pixelRatio_) + : javaPeer(SeizeGenericWeak(obj.NewWeakGlobalRef(_env).release())) + , pixelRatio(pixelRatio_) , fileSource(FileSource::getDefaultFileSource(_env, _fileSource)) , programCacheDir(jni::Make(_env, programCacheDir_)) , localIdeographFontFamily(localIdeographFontFamily_ == nullptr ? optional{} : jni::Make(_env, localIdeographFontFamily_ )) @@ -52,6 +53,7 @@ void MapRenderer::schedule(std::weak_ptr scheduled) { auto peer = runnable->peer(); // Queue the event on the Java Peer + static auto javaClass = jni::Class::Singleton(*_env); static auto queueEvent = javaClass.GetMethod)>(*_env, "queueEvent"); javaPeer->Call(*_env, queueEvent, *peer); @@ -62,6 +64,7 @@ void MapRenderer::schedule(std::weak_ptr scheduled) { void MapRenderer::requestRender() { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto onInvalidate = javaClass.GetMethod(*_env, "requestRender"); javaPeer->Call(*_env, onInvalidate); } @@ -179,16 +182,14 @@ void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) { // Static methods // -jni::Class MapRenderer::javaClass; - void MapRenderer::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRenderer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, MapRenderer::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, jni::Object, jni::jfloat, jni::String, jni::String>, "nativeInitialize", "finalize", METHOD(&MapRenderer::render, "nativeRender"), @@ -199,7 +200,8 @@ void MapRenderer::registerNative(jni::JNIEnv& env) { } MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, jni::Object jObject) { - static auto field = MapRenderer::javaClass.GetField(env, "nativePtr"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "nativePtr"); MapRenderer* mapRenderer = reinterpret_cast(jObject.Get(env, field)); assert(mapRenderer != nullptr); return *mapRenderer; diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp index 97d2db4a9..6fcf2fee7 100644 --- a/platform/android/src/map_renderer.hpp +++ b/platform/android/src/map_renderer.hpp @@ -38,8 +38,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRenderer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static MapRenderer& getNativePeer(JNIEnv&, jni::Object); @@ -99,7 +97,7 @@ private: void onSurfaceChanged(JNIEnv&, jint width, jint height); private: - GenericUniqueWeakObject javaPeer; + GenericWeak> javaPeer; float pixelRatio; DefaultFileSource& fileSource; diff --git a/platform/android/src/map_renderer_runnable.cpp b/platform/android/src/map_renderer_runnable.cpp index 4dc6611c4..1bfccebd2 100644 --- a/platform/android/src/map_renderer_runnable.cpp +++ b/platform/android/src/map_renderer_runnable.cpp @@ -12,6 +12,7 @@ MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr::Singleton(env); static auto constructor = javaClass.GetConstructor(env); auto instance = javaClass.New(env, constructor, reinterpret_cast(this)); javaPeer = instance.NewGlobalRef(env); @@ -23,23 +24,21 @@ void MapRendererRunnable::run(jni::JNIEnv&) { Mailbox::maybeReceive(mailbox); } -jni::UniqueObject MapRendererRunnable::peer() { +jni::Global> MapRendererRunnable::peer() { return std::move(javaPeer); } // Static methods // -jni::Class MapRendererRunnable::javaClass; - void MapRendererRunnable::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRendererRunnable::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) jni::RegisterNativePeer( env, - MapRendererRunnable::javaClass, + javaClass, "nativePtr", std::make_unique, "nativeInitialize", diff --git a/platform/android/src/map_renderer_runnable.hpp b/platform/android/src/map_renderer_runnable.hpp index 46fb028d2..21c4369b6 100644 --- a/platform/android/src/map_renderer_runnable.hpp +++ b/platform/android/src/map_renderer_runnable.hpp @@ -22,8 +22,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRendererRunnable"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); MapRendererRunnable(jni::JNIEnv&, std::weak_ptr); @@ -38,10 +36,10 @@ public: void run(jni::JNIEnv&); // Transfers ownership of the Peer object to the caller - jni::UniqueObject peer(); + jni::Global> peer(); private: - jni::UniqueObject javaPeer; + jni::Global> javaPeer; std::weak_ptr mailbox; }; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 8c76332b3..26814fd6b 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -103,6 +103,7 @@ void NativeMapView::notifyMapChange(mbgl::MapChange change) { assert(vm != nullptr); android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto onMapChanged = javaClass.GetMethod(*_env, "onMapChanged"); javaPeer->Call(*_env, onMapChanged, (int) change); } @@ -376,9 +377,7 @@ void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array::Singleton(*_env); static auto onSnapshotReady = javaClass.GetMethod)>(*_env, "onSnapshotReady"); javaPeer->Call(*_env, onSnapshotReady, bitmap); }); @@ -436,13 +436,11 @@ jni::Array NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array marker = jmarkers.Get(env, i); + auto marker = jni::SeizeLocal(env, jmarkers.Get(env, i)); ids.push_back(map->addAnnotation(mbgl::SymbolAnnotation { - Marker::getPosition(env, marker), - Marker::getIconId(env, marker) + Marker::getPosition(env, *marker), + Marker::getIconId(env, *marker) })); - - jni::DeleteLocalRef(env, marker); } auto result = jni::Array::New(env, len); @@ -505,12 +503,8 @@ jni::Array NativeMapView::addPolylines(JNIEnv& env, jni::ArrayaddAnnotation(annotation)); - - jni::DeleteLocalRef(env, polyline); } auto result = jni::Array::New(env, len); @@ -528,12 +522,8 @@ jni::Array NativeMapView::addPolygons(JNIEnv& env, jni::ArrayaddAnnotation(annotation)); - - jni::DeleteLocalRef(env, polygon); } auto result = jni::Array::New(env, len); @@ -670,7 +660,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo return *convert>, std::vector>( env, - rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); + rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, @@ -690,7 +680,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo return *convert>, std::vector>( env, - rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); + rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } jni::Object NativeMapView::getLight(JNIEnv& env) { @@ -708,12 +698,10 @@ jni::Array> NativeMapView::getLayers(JNIEnv& env) { std::vector layers = map->getStyle().getLayers(); // Convert - jni::Array> jLayers = jni::Array>::New(env, layers.size(), Layer::javaClass); + jni::Array> jLayers = jni::Array>::New(env, layers.size()); int index = 0; for (auto layer : layers) { - auto jLayer = jni::Object(createJavaLayerPeer(env, *map, *layer)); - jLayers.Set(env, index, jLayer); - jni::DeleteLocalRef(env, jLayer); + jLayers.Set(env, index, *jni::SeizeLocal(env, jni::Object(createJavaLayerPeer(env, *map, *layer)))); index++; } @@ -855,7 +843,7 @@ jni::Array> NativeMapView::getSources(JNIEnv& env) { std::vector sources = map->getStyle().getSources(); // Convert - jni::Array> jSources = jni::Array>::New(env, sources.size(), Source::javaClass); + jni::Array> jSources = jni::Array>::New(env, sources.size()); int index = 0; for (auto source : sources) { jSources.Set(env, index, Source::peerForCoreSource(env, *source, *rendererFrontend)); @@ -914,10 +902,8 @@ void NativeMapView::addImages(JNIEnv& env, jni::Array jimage = jimages.Get(env, i); - auto image = mbgl::android::Image::getImage(env, jimage); + auto image = mbgl::android::Image::getImage(env, *jni::SeizeLocal(env, jimages.Get(env, i))); map->getStyle().addImage(std::make_unique(image)); - jni::DeleteLocalRef(env, jimage); } } @@ -948,16 +934,14 @@ mbgl::Map& NativeMapView::getMap() { // Static methods // -jni::Class NativeMapView::javaClass; - void NativeMapView::registerNative(jni::JNIEnv& env) { // Lookup the class - NativeMapView::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, NativeMapView::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, jni::Object, jni::Object, jni::jfloat>, "nativeInitialize", "nativeDestroy", diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index e57767032..d398b39bf 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -45,8 +45,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/NativeMapView"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); NativeMapView(jni::JNIEnv&, @@ -254,7 +252,7 @@ private: std::unique_ptr rendererFrontend; JavaVM *vm = nullptr; - jni::UniqueWeakObject javaPeer; + jni::Weak> javaPeer; MapRenderer& mapRenderer; diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index e96ed7e4d..263f7b9d8 100644 --- a/platform/android/src/offline/offline_manager.cpp +++ b/platform/android/src/offline/offline_manager.cpp @@ -24,8 +24,8 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected regions) mutable { // Reattach, the callback comes from a different thread @@ -58,8 +58,8 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, // Create region fileSource.createOfflineRegion(definition, metadata, [ //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile - callback = std::shared_ptr(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected region) mutable { // Reattach, the callback comes from a different thread @@ -77,13 +77,11 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, }); } -jni::Class OfflineManager::javaClass; - void OfflineManager::registerNative(jni::JNIEnv& env) { - OfflineManager::ListOfflineRegionsCallback::registerNative(env); - OfflineManager::CreateOfflineRegionCallback::registerNative(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -101,37 +99,28 @@ void OfflineManager::registerNative(jni::JNIEnv& env) { void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env, jni::Object jFileSource, jni::Object callback, mbgl::optional> regions) { - //Convert the regions to java peer objects + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod>)>(env, "onList"); + std::size_t index = 0; - auto jregions = jni::Array>::New(env, regions->size(), OfflineRegion::javaClass); + auto jregions = jni::SeizeLocal(env, jni::Array>::New(env, regions->size())); for (auto& region : *regions) { - auto jregion = OfflineRegion::New(env, jFileSource, std::move(region)); - jregions.Set(env, index, jregion); - jni::DeleteLocalRef(env, jregion); + jregions->Set(env, index, *jni::SeizeLocal(env, OfflineRegion::New(env, jFileSource, std::move(region)))); index++; } - // Trigger callback - static auto method = javaClass.GetMethod>)>(env, "onList"); - callback.Call(env, method, jregions); - jni::DeleteLocalRef(env, jregions); -} - -jni::Class OfflineManager::ListOfflineRegionsCallback::javaClass; - -void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + callback.Call(env, method, *jregions); } // OfflineManager::CreateOfflineRegionCallback // @@ -139,30 +128,22 @@ void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env, jni::Object jFileSource, jni::Object callback, mbgl::optional region) { - // Convert the region to java peer object - auto jregion = OfflineRegion::New(env, jFileSource, std::move(*region)); - - // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onCreate"); - callback.Call(env, method, jregion); - jni::DeleteLocalRef(env, jregion); -} -jni::Class OfflineManager::CreateOfflineRegionCallback::javaClass; - -void OfflineManager::CreateOfflineRegionCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + callback.Call(env, method, + *jni::SeizeLocal(env, OfflineRegion::New(env, jFileSource, std::move(*region)))); } } // namespace android diff --git a/platform/android/src/offline/offline_manager.hpp b/platform/android/src/offline/offline_manager.hpp index 9ae2714ca..43f5045c7 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -26,10 +26,6 @@ public: jni::Object, jni::Object, mbgl::optional>); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class CreateOfflineRegionCallback { @@ -42,16 +38,10 @@ public: jni::Object, jni::Object, mbgl::optional); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); OfflineManager(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 5ed37eda7..949377e22 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -25,9 +25,9 @@ void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object&& callback_) + Observer(jni::Global>&& callback_) //TODO add a generic deleter for jni::Object - : callback(callback_.release()->Get()) { + : callback(callback_.release().Get()) { } ~Observer() override { @@ -39,41 +39,31 @@ void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object::Singleton(*env); + static auto method = javaClass.GetMethod)>(*env, "onStatusChanged"); - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod)>(*env, "onStatusChanged"); - callback.Call(*env, method, jStatus); - - // Delete references - jni::DeleteLocalRef(*env, jStatus); + callback.Call(*env, method, + *jni::SeizeLocal(*env, OfflineRegionStatus::New(*env, status))); } void responseError(mbgl::Response::Error error) override { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); - // Error object - auto jError = OfflineRegionError::New(*env, error); + static auto javaClass = jni::Class::Singleton(*env); + static auto method = javaClass.GetMethod)>(*env, "onError"); - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod)>(*env, "onError"); - callback.Call(*env, method, jError); - - // Delete references - jni::DeleteLocalRef(*env, jError); + callback.Call(*env, method, + *jni::SeizeLocal(*env, OfflineRegionError::New(*env, error))); } void mapboxTileCountLimitExceeded(uint64_t limit) override { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); - // Send limit - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod(*env, "mapboxTileCountLimitExceeded"); + static auto javaClass = jni::Class::Singleton(*env); + static auto method = javaClass.GetMethod(*env, "mapboxTileCountLimitExceeded"); + callback.Call(*env, method, jlong(limit)); } @@ -106,7 +96,7 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected status) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); @@ -123,7 +113,7 @@ void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, jni::Object(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](std::exception_ptr error) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); @@ -143,7 +133,7 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::ArraygetID(), metadata, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected data) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); @@ -159,29 +149,25 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array OfflineRegion::New(jni::JNIEnv& env, jni::Object jFileSource, mbgl::OfflineRegion region) { // Definition - auto definition = region.getDefinition().match( + auto definition = jni::SeizeLocal(env, region.getDefinition().match( [&](const mbgl::OfflineTilePyramidRegionDefinition def) { return jni::Object( *OfflineTilePyramidRegionDefinition::New(env, def)); }, [&](const mbgl::OfflineGeometryRegionDefinition def) { return jni::Object( *OfflineGeometryRegionDefinition::New(env, def)); - }); - - // Metadata - auto metadata = OfflineRegion::metadata(env, region.getMetadata()); + })); // Create region java object - static auto constructor = OfflineRegion::javaClass.GetConstructor, jni::jlong, jni::Object, jni::Array>(env); - auto jregion = OfflineRegion::javaClass.New(env, constructor, + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor, jni::jlong, jni::Object, jni::Array>(env); + + return javaClass.New(env, constructor, reinterpret_cast(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap - jFileSource, jni::jlong(region.getID()), definition, metadata); - - //Delete references - jni::DeleteLocalRef(env, definition); - jni::DeleteLocalRef(env, metadata); - - return jregion; + jFileSource, + jni::jlong(region.getID()), + *definition, + *jni::SeizeLocal(env, OfflineRegion::metadata(env, region.getMetadata()))); } jni::Array OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { @@ -201,15 +187,13 @@ mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array return metadata; } -jni::Class OfflineRegion::javaClass; - void OfflineRegion::registerNative(jni::JNIEnv& env) { - OfflineRegion::OfflineRegionObserver::registerNative(env); - OfflineRegion::OfflineRegionStatusCallback::registerNative(env); - OfflineRegion::OfflineRegionDeleteCallback::registerNative(env); - OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -227,94 +211,68 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { // OfflineRegionObserver // -jni::Class OfflineRegion::OfflineRegionObserver::javaClass; - -void OfflineRegion::OfflineRegionObserver::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - // OfflineRegionStatusCallback // -jni::Class OfflineRegion::OfflineRegionStatusCallback::javaClass; - -void OfflineRegion::OfflineRegionStatusCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, jni::Object callback, mbgl::optional status) { - //Convert to java peer object - auto jStatus = OfflineRegionStatus::New(env, std::move(*status)); - - // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onStatus"); - callback.Call(env, method, jStatus); - jni::DeleteLocalRef(env, jStatus); + + callback.Call(env, method, + *jni::SeizeLocal(env, OfflineRegionStatus::New(env, std::move(*status)))); } // OfflineRegionDeleteCallback // -jni::Class OfflineRegion::OfflineRegionDeleteCallback::javaClass; - -void OfflineRegion::OfflineRegionDeleteCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object callback) { // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onDelete"); + callback.Call(env, method); } // OfflineRegionUpdateMetadataCallback // -jni::Class OfflineRegion::OfflineRegionUpdateMetadataCallback::javaClass; - -void OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, jni::Object callback, mbgl::optional metadata) { - //Convert to java peer object - auto jMetadata = OfflineRegion::metadata(env, std::move(*metadata)); - - // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onUpdate"); - callback.Call(env, method, jMetadata); - jni::DeleteLocalRef(env, jMetadata); + + callback.Call(env, method, + *jni::SeizeLocal(env, OfflineRegion::metadata(env, std::move(*metadata)))); } } // namespace android diff --git a/platform/android/src/offline/offline_region.hpp b/platform/android/src/offline/offline_region.hpp index c05383a91..11aecb82a 100644 --- a/platform/android/src/offline/offline_region.hpp +++ b/platform/android/src/offline/offline_region.hpp @@ -15,10 +15,6 @@ public: class OfflineRegionObserver { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver"; }; - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionStatusCallback { @@ -30,10 +26,6 @@ public: static void onStatus(jni::JNIEnv&, jni::Object, mbgl::optional); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionDeleteCallback { @@ -43,10 +35,6 @@ public: static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); static void onDelete(jni::JNIEnv&, jni::Object); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionUpdateMetadataCallback { @@ -58,10 +46,6 @@ public: static void onUpdate(jni::JNIEnv&, jni::Object, mbgl::optional); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; }; @@ -86,8 +70,6 @@ public: static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, jni::Array); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); private: diff --git a/platform/android/src/offline/offline_region_definition.cpp b/platform/android/src/offline/offline_region_definition.cpp index a85667290..2a69181f5 100644 --- a/platform/android/src/offline/offline_region_definition.cpp +++ b/platform/android/src/offline/offline_region_definition.cpp @@ -10,18 +10,15 @@ namespace android { // OfflineRegionDefinition // -jni::Class OfflineRegionDefinition::javaClass; - void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env, jni::Object jDefinition) { - - if (jDefinition.IsInstanceOf(env, OfflineTilePyramidRegionDefinition::javaClass)) { + if (jDefinition.IsInstanceOf(env, jni::Class::Singleton(env))) { return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Object(*jDefinition)); - } else if (jDefinition.IsInstanceOf(env, OfflineGeometryRegionDefinition::javaClass)) { + } else if (jDefinition.IsInstanceOf(env, jni::Class::Singleton(env))) { return OfflineGeometryRegionDefinition::getDefinition(env, jni::Object(*jDefinition)); } @@ -31,104 +28,73 @@ mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env // OfflineTilePyramidRegionDefinition // jni::Object OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { - - //Convert objects - auto styleURL = jni::Make(env, definition.styleURL); - auto bounds = LatLngBounds::New(env, definition.bounds); - + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::jdouble, jni::jdouble, jni::jfloat>(env); - auto jdefinition = javaClass.New(env, constructor, styleURL, bounds, definition.minZoom, definition.maxZoom, definition.pixelRatio); - //Delete References - jni::DeleteLocalRef(env, styleURL); - jni::DeleteLocalRef(env, bounds); - - return jdefinition; + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Make(env, definition.styleURL)), + *jni::SeizeLocal(env, LatLngBounds::New(env, definition.bounds)), + definition.minZoom, + definition.maxZoom, + definition.pixelRatio); } mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object jDefinition) { // Field references + static auto javaClass = jni::Class::Singleton(env); static auto styleURLF = javaClass.GetField(env, "styleURL"); static auto boundsF = javaClass.GetField>(env, "bounds"); static auto minZoomF = javaClass.GetField(env, "minZoom"); static auto maxZoomF = javaClass.GetField(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jBounds = jDefinition.Get(env, boundsF); - - // Create definition - mbgl::OfflineTilePyramidRegionDefinition definition( - jni::Make(env, jStyleURL), - LatLngBounds::getLatLngBounds(env, jBounds), + return mbgl::OfflineTilePyramidRegionDefinition( + jni::Make(env, *jni::SeizeLocal(env, jDefinition.Get(env, styleURLF))), + LatLngBounds::getLatLngBounds(env, *jni::SeizeLocal(env, jDefinition.Get(env, boundsF))), jDefinition.Get(env, minZoomF), jDefinition.Get(env, maxZoomF), jDefinition.Get(env, pixelRatioF) ); - - // Delete references - jni::DeleteLocalRef(env, jStyleURL); - jni::DeleteLocalRef(env, jBounds); - - return definition; } -jni::Class OfflineTilePyramidRegionDefinition::javaClass; - void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } // OfflineGeometryRegionDefinition // jni::Object OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { - //Convert objects - auto styleURL = jni::Make(env, definition.styleURL); - auto geometry = geojson::Geometry::New(env, definition.geometry); - + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::jdouble, jni::jdouble, jni::jfloat>(env); - auto jdefinition = javaClass.New(env, constructor, styleURL, geometry, definition.minZoom, definition.maxZoom, definition.pixelRatio); - //Delete References - jni::DeleteLocalRef(env, styleURL); - jni::DeleteLocalRef(env, geometry); - - return jdefinition; + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Make(env, definition.styleURL)), + *jni::SeizeLocal(env, geojson::Geometry::New(env, definition.geometry)), + definition.minZoom, + definition.maxZoom, + definition.pixelRatio); } mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object jDefinition) { // Field references + static auto javaClass = jni::Class::Singleton(env); static auto styleURLF = javaClass.GetField(env, "styleURL"); static auto geometryF = javaClass.GetField>(env, "geometry"); static auto minZoomF = javaClass.GetField(env, "minZoom"); static auto maxZoomF = javaClass.GetField(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jGeometry = jDefinition.Get(env, geometryF); - - // Create definition - mbgl::OfflineGeometryRegionDefinition definition( - jni::Make(env, jStyleURL), - geojson::Geometry::convert(env, jGeometry), - jDefinition.Get(env, minZoomF), - jDefinition.Get(env, maxZoomF), - jDefinition.Get(env, pixelRatioF) + return mbgl::OfflineGeometryRegionDefinition( + jni::Make(env, *jni::SeizeLocal(env, jDefinition.Get(env, styleURLF))), + geojson::Geometry::convert(env, *jni::SeizeLocal(env, jDefinition.Get(env, geometryF))), + jDefinition.Get(env, minZoomF), + jDefinition.Get(env, maxZoomF), + jDefinition.Get(env, pixelRatioF) ); - - // Delete references - jni::DeleteLocalRef(env, jStyleURL); - jni::DeleteLocalRef(env, jGeometry); - - return definition; } -jni::Class OfflineGeometryRegionDefinition::javaClass; - void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } } // namespace android diff --git a/platform/android/src/offline/offline_region_definition.hpp b/platform/android/src/offline/offline_region_definition.hpp index a9dfb5463..853cc833b 100644 --- a/platform/android/src/offline/offline_region_definition.hpp +++ b/platform/android/src/offline/offline_region_definition.hpp @@ -10,8 +10,6 @@ class OfflineRegionDefinition { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionDefinition"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, jni::Object jDefinition); @@ -25,10 +23,7 @@ public: static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; class OfflineGeometryRegionDefinition: public OfflineRegionDefinition { @@ -39,10 +34,7 @@ public: static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; } // namespace android diff --git a/platform/android/src/offline/offline_region_error.cpp b/platform/android/src/offline/offline_region_error.cpp index b0a19f934..02432757d 100644 --- a/platform/android/src/offline/offline_region_error.cpp +++ b/platform/android/src/offline/offline_region_error.cpp @@ -28,25 +28,16 @@ jni::Object OfflineRegionError::New(jni::JNIEnv& env, mbgl:: break; } - // Convert - auto jReason = jni::Make(env, reason); - auto jMessage = jni::Make(env, error.message); - - // Create java object + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - auto jError = javaClass.New(env, constructor, jReason, jMessage); - // Delete references - jni::DeleteLocalRef(env, jReason); - jni::DeleteLocalRef(env, jMessage); - - return jError; + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Make(env, reason)), + *jni::SeizeLocal(env, jni::Make(env, error.message))); } -jni::Class OfflineRegionError::javaClass; - void OfflineRegionError::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } } // namespace android diff --git a/platform/android/src/offline/offline_region_error.hpp b/platform/android/src/offline/offline_region_error.hpp index 61efaca67..c51f08a74 100644 --- a/platform/android/src/offline/offline_region_error.hpp +++ b/platform/android/src/offline/offline_region_error.hpp @@ -12,8 +12,6 @@ public: static jni::Object New(jni::JNIEnv&, mbgl::Response::Error); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/offline/offline_region_status.cpp b/platform/android/src/offline/offline_region_status.cpp index d0bbae124..0a415bdb5 100644 --- a/platform/android/src/offline/offline_region_status.cpp +++ b/platform/android/src/offline/offline_region_status.cpp @@ -17,6 +17,7 @@ jni::Object OfflineRegionStatus::New(jni::JNIEnv& env, mbgl } // Create java object + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, downloadState, @@ -29,10 +30,8 @@ jni::Object OfflineRegionStatus::New(jni::JNIEnv& env, mbgl ); } -jni::Class OfflineRegionStatus::javaClass; - void OfflineRegionStatus::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } } // namespace android diff --git a/platform/android/src/offline/offline_region_status.hpp b/platform/android/src/offline/offline_region_status.hpp index b29a65365..9f638e109 100644 --- a/platform/android/src/offline/offline_region_status.hpp +++ b/platform/android/src/offline/offline_region_status.hpp @@ -12,8 +12,6 @@ public: static jni::Object New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/snapshotter/map_snapshot.cpp b/platform/android/src/snapshotter/map_snapshot.cpp index 379ac89d5..d626ae68b 100644 --- a/platform/android/src/snapshotter/map_snapshot.cpp +++ b/platform/android/src/snapshotter/map_snapshot.cpp @@ -38,21 +38,20 @@ jni::Object MapSnapshot::New(JNIEnv& env, auto bitmap = Bitmap::CreateBitmap(env, std::move(image)); // Create the Mapsnapshot peers + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::Array, jni::jboolean>(env); auto nativePeer = std::make_unique(pixelRatio, pointForFn, latLngForFn); return javaClass.New(env, constructor, reinterpret_cast(nativePeer.release()), bitmap, conversion::toArray(env, attributions), (jni::jboolean) showLogo); } -jni::Class MapSnapshot::javaClass; - void MapSnapshot::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshot::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, MapSnapshot::javaClass, + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, "initialize", diff --git a/platform/android/src/snapshotter/map_snapshot.hpp b/platform/android/src/snapshotter/map_snapshot.hpp index f168be85b..3cd293b62 100644 --- a/platform/android/src/snapshotter/map_snapshot.hpp +++ b/platform/android/src/snapshotter/map_snapshot.hpp @@ -39,8 +39,6 @@ public: jni::Object latLngForPixel(jni::JNIEnv&, jni::Object); private: - static jni::Class javaClass; - float pixelRatio; mbgl::MapSnapshotter::PointForFn pointForFn; mbgl::MapSnapshotter::LatLngForFn latLngForFn; diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp index a93404dbf..4df0749aa 100644 --- a/platform/android/src/snapshotter/map_snapshotter.cpp +++ b/platform/android/src/snapshotter/map_snapshotter.cpp @@ -25,7 +25,7 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, jni::Object position, jni::jboolean _showLogo, jni::String _programCacheDir) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object(jni::NewWeakGlobalRef(_env, _obj.Get()).release()))) + : javaPeer(SeizeGenericWeak(_obj.NewWeakGlobalRef(_env).release())) , pixelRatio(_pixelRatio) , threadPool(sharedThreadPool()) { @@ -80,13 +80,13 @@ void MapSnapshotter::start(JNIEnv& env) { [this](std::exception_ptr err, PremultipliedImage image, std::vector attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { MBGL_VERIFY_THREAD(tid); android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); if (err) { // error handler callback static auto onSnapshotFailed = javaClass.GetMethod(*_env, "onSnapshotFailed"); - auto message = jni::Make(*_env, util::toString(err)); - javaPeer->Call(*_env, onSnapshotFailed, message); - jni::DeleteLocalRef(*_env, message); + javaPeer->Call(*_env, onSnapshotFailed, + *jni::SeizeLocal(*_env, jni::Make(*_env, util::toString(err)))); } else { // Create the wrapper auto mapSnapshot = android::MapSnapshot::New(*_env, std::move(image), pixelRatio, attributions, showLogo, pointForFn, latLngForFn); @@ -149,16 +149,14 @@ void MapSnapshotter::deactivateFilesource(JNIEnv& env) { // Static methods // -jni::Class MapSnapshotter::javaClass; - void MapSnapshotter::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshotter::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, MapSnapshotter::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, jni::Object, jni::jfloat, jni::jint, jni::jint, jni::String, jni::String, jni::Object, jni::Object, jni::jboolean, jni::String>, "nativeInitialize", "finalize", diff --git a/platform/android/src/snapshotter/map_snapshotter.hpp b/platform/android/src/snapshotter/map_snapshotter.hpp index 7b72452c4..05a27256a 100644 --- a/platform/android/src/snapshotter/map_snapshotter.hpp +++ b/platform/android/src/snapshotter/map_snapshotter.hpp @@ -23,8 +23,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/snapshotter/MapSnapshotter"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); MapSnapshotter(jni::JNIEnv&, @@ -60,7 +58,7 @@ private: MBGL_STORE_THREAD(tid); JavaVM *vm = nullptr; - GenericUniqueWeakObject javaPeer; + GenericWeak> javaPeer; float pixelRatio; bool showLogo; diff --git a/platform/android/src/style/conversion/filter.cpp b/platform/android/src/style/conversion/filter.cpp index 4eac0cf82..44b5a71aa 100644 --- a/platform/android/src/style/conversion/filter.cpp +++ b/platform/android/src/style/conversion/filter.cpp @@ -8,11 +8,11 @@ namespace mbgl { namespace android { namespace conversion { -optional toFilter(jni::JNIEnv& env, jni::Array> jfilter) { +optional toFilter(jni::JNIEnv& env, jni::Local>> jfilter) { mbgl::optional filter; if (jfilter) { mbgl::style::conversion::Error error; - auto converted = mbgl::style::conversion::convert(Value(env, jfilter), error); + auto converted = mbgl::style::conversion::convert(Value(env, std::move(jfilter)), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error converting filter: " + error.message); } @@ -23,4 +23,4 @@ optional toFilter(jni::JNIEnv& env, jni::Array toFilter(jni::JNIEnv&, jni::Array>); +optional toFilter(jni::JNIEnv&, jni::Local>>); } // namespace conversion } // namespace android diff --git a/platform/android/src/style/layers/background_layer.cpp b/platform/android/src/style/layers/background_layer.cpp index a8f013b23..00c348b23 100644 --- a/platform/android/src/style/layers/background_layer.cpp +++ b/platform/android/src/style/layers/background_layer.cpp @@ -93,22 +93,21 @@ namespace android { } - jni::Class BackgroundLayer::javaClass; - jni::jobject* BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = BackgroundLayer::javaClass.template GetConstructor(env); - return BackgroundLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void BackgroundLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - BackgroundLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, BackgroundLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp index 95555a2d7..3b7f03ddb 100644 --- a/platform/android/src/style/layers/background_layer.hpp +++ b/platform/android/src/style/layers/background_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/BackgroundLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); BackgroundLayer(jni::JNIEnv&, jni::String); diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp index 4c7f69e95..47a492dd4 100644 --- a/platform/android/src/style/layers/circle_layer.cpp +++ b/platform/android/src/style/layers/circle_layer.cpp @@ -206,22 +206,21 @@ namespace android { } - jni::Class CircleLayer::javaClass; - jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CircleLayer::javaClass.template GetConstructor(env); - return CircleLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void CircleLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CircleLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, CircleLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp index 9d323e92b..03063b1fc 100644 --- a/platform/android/src/style/layers/circle_layer.hpp +++ b/platform/android/src/style/layers/circle_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CircleLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); CircleLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp index 61e74a9cf..c0dcc24f0 100644 --- a/platform/android/src/style/layers/custom_layer.cpp +++ b/platform/android/src/style/layers/custom_layer.cpp @@ -33,22 +33,21 @@ namespace android { } } - jni::Class CustomLayer::javaClass; - jni::jobject* CustomLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomLayer::javaClass.template GetConstructor(env); - return CustomLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void CustomLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, CustomLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/custom_layer.hpp b/platform/android/src/style/layers/custom_layer.hpp index 7eb649d92..75e195771 100644 --- a/platform/android/src/style/layers/custom_layer.hpp +++ b/platform/android/src/style/layers/custom_layer.hpp @@ -9,19 +9,13 @@ namespace android { class CustomLayer : public Layer { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CustomLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); CustomLayer(jni::JNIEnv&, jni::String, jni::jlong); - CustomLayer(mbgl::Map&, mbgl::style::CustomLayer&); - CustomLayer(mbgl::Map&, std::unique_ptr); - ~CustomLayer(); void update(jni::JNIEnv&); diff --git a/platform/android/src/style/layers/fill_extrusion_layer.cpp b/platform/android/src/style/layers/fill_extrusion_layer.cpp index 492e1729b..6c6a0bef5 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.cpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.cpp @@ -156,22 +156,21 @@ namespace android { } - jni::Class FillExtrusionLayer::javaClass; - jni::jobject* FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillExtrusionLayer::javaClass.template GetConstructor(env); - return FillExtrusionLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void FillExtrusionLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillExtrusionLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, FillExtrusionLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/fill_extrusion_layer.hpp b/platform/android/src/style/layers/fill_extrusion_layer.hpp index 11a74bc8e..233c3cc33 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.hpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); FillExtrusionLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/fill_layer.cpp b/platform/android/src/style/layers/fill_layer.cpp index f4cddc885..5182c546c 100644 --- a/platform/android/src/style/layers/fill_layer.cpp +++ b/platform/android/src/style/layers/fill_layer.cpp @@ -143,22 +143,21 @@ namespace android { } - jni::Class FillLayer::javaClass; - jni::jobject* FillLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillLayer::javaClass.template GetConstructor(env); - return FillLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void FillLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, FillLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp index a773cf785..db1fee166 100644 --- a/platform/android/src/style/layers/fill_layer.hpp +++ b/platform/android/src/style/layers/fill_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); FillLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/heatmap_layer.cpp b/platform/android/src/style/layers/heatmap_layer.cpp index b3d90faab..e83d92873 100644 --- a/platform/android/src/style/layers/heatmap_layer.cpp +++ b/platform/android/src/style/layers/heatmap_layer.cpp @@ -109,22 +109,21 @@ namespace android { } - jni::Class HeatmapLayer::javaClass; - jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HeatmapLayer::javaClass.template GetConstructor(env); - return HeatmapLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void HeatmapLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HeatmapLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, HeatmapLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp index 9e8908b06..00ab27d85 100644 --- a/platform/android/src/style/layers/heatmap_layer.hpp +++ b/platform/android/src/style/layers/heatmap_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); HeatmapLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/hillshade_layer.cpp b/platform/android/src/style/layers/hillshade_layer.cpp index d98e3ee07..b6409b3b3 100644 --- a/platform/android/src/style/layers/hillshade_layer.cpp +++ b/platform/android/src/style/layers/hillshade_layer.cpp @@ -124,22 +124,21 @@ namespace android { } - jni::Class HillshadeLayer::javaClass; - jni::jobject* HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HillshadeLayer::javaClass.template GetConstructor(env); - return HillshadeLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void HillshadeLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HillshadeLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, HillshadeLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/hillshade_layer.hpp b/platform/android/src/style/layers/hillshade_layer.hpp index 4b6825177..f82469805 100644 --- a/platform/android/src/style/layers/hillshade_layer.hpp +++ b/platform/android/src/style/layers/hillshade_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HillshadeLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); HillshadeLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp index 48e09674e..fe4fb9aeb 100644 --- a/platform/android/src/style/layers/layer.cpp +++ b/platform/android/src/style/layers/layer.cpp @@ -93,7 +93,7 @@ namespace android { void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { // Convert and set property - optional error = layer.setLayoutProperty(jni::Make(env, jname), Value(env, jvalue)); + optional error = layer.setLayoutProperty(jni::Make(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; @@ -102,7 +102,7 @@ namespace android { void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { // Convert and set property - optional error = layer.setPaintProperty(jni::Make(env, jname), Value(env, jvalue)); + optional error = layer.setPaintProperty(jni::Make(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; @@ -128,7 +128,7 @@ namespace android { using namespace mbgl::style::conversion; Error error; - optional converted = convert(Value(env, jfilter), error); + optional converted = convert(Value(env, jni::SeizeLocal(env, std::move(jfilter))), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + error.message); return; @@ -246,16 +246,14 @@ namespace android { return jni::Object(*convert(env, layer.getVisibility())); } - jni::Class Layer::javaClass; - void Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - Layer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Layer::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", METHOD(&Layer::getId, "nativeGetId"), METHOD(&Layer::setLayoutProperty, "nativeSetLayoutProperty"), METHOD(&Layer::setPaintProperty, "nativeSetPaintProperty"), diff --git a/platform/android/src/style/layers/layer.cpp.ejs b/platform/android/src/style/layers/layer.cpp.ejs index b08f0ec4d..7dbb031b2 100644 --- a/platform/android/src/style/layers/layer.cpp.ejs +++ b/platform/android/src/style/layers/layer.cpp.ejs @@ -84,22 +84,21 @@ namespace android { <% } -%> <% } -%> - jni::Class<<%- camelize(type) %>Layer> <%- camelize(type) %>Layer::javaClass; - jni::jobject* <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = <%- camelize(type) %>Layer::javaClass.template GetConstructor(env); - return <%- camelize(type) %>Layer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void <%- camelize(type) %>Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - <%- camelize(type) %>Layer::javaClass = *jni::Class<<%- camelize(type) %>Layer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer<<%- camelize(type) %>Layer>( - env, <%- camelize(type) %>Layer::javaClass, "nativePtr", + env, javaClass, "nativePtr", <% if (type === 'background') { -%> std::make_unique<<%- camelize(type) %>Layer, JNIEnv&, jni::String>, <% } else { -%> diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp index 41022bf74..8112dd18d 100644 --- a/platform/android/src/style/layers/layer.hpp +++ b/platform/android/src/style/layers/layer.hpp @@ -17,8 +17,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/Layer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); /* diff --git a/platform/android/src/style/layers/layer.hpp.ejs b/platform/android/src/style/layers/layer.hpp.ejs index 837049b4c..dd599d71d 100644 --- a/platform/android/src/style/layers/layer.hpp.ejs +++ b/platform/android/src/style/layers/layer.hpp.ejs @@ -19,8 +19,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/<%- camelize(type) %>Layer"; }; - static jni::Class<<%- camelize(type) %>Layer> javaClass; - static void registerNative(jni::JNIEnv&); <% if (type === 'background') { -%> diff --git a/platform/android/src/style/layers/line_layer.cpp b/platform/android/src/style/layers/line_layer.cpp index f143ecc23..2656bd9c0 100644 --- a/platform/android/src/style/layers/line_layer.cpp +++ b/platform/android/src/style/layers/line_layer.cpp @@ -243,22 +243,21 @@ namespace android { } - jni::Class LineLayer::javaClass; - jni::jobject* LineLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = LineLayer::javaClass.template GetConstructor(env); - return LineLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void LineLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - LineLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, LineLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp index 9eef1349c..4d1e759c1 100644 --- a/platform/android/src/style/layers/line_layer.hpp +++ b/platform/android/src/style/layers/line_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/LineLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); LineLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/raster_layer.cpp b/platform/android/src/style/layers/raster_layer.cpp index 53086951e..c52891b66 100644 --- a/platform/android/src/style/layers/raster_layer.cpp +++ b/platform/android/src/style/layers/raster_layer.cpp @@ -162,22 +162,21 @@ namespace android { } - jni::Class RasterLayer::javaClass; - jni::jobject* RasterLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterLayer::javaClass.template GetConstructor(env); - return RasterLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void RasterLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, RasterLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp index d1c1b4523..4e268c36e 100644 --- a/platform/android/src/style/layers/raster_layer.hpp +++ b/platform/android/src/style/layers/raster_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/RasterLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); RasterLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp index d44744a6c..953c73e22 100644 --- a/platform/android/src/style/layers/symbol_layer.cpp +++ b/platform/android/src/style/layers/symbol_layer.cpp @@ -492,22 +492,21 @@ namespace android { } - jni::Class SymbolLayer::javaClass; - jni::jobject* SymbolLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = SymbolLayer::javaClass.template GetConstructor(env); - return SymbolLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void SymbolLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - SymbolLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, SymbolLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp index 417e5e143..3835e01bf 100644 --- a/platform/android/src/style/layers/symbol_layer.hpp +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/SymbolLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); SymbolLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/unknown_layer.cpp b/platform/android/src/style/layers/unknown_layer.cpp index 8ffda82bf..9f877e489 100644 --- a/platform/android/src/style/layers/unknown_layer.cpp +++ b/platform/android/src/style/layers/unknown_layer.cpp @@ -22,16 +22,15 @@ namespace android { : Layer(map, std::move(coreLayer)) { } - jni::Class UnknownLayer::javaClass; - jni::jobject* UnknownLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownLayer::javaClass.template GetConstructor(env); - return UnknownLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void UnknownLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -39,7 +38,7 @@ namespace android { // Register the peer jni::RegisterNativePeer( - env, UnknownLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", init, "initialize", "finalize"); diff --git a/platform/android/src/style/layers/unknown_layer.hpp b/platform/android/src/style/layers/unknown_layer.hpp index 67992ea00..0610c843f 100644 --- a/platform/android/src/style/layers/unknown_layer.hpp +++ b/platform/android/src/style/layers/unknown_layer.hpp @@ -12,8 +12,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/UnknownLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); UnknownLayer(mbgl::Map&, mbgl::style::Layer&); diff --git a/platform/android/src/style/light.cpp b/platform/android/src/style/light.cpp index 71f1cb076..64afb8920 100644 --- a/platform/android/src/style/light.cpp +++ b/platform/android/src/style/light.cpp @@ -23,11 +23,10 @@ jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style return result; } -jni::Class Light::javaClass; - jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor(env); - return Light::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void Light::setAnchor(jni::JNIEnv& env, jni::String property) { @@ -121,11 +120,11 @@ void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { void Light::registerNative(jni::JNIEnv& env) { // Lookup the class - Light::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Light::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", METHOD(&Light::getAnchor, "nativeGetAnchor"), METHOD(&Light::setAnchor, "nativeSetAnchor"), METHOD(&Light::getPositionTransition, "nativeGetPositionTransition"), diff --git a/platform/android/src/style/light.cpp.ejs b/platform/android/src/style/light.cpp.ejs index 17f0bba09..f18dc57a4 100644 --- a/platform/android/src/style/light.cpp.ejs +++ b/platform/android/src/style/light.cpp.ejs @@ -26,11 +26,10 @@ jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style return result; } -jni::Class Light::javaClass; - jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor(env); - return Light::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } <% for (const property of properties) { -%> @@ -106,11 +105,11 @@ void Light::set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong dura <% } -%> void Light::registerNative(jni::JNIEnv& env) { // Lookup the class - Light::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Light::javaClass, "nativePtr",<% for(var i = 0; i < properties.length; i++) {%> + jni::RegisterNativePeer(env, javaClass, "nativePtr",<% for(var i = 0; i < properties.length; i++) {%> <% if (properties[i].transition) { -%> METHOD(&Light::get<%- camelize(properties[i].name) %>Transition, "nativeGet<%- camelize(properties[i].name) %>Transition"), METHOD(&Light::set<%- camelize(properties[i].name) %>Transition, "nativeSet<%- camelize(properties[i].name) %>Transition"), diff --git a/platform/android/src/style/position.cpp b/platform/android/src/style/position.cpp index 0bbcefcbc..c6918a2e9 100644 --- a/platform/android/src/style/position.cpp +++ b/platform/android/src/style/position.cpp @@ -4,29 +4,30 @@ namespace mbgl { namespace android { jni::Object Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { - static auto method = Position::javaClass.GetStaticMethod (jfloat, jfloat, jfloat)>(env, "fromPosition"); - return Position::javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jfloat, jfloat, jfloat)>(env, "fromPosition"); + return javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); } void Position::registerNative(jni::JNIEnv& env) { - // Lookup the class - Position::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Position::javaClass; - float Position::getRadialCoordinate(jni::JNIEnv& env, jni::Object position){ - static auto field = Position::javaClass.GetField(env, "radialCoordinate"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "radialCoordinate"); return position.Get(env, field); } float Position::getAzimuthalAngle(jni::JNIEnv& env, jni::Object position){ - static auto field = Position::javaClass.GetField(env, "azimuthalAngle"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "azimuthalAngle"); return position.Get(env, field); } float Position::getPolarAngle(jni::JNIEnv& env, jni::Object position){ - static auto field = Position::javaClass.GetField(env, "polarAngle"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "polarAngle"); return position.Get(env, field); } diff --git a/platform/android/src/style/position.hpp b/platform/android/src/style/position.hpp index 4aafa853d..4f3738da9 100644 --- a/platform/android/src/style/position.hpp +++ b/platform/android/src/style/position.hpp @@ -9,21 +9,16 @@ namespace android { class Position : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Position"; }; static jni::Object fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static float getRadialCoordinate(jni::JNIEnv&, jni::Object); static float getAzimuthalAngle(jni::JNIEnv&, jni::Object); static float getPolarAngle(jni::JNIEnv&, jni::Object); - }; - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp index e9a530f75..029824eae 100644 --- a/platform/android/src/style/sources/custom_geometry_source.cpp +++ b/platform/android/src/style/sources/custom_geometry_source.cpp @@ -21,7 +21,7 @@ namespace android { // the value was originally a CustomGeometrySourceOptions object on the Java side. If it fails // to convert, it's a bug in our serialization or Java-side static typing. static style::CustomGeometrySource::Options convertCustomGeometrySourceOptions(jni::JNIEnv& env, - jni::Object<> options, + jni::Local> options, style::TileFunction fetchFn, style::TileFunction cancelFn) { using namespace mbgl::style::conversion; @@ -29,7 +29,7 @@ namespace android { return style::CustomGeometrySource::Options(); } Error error; - optional result = convert(Value(env, options), error); + optional result = convert(Value(env, std::move(options)), error); if (!result) { throw std::logic_error(error.message); } @@ -43,7 +43,7 @@ namespace android { jni::Object<> options) : Source(env, std::make_unique( jni::Make(env, sourceId), - convertCustomGeometrySourceOptions(env, options, + convertCustomGeometrySourceOptions(env, jni::SeizeLocal(env, std::move(options)), std::bind(&CustomGeometrySource::fetchTile, this, std::placeholders::_1), std::bind(&CustomGeometrySource::cancelTile, this, std::placeholders::_1)))) { } @@ -61,44 +61,48 @@ namespace android { void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto fetchTile = javaClass.GetMethod(*_env, "fetchTile"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, *javaPeer); peer.Call(*_env, fetchTile, (int)tileID.z, (int)tileID.x, (int)tileID.y); }; void CustomGeometrySource::cancelTile(const mbgl::CanonicalTileID& tileID) { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto cancelTile = javaClass.GetMethod(*_env, "cancelTile"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, *javaPeer); peer.Call(*_env, cancelTile, (int)tileID.z, (int)tileID.x, (int)tileID.y); }; void CustomGeometrySource::startThreads() { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto startThreads = javaClass.GetMethod(*_env, "startThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, *javaPeer); peer.Call(*_env, startThreads); } void CustomGeometrySource::releaseThreads() { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto releaseThreads = javaClass.GetMethod(*_env, "releaseThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, *javaPeer); peer.Call(*_env, releaseThreads); }; @@ -107,11 +111,12 @@ namespace android { jni::jint y) { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto isCancelled = javaClass.GetMethod(*_env, "isCancelled"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, *javaPeer); return peer.Call(*_env, isCancelled, z, x, y); }; @@ -147,16 +152,16 @@ namespace android { std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } return *convert>, std::vector>(env, features); } - jni::Class CustomGeometrySource::javaClass; - jni::Object CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomGeometrySource::javaClass.template GetConstructor(env); - return jni::Object(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void CustomGeometrySource::addToMap(JNIEnv& env, jni::Object obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { @@ -174,13 +179,13 @@ namespace android { void CustomGeometrySource::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomGeometrySource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, CustomGeometrySource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/custom_geometry_source.hpp b/platform/android/src/style/sources/custom_geometry_source.hpp index 801f81b08..ecfadd659 100644 --- a/platform/android/src/style/sources/custom_geometry_source.hpp +++ b/platform/android/src/style/sources/custom_geometry_source.hpp @@ -18,14 +18,10 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/CustomGeometrySource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); CustomGeometrySource(jni::JNIEnv&, jni::String, jni::Object<>); - CustomGeometrySource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~CustomGeometrySource(); bool removeFromMap(JNIEnv&, jni::Object, mbgl::Map&) override; @@ -36,6 +32,8 @@ public: bool isCancelled(jni::jint z, jni::jint x, jni::jint y); void startThreads(); void releaseThreads(); + +private: void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, jni::Object jf); void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y); @@ -44,7 +42,6 @@ public: jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array> ); -private: jni::Object createJavaPeer(jni::JNIEnv&); }; // class CustomGeometrySource diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index 9d6ca704e..b9f3f7380 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -29,13 +29,14 @@ namespace android { // This conversion is expected not to fail because it's used only in contexts where // the value was originally a GeoJsonOptions object on the Java side. If it fails // to convert, it's a bug in our serialization or Java-side static typing. - static style::GeoJSONOptions convertGeoJSONOptions(jni::JNIEnv& env, jni::Object<> options) { + static style::GeoJSONOptions convertGeoJSONOptions(jni::JNIEnv& env, jni::Local> options) { using namespace mbgl::style::conversion; if (!options) { return style::GeoJSONOptions(); } Error error; - optional result = convert(mbgl::android::Value(env, options), error); + optional result = convert( + mbgl::android::Value(env, std::move(options)), error); if (!result) { throw std::logic_error(error.message); } @@ -45,7 +46,7 @@ namespace android { GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<> options) : Source(env, std::make_unique( jni::Make(env, sourceId), - convertGeoJSONOptions(env, options))) + convertGeoJSONOptions(env, jni::SeizeLocal(env, std::move(options))))) , threadPool(sharedThreadPool()) , converter(std::make_unique>(*threadPool)) { } @@ -100,22 +101,22 @@ namespace android { std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } return *convert>, std::vector>(env, features); } - jni::Class GeoJSONSource::javaClass; - jni::Object GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = GeoJSONSource::javaClass.template GetConstructor(env); - return jni::Object(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } template void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, jni::Object jObject) { - std::shared_ptr object = std::shared_ptr(jObject.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter()); + std::shared_ptr object = std::shared_ptr(jObject.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter()); Update::Converter converterFn = [this, object](ActorRef _callback) { converter->self().invoke(&FeatureConverter::convertObject, jni::Object(*object), _callback); @@ -158,13 +159,13 @@ namespace android { void GeoJSONSource::registerNative(jni::JNIEnv& env) { // Lookup the class - GeoJSONSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, GeoJSONSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 24ea3c73f..eb28e2470 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -30,35 +30,26 @@ struct Update { class GeoJSONSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/GeoJsonSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); GeoJSONSource(jni::JNIEnv&, jni::String, jni::Object<>); - GeoJSONSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~GeoJSONSource(); +private: void setGeoJSONString(jni::JNIEnv&, jni::String); - void setFeatureCollection(jni::JNIEnv&, jni::Object); - void setFeature(jni::JNIEnv&, jni::Object); - void setGeometry(jni::JNIEnv&, jni::Object); - void setURL(jni::JNIEnv&, jni::String); + jni::Array> querySourceFeatures(jni::JNIEnv&, + jni::Array>); + jni::String getURL(jni::JNIEnv&); - jni::Array> querySourceFeatures(jni::JNIEnv&, - jni::Array> jfilter); - -private: jni::Object createJavaPeer(jni::JNIEnv&); std::unique_ptr awaitingUpdate; std::unique_ptr update; diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp index 278564485..343b7439c 100644 --- a/platform/android/src/style/sources/image_source.cpp +++ b/platform/android/src/style/sources/image_source.cpp @@ -50,22 +50,21 @@ namespace android { LatLngQuad::getLatLngArray(env, coordinatesObject)); } - jni::Class ImageSource::javaClass; - jni::Object ImageSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = ImageSource::javaClass.template GetConstructor(env); - return jni::Object(ImageSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void ImageSource::registerNative(jni::JNIEnv& env) { // Lookup the class - ImageSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, ImageSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp index 6021a03dc..b09d4f8c9 100644 --- a/platform/android/src/style/sources/image_source.hpp +++ b/platform/android/src/style/sources/image_source.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/ImageSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); ImageSource(jni::JNIEnv&, jni::String, jni::Object); diff --git a/platform/android/src/style/sources/raster_dem_source.cpp b/platform/android/src/style/sources/raster_dem_source.cpp index 75e0159d7..73d04f27c 100644 --- a/platform/android/src/style/sources/raster_dem_source.cpp +++ b/platform/android/src/style/sources/raster_dem_source.cpp @@ -17,7 +17,7 @@ namespace android { env, std::make_unique( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)), + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))), tileSize ) ) { @@ -36,22 +36,21 @@ namespace android { return url ? jni::Make(env, *url) : jni::String(); } - jni::Class RasterDEMSource::javaClass; - jni::Object RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterDEMSource::javaClass.template GetConstructor(env); - return jni::Object(RasterDEMSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void RasterDEMSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterDEMSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, RasterDEMSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, jni::jint>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/raster_dem_source.hpp b/platform/android/src/style/sources/raster_dem_source.hpp index 56924c1f8..25d9fe90c 100644 --- a/platform/android/src/style/sources/raster_dem_source.hpp +++ b/platform/android/src/style/sources/raster_dem_source.hpp @@ -9,17 +9,12 @@ namespace android { class RasterDEMSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterDemSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); RasterDEMSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - RasterDEMSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~RasterDEMSource(); jni::String getURL(jni::JNIEnv&); diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp index 33223a5b6..4eef41c8b 100644 --- a/platform/android/src/style/sources/raster_source.cpp +++ b/platform/android/src/style/sources/raster_source.cpp @@ -16,7 +16,7 @@ namespace android { env, std::make_unique( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)), + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))), tileSize ) ) { @@ -35,22 +35,21 @@ namespace android { return url ? jni::Make(env, *url) : jni::String(); } - jni::Class RasterSource::javaClass; - jni::Object RasterSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterSource::javaClass.template GetConstructor(env); - return jni::Object(RasterSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void RasterSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, RasterSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, jni::jint>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/raster_source.hpp b/platform/android/src/style/sources/raster_source.hpp index a1da22f40..888d9f601 100644 --- a/platform/android/src/style/sources/raster_source.hpp +++ b/platform/android/src/style/sources/raster_source.hpp @@ -9,17 +9,12 @@ namespace android { class RasterSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); RasterSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - RasterSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~RasterSource(); jni::String getURL(jni::JNIEnv&); diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp index d2e2426c0..c7968786e 100644 --- a/platform/android/src/style/sources/source.cpp +++ b/platform/android/src/style/sources/source.cpp @@ -76,6 +76,7 @@ namespace android { if (ownedSource.get() == nullptr && javaPeer.get() != nullptr) { // Manually clear the java peer android::UniqueEnv env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*env); static auto nativePtrField = javaClass.GetField(*env, "nativePtr"); javaPeer->Set(*env, nativePtrField, (jlong) 0); javaPeer.reset(); @@ -140,16 +141,14 @@ namespace android { rendererFrontend = nullptr; } - jni::Class Source::javaClass; - void Source::registerNative(jni::JNIEnv& env) { // Lookup the class - Source::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Source::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", METHOD(&Source::getId, "nativeGetId"), METHOD(&Source::getAttribution, "nativeGetAttribution") ); diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp index 6b906eb9c..492be8dfe 100644 --- a/platform/android/src/style/sources/source.hpp +++ b/platform/android/src/style/sources/source.hpp @@ -17,8 +17,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/Source"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static jni::Object peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); @@ -53,7 +51,7 @@ protected: mbgl::style::Source& source; // Set when the source is added to a map. - jni::UniqueObject javaPeer; + jni::Global> javaPeer; // RendererFrontend pointer is valid only when added to the map. AndroidRendererFrontend* rendererFrontend { nullptr }; diff --git a/platform/android/src/style/sources/unknown_source.cpp b/platform/android/src/style/sources/unknown_source.cpp index 4b5510c1d..8e9179839 100644 --- a/platform/android/src/style/sources/unknown_source.cpp +++ b/platform/android/src/style/sources/unknown_source.cpp @@ -18,22 +18,21 @@ namespace android { : Source(env, coreSource, createJavaPeer(env), frontend) { } - jni::Class UnknownSource::javaClass; - jni::Object UnknownSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownSource::javaClass.template GetConstructor(env); - return jni::Object(UnknownSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void UnknownSource::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, UnknownSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", init, "initialize", "finalize" diff --git a/platform/android/src/style/sources/unknown_source.hpp b/platform/android/src/style/sources/unknown_source.hpp index 414d420c6..855aea7c6 100644 --- a/platform/android/src/style/sources/unknown_source.hpp +++ b/platform/android/src/style/sources/unknown_source.hpp @@ -12,8 +12,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/UnknownSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); UnknownSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index 9a9548d28..69052bd98 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -25,7 +25,7 @@ namespace android { env, std::make_unique( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)) + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))) ) ) { } @@ -51,27 +51,27 @@ namespace android { std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { toVector(env, jSourceLayerIds), toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { toVector(env, jSourceLayerIds), toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } return *convert>, std::vector>(env, features); } - jni::Class VectorSource::javaClass; - jni::Object VectorSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = VectorSource::javaClass.template GetConstructor(env); - return jni::Object(VectorSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void VectorSource::registerNative(jni::JNIEnv& env) { // Lookup the class - VectorSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, VectorSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index 16049f5c7..587a4be20 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -10,25 +10,20 @@ namespace android { class VectorSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/VectorSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); VectorSource(jni::JNIEnv&, jni::String, jni::Object<>); - VectorSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~VectorSource(); +private: jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array, jni::Array> jfilter); jni::String getURL(jni::JNIEnv&); -private: jni::Object createJavaPeer(jni::JNIEnv&); }; // class VectorSource diff --git a/platform/android/src/style/transition_options.cpp b/platform/android/src/style/transition_options.cpp index c70aa5fe2..84bd90912 100644 --- a/platform/android/src/style/transition_options.cpp +++ b/platform/android/src/style/transition_options.cpp @@ -4,17 +4,14 @@ namespace mbgl { namespace android { jni::Object TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { - static auto method = TransitionOptions::javaClass.GetStaticMethod (jlong, jlong)>(env, "fromTransitionOptions"); - return TransitionOptions::javaClass.Call(env, method, duration, delay); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jlong, jlong)>(env, "fromTransitionOptions"); + return javaClass.Call(env, method, duration, delay); } void TransitionOptions::registerNative(jni::JNIEnv& env) { - // Lookup the class - TransitionOptions::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class TransitionOptions::javaClass; - - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/style/transition_options.hpp b/platform/android/src/style/transition_options.hpp index 3e6b0bc48..83276ca1d 100644 --- a/platform/android/src/style/transition_options.hpp +++ b/platform/android/src/style/transition_options.hpp @@ -9,17 +9,12 @@ namespace android { class TransitionOptions : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/TransitionOptions"; }; static jni::Object fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp index 70bdea667..6cdf13493 100644 --- a/platform/android/src/style/value.cpp +++ b/platform/android/src/style/value.cpp @@ -4,84 +4,70 @@ namespace mbgl { namespace android { - - class ObjectDeleter { - public: - ObjectDeleter() = default; - ObjectDeleter(JNIEnv& e) : env(e) {} - - void operator()(jni::jobject* p) const { - if (p) { - jni::DeleteLocalRef(env, p); - } - } - - private: - JNIEnv& env; - }; - // Instance - Value::Value(jni::JNIEnv& _env, jni::jobject* _value) : env(_env), value(_value, ObjectDeleter(env)) {} + Value::Value(jni::JNIEnv& _env, jni::Local> _value) + : env(_env), + value(std::move(_value)) {} bool Value::isNull() const { - return value == nullptr; + return !value; } bool Value::isArray() const { - return jni::IsInstanceOf(env, value.get(), *java::ObjectArray::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::ObjectArray::jclass); } bool Value::isObject() const { - return jni::IsInstanceOf(env, value.get(), *java::Map::jclass);; + return jni::IsInstanceOf(env, value->Get(), *java::Map::jclass); } bool Value::isString() const { - return jni::IsInstanceOf(env, value.get(), *java::String::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::String::jclass); } bool Value::isBool() const { - return jni::IsInstanceOf(env, value.get(), *java::Boolean::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::Boolean::jclass); } bool Value::isNumber() const { - return jni::IsInstanceOf(env, value.get(), *java::Number::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::Number::jclass); } std::string Value::toString() const { - jni::jstring* string = reinterpret_cast(value.get()); + jni::jstring* string = reinterpret_cast(value->Get()); return jni::Make(env, jni::String(string)); } float Value::toFloat() const { - return jni::CallMethod(env, value.get(), *java::Number::floatValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Number::floatValueMethodId); } double Value::toDouble() const { - return jni::CallMethod(env, value.get(), *java::Number::doubleValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Number::doubleValueMethodId); } long Value::toLong() const { - return jni::CallMethod(env, value.get(), *java::Number::longValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Number::longValueMethodId); } bool Value::toBool() const { - return jni::CallMethod(env, value.get(), *java::Boolean::booleanValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Boolean::booleanValueMethodId); } Value Value::get(const char* key) const { - jni::jobject* member = jni::CallMethod(env, value.get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).Get()); - return Value(env, member); + jni::jobject* member = jni::CallMethod(env, value->Get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).Get()); + return Value(env, jni::SeizeLocal(env, jni::Object<>(member))); } int Value::getLength() const { - auto array = (jni::jarray*) value.get(); + auto array = (jni::jarray*) value->Get(); return jni::GetArrayLength(env, *array); } Value Value::get(const int index) const { - auto array = (jni::jarray*) value.get(); - return Value(env, jni::GetObjectArrayElement(env, *array, index)); + auto array = (jni::jarray*) value->Get(); + return Value(env, jni::SeizeLocal(env, jni::Object<>(jni::GetObjectArrayElement(env, *array, index)))); } } } diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp index 2057b9345..bd1c552be 100644 --- a/platform/android/src/style/value.hpp +++ b/platform/android/src/style/value.hpp @@ -9,7 +9,7 @@ namespace android { class Value { public: - Value(jni::JNIEnv&, jni::jobject*); + Value(jni::JNIEnv&, jni::Local>); Value(Value&&) = default; Value& operator=(Value&&) = default; @@ -34,7 +34,7 @@ public: Value get(const int index ) const; jni::JNIEnv& env; - std::shared_ptr value; + jni::Local> value; }; } diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/text/collator.cpp index 37af0a1c5..86e72a1da 100644 --- a/platform/android/src/text/collator.cpp +++ b/platform/android/src/text/collator.cpp @@ -13,34 +13,32 @@ namespace mbgl { namespace android { void Collator::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Collator::javaClass; - jni::Object Collator::getInstance(jni::JNIEnv& env, jni::Object locale) { - using Signature = jni::Object(jni::Object); - auto method = javaClass.GetStaticMethod(env, "getInstance"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "getInstance"); return javaClass.Call(env, method, locale); } void Collator::setStrength(jni::JNIEnv& env, jni::Object collator, jni::jint strength) { - using Signature = void(jni::jint); - auto static method = javaClass.GetMethod(env, "setStrength"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "setStrength"); collator.Call(env, method, strength); } jni::jint Collator::compare(jni::JNIEnv& env, jni::Object collator, jni::String lhs, jni::String rhs) { - using Signature = jni::jint(jni::String, jni::String); - auto static method = javaClass.GetMethod(env, "compare"); + static auto javaClass = jni::Class::Singleton(env); + auto static method = javaClass.GetMethod(env, "compare"); return collator.Call(env, method, lhs, rhs); } void Locale::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } - /* +/* We would prefer to use for/toLanguageTag, but they're only available in API level 21+ jni::Object Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) { @@ -54,39 +52,38 @@ jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object locale) auto static method = javaClass.GetMethod(env, "toLanguageTag"); return locale.Call(env, method); } - */ - +*/ jni::String Locale::getLanguage(jni::JNIEnv& env, jni::Object locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod(env, "getLanguage"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getLanguage"); return locale.Call(env, method); } jni::String Locale::getCountry(jni::JNIEnv& env, jni::Object locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod(env, "getCountry"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getCountry"); return locale.Call(env, method); } jni::Object Locale::getDefault(jni::JNIEnv& env) { - using Signature = jni::Object(); - auto method = javaClass.GetStaticMethod(env, "getDefault"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod ()>(env, "getDefault"); return javaClass.Call(env, method); } jni::Object Locale::New(jni::JNIEnv& env, jni::String language) { + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, language); } jni::Object Locale::New(jni::JNIEnv& env, jni::String language, jni::String region) { + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, language, region); } -jni::Class Locale::javaClass; - } // namespace android namespace style { @@ -138,28 +135,23 @@ 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::String jlhs = jni::Make(*env, useUnaccent ? + jni::Local jlhs = jni::SeizeLocal(*env, jni::Make(*env, useUnaccent ? platform::unaccent(lhs) : - lhs); - jni::String jrhs = jni::Make(*env, useUnaccent ? + lhs)); + jni::Local jrhs = jni::SeizeLocal(*env, jni::Make(*env, useUnaccent ? platform::unaccent(rhs) : - rhs); + rhs)); - jni::jint result = android::Collator::compare(*env, *collator, jlhs, jrhs);; - - jni::DeleteLocalRef(*env, jlhs); - jni::DeleteLocalRef(*env, jrhs); + jni::jint result = android::Collator::compare(*env, *collator, *jlhs, *jrhs); return result; } std::string resolvedLocale() const { - jni::String jLanguage = android::Locale::getLanguage(*env, *locale); - std::string language = jni::Make(*env, jLanguage); - jni::DeleteLocalRef(*env, jLanguage); - jni::String jRegion = android::Locale::getCountry(*env, *locale); - std::string region = jni::Make(*env, jRegion); - jni::DeleteLocalRef(*env, jRegion); + std::string language = jni::Make(*env, + *jni::SeizeLocal(*env, android::Locale::getLanguage(*env, *locale))); + std::string region = jni::Make(*env, + *jni::SeizeLocal(*env, android::Locale::getCountry(*env, *locale))); optional resultLanguage; if (!language.empty()) resultLanguage = language; @@ -168,13 +160,14 @@ public: return LanguageTag(resultLanguage, {}, resultRegion).toBCP47(); } + private: bool caseSensitive; bool diacriticSensitive; android::UniqueEnv env; - jni::UniqueObject collator; - jni::UniqueObject locale; + jni::Global> collator; + jni::Global> locale; }; diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/text/collator_jni.hpp index 96c381b1c..30fb6a436 100644 --- a/platform/android/src/text/collator_jni.hpp +++ b/platform/android/src/text/collator_jni.hpp @@ -31,10 +31,8 @@ public: static jni::Object New(jni::JNIEnv&, jni::String); static jni::Object New(jni::JNIEnv&, jni::String, jni::String); - static jni::Class javaClass; static void registerNative(jni::JNIEnv&); - }; class Collator { @@ -47,10 +45,8 @@ public: static jni::jint compare(jni::JNIEnv&, jni::Object, jni::String, jni::String); - static jni::Class javaClass; static void registerNative(jni::JNIEnv&); - }; } // namespace android diff --git a/platform/android/src/text/local_glyph_rasterizer.cpp b/platform/android/src/text/local_glyph_rasterizer.cpp index 3dc1eb275..adfa0559f 100644 --- a/platform/android/src/text/local_glyph_rasterizer.cpp +++ b/platform/android/src/text/local_glyph_rasterizer.cpp @@ -36,6 +36,7 @@ namespace android { LocalGlyphRasterizer::LocalGlyphRasterizer() { UniqueEnv env { AttachEnv() }; + static auto javaClass = jni::Class::Singleton(*env); static auto constructor = javaClass.GetConstructor(*env); javaObject = javaClass.New(*env, constructor).NewGlobalRef(*env); @@ -44,29 +45,22 @@ LocalGlyphRasterizer::LocalGlyphRasterizer() { PremultipliedImage LocalGlyphRasterizer::drawGlyphBitmap(const std::string& fontFamily, const bool bold, const GlyphID glyphID) { UniqueEnv env { AttachEnv() }; - using Signature = jni::Object(jni::String, jni::jboolean, jni::jchar); - static auto method = javaClass.GetMethod(*env, "drawGlyphBitmap"); + static auto javaClass = jni::Class::Singleton(*env); + static auto drawGlyphBitmap = javaClass.GetMethod (jni::String, jni::jboolean, jni::jchar)>(*env, "drawGlyphBitmap"); - jni::String jniFontFamily = jni::Make(*env, fontFamily); + auto javaBitmap = jni::SeizeLocal(*env, + javaObject->Call(*env, drawGlyphBitmap, + *jni::SeizeLocal(*env, jni::Make(*env, fontFamily)), + static_cast(bold), + static_cast(glyphID))); - auto javaBitmap = javaObject->Call(*env, - method, - jniFontFamily, - static_cast(bold), - static_cast(glyphID)); - jni::DeleteLocalRef(*env, jniFontFamily); - - PremultipliedImage result = Bitmap::GetImage(*env, javaBitmap); - jni::DeleteLocalRef(*env, javaBitmap); - return result; + return Bitmap::GetImage(*env, *javaBitmap); } void LocalGlyphRasterizer::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class LocalGlyphRasterizer::javaClass; - } // namespace android class LocalGlyphRasterizer::Impl { diff --git a/platform/android/src/text/local_glyph_rasterizer_jni.hpp b/platform/android/src/text/local_glyph_rasterizer_jni.hpp index 1c83ea5f5..e80e84833 100644 --- a/platform/android/src/text/local_glyph_rasterizer_jni.hpp +++ b/platform/android/src/text/local_glyph_rasterizer_jni.hpp @@ -19,8 +19,6 @@ class LocalGlyphRasterizer { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/text/LocalGlyphRasterizer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); LocalGlyphRasterizer(); @@ -28,7 +26,7 @@ public: PremultipliedImage drawGlyphBitmap(const std::string& fontFamily, const bool bold, const char16_t glyphID); private: - jni::UniqueObject javaObject; + jni::Global> javaObject; }; } // namespace android