diff options
153 files changed, 817 insertions, 1753 deletions
diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index 4caa6d4d88..7330f2f3a2 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 eca7529c0b..9a57e76808 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 a1fe436dbd..b9a8c714a1 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> Marker::javaClass; - mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, jni::Object<Marker> marker) { - static auto positionField = Marker::javaClass.GetField<jni::Object<LatLng>>(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<Marker>::Singleton(env); + static auto positionField = javaClass.GetField<jni::Object<LatLng>>(env, "position"); + return LatLng::getGeometry(env, *jni::SeizeLocal(env, marker.Get(env, positionField))); } std::string Marker::getIconId(jni::JNIEnv& env, jni::Object<Marker> marker) { - static auto iconIdField = Marker::javaClass.GetField<jni::String>(env, "iconId"); - auto jIconId = marker.Get(env, iconIdField); - auto iconId = jni::Make<std::string>(env, jIconId); - jni::DeleteLocalRef(env, jIconId); - return iconId; + static auto javaClass = jni::Class<Marker>::Singleton(env); + static auto iconIdField = javaClass.GetField<jni::String>(env, "iconId"); + return jni::Make<std::string>(env, *jni::SeizeLocal(env, marker.Get(env, iconIdField))); } void Marker::registerNative(jni::JNIEnv& env) { - // Lookup the class - Marker::javaClass = *jni::Class<Marker>::Find(env).NewGlobalRef(env).release(); + jni::Class<Marker>::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 b11a225245..d03c244921 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<Marker> javaClass; - static mbgl::Point<double> getPosition(jni::JNIEnv&, jni::Object<Marker>); static std::string getIconId(jni::JNIEnv&, jni::Object<Marker>); diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp index e1152dfd60..1a6b945261 100644 --- a/platform/android/src/annotation/multi_point.hpp +++ b/platform/android/src/annotation/multi_point.hpp @@ -15,25 +15,17 @@ protected: template <class Geometry> static Geometry toGeometry(JNIEnv& env, jni::Object<java::util::List> pointsList) { - NullCheck(env, &pointsList); - auto jarray = java::util::List::toArray<LatLng>(env, pointsList); - NullCheck(env, &jarray); + auto jarray = jni::SeizeLocal(env, java::util::List::toArray<LatLng>(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 fbd849432a..f049911be0 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> Polygon::javaClass; - mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object<Polygon> 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<double> geometry { MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, points) }; + mbgl::Polygon<double> geometry { MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, *points) }; - auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, holes); - std::size_t jHoleListsSize = jHoleListsArray.Length(env); + auto jHoleListsArray = jni::SeizeLocal(env, java::util::List::toArray<java::util::List>(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<mbgl::LinearRing<double>>(env, jHoleList)); - jni::DeleteLocalRef(env, jHoleList); + geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(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<java::util::List> Polygon::getPoints(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<jni::Object<java::util::List>>(env, "points"); + static auto javaClass = jni::Class<Polygon>::Singleton(env); + static auto field = javaClass.GetField<jni::Object<java::util::List>>(env, "points"); return polygon.Get(env, field); } jni::Object<java::util::List> Polygon::getHoles(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<jni::Object<java::util::List>>(env, "holes"); + static auto javaClass = jni::Class<Polygon>::Singleton(env); + static auto field = javaClass.GetField<jni::Object<java::util::List>>(env, "holes"); return polygon.Get(env, field); } float Polygon::getOpacity(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<float>(env, "alpha"); + static auto javaClass = jni::Class<Polygon>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "alpha"); return polygon.Get(env, field); } mbgl::Color Polygon::getFillColor(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<int>(env, "fillColor"); + static auto javaClass = jni::Class<Polygon>::Singleton(env); + static auto field = javaClass.GetField<int>(env, "fillColor"); return *conversion::convert<mbgl::Color, int>(env, polygon.Get(env, field)); } mbgl::Color Polygon::getOutlineColor(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<int>(env, "strokeColor"); + static auto javaClass = jni::Class<Polygon>::Singleton(env); + static auto field = javaClass.GetField<int>(env, "strokeColor"); return *conversion::convert<mbgl::Color, int>(env, polygon.Get(env, field)); } void Polygon::registerNative(jni::JNIEnv& env) { - Polygon::javaClass = *jni::Class<Polygon>::Find(env).NewGlobalRef(env).release(); + jni::Class<Polygon>::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 a98b2822cf..f7cc015c8a 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<Polygon> javaClass; - static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object<Polygon>); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index 3723dc1871..22d25a0f75 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> Polyline::javaClass; - mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - auto points = Polyline::getPoints(env, polyline); + auto points = jni::SeizeLocal(env, Polyline::getPoints(env, polyline)); - mbgl::LineAnnotation annotation { MultiPoint::toGeometry<mbgl::LineString<double>>(env, points) }; + mbgl::LineAnnotation annotation { MultiPoint::toGeometry<mbgl::LineString<double>>(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<java::util::List> Polyline::getPoints(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<jni::Object<java::util::List>>(env, "points"); + static auto javaClass = jni::Class<Polyline>::Singleton(env); + static auto field = javaClass.GetField<jni::Object<java::util::List>>(env, "points"); return polyline.Get(env, field); } float Polyline::getOpacity(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<float>(env, "alpha"); + static auto javaClass = jni::Class<Polyline>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "alpha"); return polyline.Get(env, field); } mbgl::Color Polyline::getColor(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<int>(env, "color"); + static auto javaClass = jni::Class<Polyline>::Singleton(env); + static auto field = javaClass.GetField<int>(env, "color"); return *conversion::convert<mbgl::Color, int>(env, polyline.Get(env, field)); } float Polyline::getWidth(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<float>(env, "width"); + static auto javaClass = jni::Class<Polyline>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "width"); return polyline.Get(env, field); } void Polyline::registerNative(jni::JNIEnv& env) { - Polyline::javaClass = *jni::Class<Polyline>::Find(env).NewGlobalRef(env).release(); + jni::Class<Polyline>::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 bcc616a5f7..69f5d19c1f 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<Polyline> javaClass; - static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object<Polyline>); 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 dcad95664a..bb0809a442 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<android::AssetManager> assetManager; + jni::Global<jni::Object<android::AssetManager>> assetManager; std::unique_ptr<util::Thread<Impl>> impl; }; diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp index 0d3670b666..53136b868e 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> bitmap; uint8_t* address; }; -void Bitmap::Config::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Config>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Bitmap::Config> Bitmap::Config::_class; - jni::Object<Bitmap::Config> Bitmap::Config::Create(jni::JNIEnv& env, Value value) { + static auto _class = jni::Class<Config>::Singleton(env); switch (value) { case ALPHA_8: return _class.Get(env, @@ -62,18 +54,17 @@ jni::Object<Bitmap::Config> Bitmap::Config::Create(jni::JNIEnv& env, Value value } void Bitmap::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Bitmap>::Find(env).NewGlobalRef(env).release(); - Config::registerNative(env); + jni::Class<Bitmap>::Singleton(env); + jni::Class<Bitmap::Config>::Singleton(env); } -jni::Class<Bitmap> Bitmap::_class; - jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, jni::Object<Config> config) { - using Signature = jni::Object<Bitmap>(jni::jint, jni::jint, jni::Object<Config>); - auto method = _class.GetStaticMethod<Signature>(env, "createBitmap"); + static auto _class = jni::Class<Bitmap>::Singleton(env); + static auto method = _class.GetStaticMethod<jni::Object<Bitmap> (jni::jint, jni::jint, jni::Object<Config>)>(env, "createBitmap"); + return _class.Call(env, method, width, height, config); } @@ -106,15 +97,13 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object<Bitmap> 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> bitmap } jni::Object<Bitmap> Bitmap::Copy(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) { - using Signature = jni::Object<Bitmap>(jni::Object<Config>, jni::jboolean); - auto static method = _class.GetMethod<Signature>(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<Bitmap>::Singleton(env); + static auto copy = klass.GetMethod<jni::Object<Bitmap> (jni::Object<Config>, 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 c4e41db1e0..2266bc0e67 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<Config> Create(jni::JNIEnv&, Value); - - private: - static jni::Class<Config> _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<Bitmap> CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, jni::Object<Config>); + static jni::Object<Bitmap> 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<Bitmap>); static jni::Object<Bitmap> CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); static jni::Object<Bitmap> Copy(jni::JNIEnv&, jni::Object<Bitmap>); - -private: - static jni::Class<Bitmap> _class; }; } // namespace android diff --git a/platform/android/src/bitmap_factory.cpp b/platform/android/src/bitmap_factory.cpp index 7d9b068b20..79cdc913a0 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<BitmapFactory>::Find(env).NewGlobalRef(env).release(); + jni::Class<BitmapFactory>::Singleton(env); } -jni::Class<BitmapFactory> BitmapFactory::_class; - jni::Object<Bitmap> BitmapFactory::DecodeByteArray(jni::JNIEnv& env, jni::Array<jni::jbyte> data, jni::jint offset, jni::jint length) { + static auto _class = jni::Class<BitmapFactory>::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<Bitmap>(jni::Array<jni::jbyte>, jni::jint, jni::jint); - auto method = _class.GetStaticMethod<Signature>(env, "decodeByteArray"); + using Signature = jni::Object<Bitmap> (jni::Array<jni::jbyte>, jni::jint, jni::jint); + static auto method = _class.GetStaticMethod<Signature>(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 b0e7198260..6e019d017c 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<Bitmap> DecodeByteArray(jni::JNIEnv&, jni::Array<jni::jbyte> data, jni::jint offset, jni::jint length); - -private: - static jni::Class<BitmapFactory> _class; }; } // namespace android diff --git a/platform/android/src/connectivity_listener.cpp b/platform/android/src/connectivity_listener.cpp index 5b1c0a86e4..3fcc580aab 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> ConnectivityListener::javaClass; - void ConnectivityListener::registerNative(jni::JNIEnv& env) { // Lookup the class - ConnectivityListener::javaClass = *jni::Class<ConnectivityListener>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<ConnectivityListener>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<ConnectivityListener>( env, - ConnectivityListener::javaClass, + javaClass, "nativePtr", std::make_unique<ConnectivityListener, JNIEnv&>, "initialize", diff --git a/platform/android/src/connectivity_listener.hpp b/platform/android/src/connectivity_listener.hpp index b0d655d027..a09507c0f7 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<ConnectivityListener> javaClass; - static void registerNative(jni::JNIEnv&); /* diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp index 6775228e15..3195458aa6 100644 --- a/platform/android/src/conversion/collection.cpp +++ b/platform/android/src/conversion/collection.cpp @@ -11,24 +11,17 @@ std::vector<std::string> toVector(JNIEnv& env, jni::Array<jni::String> array) { vector.reserve(len); for (std::size_t i = 0; i < len; i++) { - jni::String jstr = array.Get(env, i); - vector.push_back(*convert<std::string, jni::String>(env, jstr)); - jni::DeleteLocalRef(env, jstr); + vector.push_back(*convert<std::string>(env, *jni::SeizeLocal(env, array.Get(env, i)))); } return vector; } jni::Array<jni::String> toArray(JNIEnv& env, const std::vector<std::string>& vector) { - static auto clazz = *jni::Class<jni::StringTag>::Find(env).NewGlobalRef(env).release(); - auto result = jni::Array<jni::String>::New(env, vector.size(), clazz); - - std::size_t index = 0; - for (auto&& item : vector) { - auto element = jni::Make<jni::String>(env, item); - result.Set(env, index, element); - DeleteLocalRef(env, element); - index++; + auto result = jni::Array<jni::String>::New(env, vector.size()); + + for (std::size_t i = 0; i < vector.size(); i++) { + result.Set(env, i, *jni::SeizeLocal(env, jni::Make<jni::String>(env, vector.at(i)))); } return result; diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 2a6cac3b02..32c304b909 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<FileSource:: // a subsequent call. // Note: we're converting it to shared_ptr because this lambda is converted to a std::function, // which requires copyability of its captured variables. - [callback = std::shared_ptr<jni::jobject>(transformCallback.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter())] + [callback = std::shared_ptr<jni::jobject>(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<FileSource::ResourceTransformCallback>(*callback), int(kind), url_); @@ -92,10 +92,9 @@ jni::jboolean FileSource::isResumed(jni::JNIEnv&) { return (jboolean) false; } -jni::Class<FileSource> FileSource::javaClass; - FileSource* FileSource::getNativePeer(jni::JNIEnv& env, jni::Object<FileSource> jFileSource) { - static auto field = FileSource::javaClass.GetField<jlong>(env, "nativePtr"); + static auto javaClass = jni::Class<FileSource>::Singleton(env); + static auto field = javaClass.GetField<jlong>(env, "nativePtr"); return reinterpret_cast<FileSource *>(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<FileSource>::Find(env).NewGlobalRef(env).release(); - FileSource::ResourceTransformCallback::javaClass = *jni::Class<FileSource::ResourceTransformCallback>::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<ResourceTransformCallback>::Singleton(env); + + static auto javaClass = jni::Class<FileSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<FileSource>( - env, FileSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<FileSource, JNIEnv&, jni::String, jni::String, jni::Object<AssetManager>>, "initialize", "finalize", @@ -131,16 +133,13 @@ void FileSource::registerNative(jni::JNIEnv& env) { // FileSource::ResourceTransformCallback // -jni::Class<FileSource::ResourceTransformCallback> FileSource::ResourceTransformCallback::javaClass; - std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, jni::Object<FileSource::ResourceTransformCallback> callback, int kind, std::string url_) { - static auto method = FileSource::ResourceTransformCallback::javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL"); - auto url = jni::Make<jni::String>(env, url_); + static auto javaClass = jni::Class<FileSource::ResourceTransformCallback>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL"); - url = callback.Call(env, method, kind, url); - auto urlStr = jni::Make<std::string>(env, url); - jni::DeleteLocalRef(env, url); - return urlStr; + return jni::Make<std::string>(env, + *jni::SeizeLocal(env, callback.Call(env, method, kind, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, url_))))); } } // namespace android diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index e4295e1b84..f1b11c754c 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<FileSource::ResourceTransformCallback>, int, std::string); - - static jni::Class<ResourceTransformCallback> javaClass; }; FileSource(jni::JNIEnv&, jni::String, jni::String, jni::Object<AssetManager>); @@ -47,8 +45,6 @@ public: jni::jboolean isResumed(jni::JNIEnv&); - static jni::Class<FileSource> javaClass; - static FileSource* getNativePeer(jni::JNIEnv&, jni::Object<FileSource>); static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, jni::Object<FileSource>); diff --git a/platform/android/src/geojson/conversion/feature.cpp b/platform/android/src/geojson/conversion/feature.cpp index 3cb6d37b17..7386e29df5 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; - - /** - * 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, "<init>", "(Ljava/lang/Boolean;)V"); - - // Create JsonPrimitive - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, bool>(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, "<init>", "(Ljava/lang/String;)V"); - - // Create JsonPrimitive - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - /** - * Number primitives - */ - template <class Number> - 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, "<init>", "(Ljava/lang/Number;)V"); - - // Create JsonPrimitive - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, Number>(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - - /** - * Json Array - */ - jni::jobject* operator()(const std::vector<mbgl::Value> &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, "<init>", "()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<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this)); - jni::CallMethod<void>(env, jarray, *add, converted.get()); - } - - return jarray; - } - - /** - * Json Object - */ - jni::jobject* operator()(const std::unordered_map<std::string, mbgl::Value> &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, "<init>", "()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<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this)); - jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first)); - jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get()); - } - - return jsonObject; - } -}; - -Result<jni::jobject*> Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>>::operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& 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, "<init>", "()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<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator)); - jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first)); - jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get()); - } - - return {jsonObject}; -} - -Result<jni::Object<android::geojson::Feature>> Converter<jni::Object<android::geojson::Feature>, 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<jni::String>(env, id); - - // Convert properties - auto properties = jni::Object<gson::JsonObject>(*convert<jni::jobject*>(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); +jni::Object<android::geojson::Feature> convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { + using namespace mbgl::android::geojson; - 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<jni::String>(env, value.id ? value.id.value().match(FeatureIdVisitor()) : ""))); } Result<jni::Array<jni::Object<android::geojson::Feature>>> Converter<jni::Array<jni::Object<android::geojson::Feature>>, std::vector<mbgl::Feature>>::operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const { using namespace mbgl::android::geojson; - auto features = jni::Array<jni::Object<Feature>>::New(env, value.size(), Feature::javaClass); - for(size_t i = 0; i < value.size(); i = i + 1) { - auto converted = *convert<jni::Object<android::geojson::Feature>, mbgl::Feature>(env, value.at(i)); - features.Set(env, i, converted); - jni::DeleteLocalRef(env, converted); + auto features = jni::Array<jni::Object<Feature>>::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 031449cd23..d9fc0a0b67 100644 --- a/platform/android/src/geojson/conversion/feature.hpp +++ b/platform/android/src/geojson/conversion/feature.hpp @@ -7,23 +7,12 @@ #include <jni/jni.hpp> #include <vector> -#include <unordered_map> namespace mbgl { namespace android { namespace conversion { template <> -struct Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const; -}; - -template <> -struct Converter<jni::Object<android::geojson::Feature>, mbgl::Feature> { - Result<jni::Object<android::geojson::Feature>> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const; -}; - -template <> struct Converter<jni::Array<jni::Object<android::geojson::Feature>>, std::vector<mbgl::Feature>> { Result<jni::Array<jni::Object<android::geojson::Feature>>> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const; }; diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index d8a4e829e2..1e02c756eb 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<Feature> 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<mapbox::geometry::identifier> id; - auto jId = Feature::id(env, jFeature); + auto jId = jni::SeizeLocal(env, Feature::id(env, jFeature)); if (jId) { - id = { jni::Make<std::string>(env, jId) }; + id = { jni::Make<std::string>(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<Geometry> Feature::geometry(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - static auto method = Feature::javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry"); + static auto javaClass = jni::Class<Feature>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry"); return jFeature.Call(env, method); } jni::Object<gson::JsonObject> Feature::properties(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - static auto method = Feature::javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties"); + static auto javaClass = jni::Class<Feature>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties"); return jFeature.Call(env, method); } jni::String Feature::id(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - static auto method = Feature::javaClass.GetMethod<jni::String ()>(env, "id"); + static auto javaClass = jni::Class<Feature>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "id"); return jFeature.Call(env, method); } jni::Object<Feature> Feature::fromGeometry(jni::JNIEnv& env, jni::Object<Geometry> geometry, jni::Object<gson::JsonObject> properties, jni::String id) { - static auto method = Feature::javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<gson::JsonObject>, jni::String)>(env, "fromGeometry"); - return Feature::javaClass.Call(env, method, geometry, properties, id); + static auto javaClass = jni::Class<Feature>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<gson::JsonObject>, 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<Feature>::Find(env).NewGlobalRef(env).release(); + jni::Class<Feature>::Singleton(env); } -jni::Class<Feature> 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 ab59d783e5..de38e9b1e3 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -28,10 +28,7 @@ public: static jni::Object<gson::JsonObject> properties(jni::JNIEnv&, jni::Object<Feature>); - static jni::Class<Feature> 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 18a41d48fa..c2825e037b 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<Feature>(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<Feature>(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<java::util::List> FeatureCollection::features(jni::JNIEnv& env, jni::Object<FeatureCollection> jCollection) { - static auto method = FeatureCollection::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features"); + static auto javaClass = jni::Class<FeatureCollection>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features"); return jCollection.Call(env, method); } void FeatureCollection::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class<FeatureCollection>::Find(env).NewGlobalRef(env).release(); + jni::Class<FeatureCollection>::Singleton(env); } -jni::Class<FeatureCollection> 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 259ffab370..1b45cca5de 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<java::util::List> features(jni::JNIEnv&, jni::Object<FeatureCollection>); - static jni::Class<FeatureCollection> javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp index 5635b5a0f5..4262b4ee69 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<Geometry> operator()(const mbgl::Point<double> &geometry) const { - return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass); + return Point::New(env, geometry); } jni::Object<Geometry> operator()(const mbgl::LineString<double> &geometry) const { - return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass); + return LineString::New(env, geometry); } jni::Object<Geometry> operator()(const mbgl::MultiLineString<double> &geometry) const { - return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass); + return MultiLineString::New(env, geometry); } jni::Object<Geometry> operator()(const mbgl::MultiPoint<double> &geometry) const { - return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass); + return MultiPoint::New(env, geometry); } jni::Object<Geometry> operator()(const mbgl::Polygon<double> &geometry) const { - return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass); + return Polygon::New(env, geometry); } jni::Object<Geometry> operator()(const mbgl::MultiPolygon<double> &geometry) const { - return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass); + return MultiPolygon::New(env, geometry); } jni::Object<Geometry> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const { - return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass); + return GeometryCollection::New(env, geometry); } }; @@ -78,20 +78,15 @@ mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, jni::Object<Geometry> } std::string Geometry::getType(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) { - static auto method = Geometry::javaClass.GetMethod<jni::String ()>(env, "type"); - auto jType = jGeometry.Call(env, method); - auto type = jni::Make<std::string>(env, jType); - jni::DeleteLocalRef(env, jType); - return type; + static auto javaClass = jni::Class<Geometry>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "type"); + return jni::Make<std::string>(env, *jni::SeizeLocal(env, jGeometry.Call(env, method))); } void Geometry::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Geometry>::Find(env).NewGlobalRef(env).release(); + jni::Class<Geometry>::Singleton(env); } -jni::Class<Geometry> 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 a1bb886683..836c3bd5a0 100644 --- a/platform/android/src/geojson/geometry.hpp +++ b/platform/android/src/geojson/geometry.hpp @@ -1,7 +1,6 @@ #pragma once #include <mbgl/util/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #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<Geometry>); - static jni::Class<Geometry> 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 770cb9a5d6..ad0af71214 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> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) { // Create an array of geometries - auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size(), Geometry::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array<jni::Object<Geometry>>::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<GeometryCollection>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(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<double> GeometryCollection::convert(jni::JNIEnv &env, jni::Object<GeometryCollection> jCollection) { // Get geometries + static auto javaClass = jni::Class<GeometryCollection>::Singleton(env); static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "geometries"); - auto jList = jCollection.Call(env, getGeometries); // Turn into array - auto jarray = java::util::List::toArray<Geometry>(env, jList); - jni::DeleteLocalRef(env, jList); + auto jarray = jni::SeizeLocal(env, + java::util::List::toArray<Geometry>(env, + *jni::SeizeLocal(env, jCollection.Call(env, getGeometries)))); // Convert each geometry mapbox::geometry::geometry_collection<double> 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<GeometryCollection>::Find(env).NewGlobalRef(env).release(); + jni::Class<GeometryCollection>::Singleton(env); } -jni::Class<GeometryCollection> 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 9ed9953b0d..a301d86933 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<double> convert(jni::JNIEnv&, jni::Object<GeometryCollection>); - static jni::Class<GeometryCollection> 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 a5f1a468ce..5a18a02bb7 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> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) { - auto jList = asPointsList(env, lineString); - + static auto javaClass = jni::Class<LineString>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(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<LineString> 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<j mapbox::geojson::line_string lineString; if (jPointList) { - auto jPointArray = java::util::List::toArray<Point>(env, jPointList); - auto size = jPointArray.Length(env); + auto jPointArray = jni::SeizeLocal(env, java::util::List::toArray<Point>(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<java::util::List> LineString::coordinates(jni::JNIEnv &env, jni::Object<LineString> jLineString) { - static auto method = LineString::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); + static auto javaClass = jni::Class<LineString>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jLineString.Call(env, method); } void LineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<LineString>::Find(env).NewGlobalRef(env).release(); + jni::Class<LineString>::Singleton(env); } -jni::Class<LineString> 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 98dc414642..4df9349185 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<java::util::List> coordinates(jni::JNIEnv&, jni::Object<LineString>); - static jni::Class<LineString> 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 4a6ea37dd1..0a0974062c 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> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) { - auto jList = asPointsListsList(env, multiLineString); - + static auto javaClass = jni::Class<MultiLineString>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(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<MultiLineString> 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<java::util::List>(env, jPointListsList); + auto jPositionListsArray = jni::SeizeLocal(env, java::util::List::toArray<java::util::List>(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<java::util::List> MultiLineString::coordinates(jni::JNIEnv &env, jni::Object<MultiLineString> jLineString) { - static auto method = MultiLineString::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); + static auto javaClass = jni::Class<MultiLineString>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jLineString.Call(env, method); } void MultiLineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<MultiLineString>::Find(env).NewGlobalRef(env).release(); + jni::Class<MultiLineString>::Singleton(env); } -jni::Class<MultiLineString> 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 934a0cb6b5..c66aadaf03 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<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiLineString>); - static jni::Class<MultiLineString> 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 6f62541209..5f51058f38 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> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) { - auto jList = asPointsList(env, multiPoint); - + static auto javaClass = jni::Class<MultiPoint>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(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<MultiPoint> jMultiPoint) { mapbox::geojson::multi_point multiPoint; if (jMultiPoint) { - auto jPointListsList = MultiPoint::coordinates(env, jMultiPoint); - multiPoint = convertExplicit<mapbox::geojson::multi_point>(LineString::convert(env, jPointListsList)); - jni::DeleteLocalRef(env, jPointListsList); + multiPoint = convertExplicit<mapbox::geojson::multi_point>( + LineString::convert(env, *jni::SeizeLocal(env, MultiPoint::coordinates(env, jMultiPoint)))); } return multiPoint; } jni::Object<java::util::List> MultiPoint::coordinates(jni::JNIEnv &env, jni::Object<MultiPoint> jMultiPoint) { - static auto method = MultiPoint::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); + static auto javaClass = jni::Class<MultiPoint>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jMultiPoint.Call(env, method); } void MultiPoint::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<MultiPoint>::Find(env).NewGlobalRef(env).release(); + jni::Class<MultiPoint>::Singleton(env); } -jni::Class<MultiPoint> 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 cfe80cd34c..0df16bfd6a 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<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPoint>); - static jni::Class<MultiPoint> 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 cc872d4955..109ac714c3 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> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) { - auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size(), java::util::List::javaClass); + static auto javaClass = jni::Class<MultiPolygon>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats"); + + auto jarray = jni::SeizeLocal(env, + jni::Array<jni::Object<java::util::List>>::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<MultiPolygon> (jni::Object<java::util::List>)>(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<MultiPolygon> jMultiPolygon) { mapbox::geojson::multi_polygon multiPolygon; if (jMultiPolygon) { - auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon); - auto jPointListsListArray = java::util::List::toArray<java::util::List>(env, jPointListsListList); + auto jPointListsListList = jni::SeizeLocal(env, MultiPolygon::coordinates(env, jMultiPolygon)); + auto jPointListsListArray = jni::SeizeLocal(env, java::util::List::toArray<java::util::List>(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<java::util::List> MultiPolygon::coordinates(jni::JNIEnv &env, jni::Object<MultiPolygon> jPolygon) { - static auto method = MultiPolygon::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); + static auto javaClass = jni::Class<MultiPolygon>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jPolygon.Call(env, method); } void MultiPolygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<MultiPolygon>::Find(env).NewGlobalRef(env).release(); + jni::Class<MultiPolygon>::Singleton(env); } -jni::Class<MultiPolygon> 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 b4657af09d..3477e989ea 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<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPolygon>); - static jni::Class<MultiPolygon> javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index 8a9656ea14..69da997250 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> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) { + static auto javaClass = jni::Class<Point>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<Point> (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<Point> 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<java::util:: mapbox::geojson::point point; if (jDoubleList) { - auto jDoubleArray = java::util::List::toArray<jobject>(env, jDoubleList); + auto jDoubleArray = jni::SeizeLocal(env, java::util::List::toArray<jobject>(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<jni::jdouble>(env, lonObject, + point.x = jni::CallMethod<jni::jdouble>(env, *lonObject, *java::Number::doubleValueMethodId); - point.y = jni::CallMethod<jni::jdouble>(env, latObject, + point.y = jni::CallMethod<jni::jdouble>(env, *latObject, *java::Number::doubleValueMethodId); - - jni::DeleteLocalRef(env, lonObject); - jni::DeleteLocalRef(env, latObject); - jni::DeleteLocalRef(env, jDoubleArray); } return point; } jni::Object<java::util::List> Point::coordinates(jni::JNIEnv &env, jni::Object<Point> jPoint) { - static auto method = Point::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); - return jPoint.Call(env, method); + static auto javaClass = jni::Class<Point>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); + return jPoint.Call(env, method); } void Point::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Point>::Find(env).NewGlobalRef(env).release(); + jni::Class<Point>::Singleton(env); } -jni::Class<Point> 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 627bd1b649..3a852a3e74 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -26,8 +26,6 @@ public: static jni::Object<java::util::List> coordinates(JNIEnv&, jni::Object<Point>); - static jni::Class<Point> javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp index 96058b63b3..add843e294 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> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) { - auto jList = asPointsListsList(env, polygon); - + static auto javaClass = jni::Class<Polygon>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(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<Polygon> 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<java::ut jni::Object<java::util::List> Polygon::coordinates(jni::JNIEnv &env, jni::Object<Polygon> jPolygon) { - static auto method = Polygon::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); + static auto javaClass = jni::Class<Polygon>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jPolygon.Call(env, method); } void Polygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Polygon>::Find(env).NewGlobalRef(env).release(); + jni::Class<Polygon>::Singleton(env); } -jni::Class<Polygon> 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 f3c23b4d7b..adfa60df4d 100644 --- a/platform/android/src/geojson/polygon.hpp +++ b/platform/android/src/geojson/polygon.hpp @@ -27,8 +27,6 @@ public: static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<Polygon>); - static jni::Class<Polygon> javaClass; - static void registerNative(jni::JNIEnv &); }; diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp index 5e6d90a953..e889931c56 100644 --- a/platform/android/src/geojson/util.hpp +++ b/platform/android/src/geojson/util.hpp @@ -24,17 +24,13 @@ To convertExplicit(From&& src) { */ template <class T> static jni::Object<java::util::List> asPointsList(jni::JNIEnv& env, const T& pointsList) { - auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size(), Point::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array<jni::Object<Point>>::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<java::util::List> asPointsList(jni::JNIEnv& env, const T& poi */ template <class SHAPE> static jni::Object<java::util::List> asPointsListsList(JNIEnv& env, SHAPE value) { - auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size(), java::util::List::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array<jni::Object<java::util::List>>::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 0bf6ea7add..135755d67e 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> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { - static auto constructor = LatLng::javaClass.GetConstructor<double, double>(env); - return LatLng::javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); + static auto javaClass = jni::Class<LatLng>::Singleton(env); + static auto constructor = javaClass.GetConstructor<double, double>(env); + return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); } mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, jni::Object<LatLng> latLng) { - static auto latitudeField = LatLng::javaClass.GetField<jni::jdouble>(env, "latitude"); - static auto longitudeField = LatLng::javaClass.GetField<jni::jdouble>(env, "longitude"); + static auto javaClass = jni::Class<LatLng>::Singleton(env); + static auto latitudeField = javaClass.GetField<jni::jdouble>(env, "latitude"); + static auto longitudeField = javaClass.GetField<jni::jdouble>(env, "longitude"); return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField)); } @@ -20,12 +22,8 @@ mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, jni::Object<LatLng> latLng) { } void LatLng::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLng::javaClass = *jni::Class<LatLng>::Find(env).NewGlobalRef(env).release(); + jni::Class<LatLng>::Singleton(env); } -jni::Class<LatLng> 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 b2f12c8dcd..4431f1c739 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<LatLng>); - static jni::Class<LatLng> 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 827ee52e95..583120cb68 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> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { - static auto constructor = LatLngBounds::javaClass.GetConstructor<double, double, double, double>(env); - return LatLngBounds::javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); + static auto javaClass = jni::Class<LatLngBounds>::Singleton(env); + static auto constructor = javaClass.GetConstructor<double, double, double, double>(env); + return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); } mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> bounds) { - static auto swLatField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "latitudeSouth"); - static auto swLonField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "longitudeWest"); - static auto neLatField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "latitudeNorth"); - static auto neLonField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "longitudeEast"); + static auto javaClass = jni::Class<LatLngBounds>::Singleton(env); + static auto swLatField = javaClass.GetField<jni::jdouble>(env, "latitudeSouth"); + static auto swLonField = javaClass.GetField<jni::jdouble>(env, "longitudeWest"); + static auto neLatField = javaClass.GetField<jni::jdouble>(env, "latitudeNorth"); + static auto neLonField = javaClass.GetField<jni::jdouble>(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<L } void LatLngBounds::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLngBounds::javaClass = *jni::Class<LatLngBounds>::Find(env).NewGlobalRef(env).release(); + jni::Class<LatLngBounds>::Singleton(env); } -jni::Class<LatLngBounds> 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 1c853e4b67..751e0babda 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<LatLngBounds>); - static jni::Class<LatLngBounds> 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 2b36139e18..5530a22903 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> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) { - static auto quadConstructor = LatLngQuad::javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(env); - return LatLngQuad::javaClass.New(env, quadConstructor, + static auto javaClass = jni::Class<LatLngQuad>::Singleton(env); + static auto quadConstructor = javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(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> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLn } std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Object<LatLngQuad> quad) { - static auto topLeftField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "topLeft"); - static auto topRightField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "topRight"); - static auto bottomRightField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight"); - static auto bottomLeftField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft"); + static auto javaClass = jni::Class<LatLngQuad>::Singleton(env); + static auto topLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "topLeft"); + static auto topRightField = javaClass.GetField <jni::Object<LatLng>>(env, "topRight"); + static auto bottomRightField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight"); + static auto bottomLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft"); return std::array < mbgl::LatLng, 4 > {{ LatLng::getLatLng(env, quad.Get(env, topLeftField)), @@ -28,12 +30,8 @@ std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Ob } void LatLngQuad::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLngQuad::javaClass = *jni::Class<LatLngQuad>::Find(env).NewGlobalRef(env).release(); + jni::Class<LatLngQuad>::Singleton(env); } -jni::Class<LatLngQuad> 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 8f8c9abeef..ca1430ffbc 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<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, jni::Object<LatLngQuad>); - static jni::Class<LatLngQuad> 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 f3d9d1b0ef..4dfd7b57b2 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> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { - static auto constructor = ProjectedMeters::javaClass.GetConstructor<double, double>(env); - return ProjectedMeters::javaClass.New(env, constructor, northing, easting); + static auto javaClass = jni::Class<ProjectedMeters>::Singleton(env); + static auto constructor = javaClass.GetConstructor<double, double>(env); + return javaClass.New(env, constructor, northing, easting); } void ProjectedMeters::registerNative(jni::JNIEnv& env) { - // Lookup the class - ProjectedMeters::javaClass = *jni::Class<ProjectedMeters>::Find(env).NewGlobalRef(env).release(); + jni::Class<ProjectedMeters>::Singleton(env); } -jni::Class<ProjectedMeters> 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 9b70967b5d..5279e6bef2 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<ProjectedMeters> New(jni::JNIEnv&, double, double); - static jni::Class<ProjectedMeters> 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 3f854da2ea..eceb65b07a 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> PointF::New(jni::JNIEnv& env, float x, float y) { - static auto constructor = PointF::javaClass.GetConstructor<float, float>(env); - return PointF::javaClass.New(env, constructor, x, y); + static auto javaClass = jni::Class<PointF>::Singleton(env); + static auto constructor = javaClass.GetConstructor<float, float>(env); + return javaClass.New(env, constructor, x, y); } mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, jni::Object<PointF> point) { - static auto xField = PointF::javaClass.GetField<jni::jfloat>(env, "x"); - static auto yField = PointF::javaClass.GetField<jni::jfloat>(env, "y"); + static auto javaClass = jni::Class<PointF>::Singleton(env); + static auto xField = javaClass.GetField<jni::jfloat>(env, "x"); + static auto yField = javaClass.GetField<jni::jfloat>(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<PointF>::Find(env).NewGlobalRef(env).release(); + jni::Class<PointF>::Singleton(env); } -jni::Class<PointF> 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 e3ef24dd65..27bd49138f 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<PointF>); - static jni::Class<PointF> javaClass; - static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/graphics/rectf.cpp b/platform/android/src/graphics/rectf.cpp index 1b375dad18..9f05728b4c 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> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "left"); + static auto javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "left"); return rectf.Get(env, field); } float RectF::getTop(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "top"); + static auto javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "top"); return rectf.Get(env, field); } float RectF::getRight(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "right"); + static auto javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "right"); return rectf.Get(env, field); } float RectF::getBottom(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "bottom"); + static auto javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "bottom"); return rectf.Get(env, field); } void RectF::registerNative(jni::JNIEnv& env) { - // Lookup the class - RectF::javaClass = *jni::Class<RectF>::Find(env).NewGlobalRef(env).release(); + jni::Class<RectF>::Singleton(env); } -jni::Class<RectF> 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 0f3a7756d5..db836e78ba 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<RectF>); - static jni::Class<RectF> 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 e8852d77e9..333b402aa0 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> JsonArray::New(jni::JNIEnv& env, const std::vector<mapbox::geometry::value>& values){ - static auto constructor = JsonArray::javaClass.GetConstructor(env); - static auto addMethod = JsonArray::javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add"); + static auto javaClass = jni::Class<JsonArray>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod<void (jni::Object<JsonElement>)>(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<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv& env, const std::vector<mapbox::geometry::value> values; if (jsonArray) { - static auto getMethod = JsonArray::javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get"); - static auto sizeMethod = JsonArray::javaClass.GetMethod<jni::jint ()>(env, "size"); + static auto javaClass = jni::Class<JsonArray>::Singleton(env); + static auto getMethod = javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get"); + static auto sizeMethod = javaClass.GetMethod<jni::jint ()>(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<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv& env, const } void JsonArray::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class<JsonArray>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonArray>::Singleton(env); } -jni::Class<JsonArray> 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 c9ae98692f..e74b92176f 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 <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #include <jni/jni.hpp> @@ -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<JsonArray> New(jni::JNIEnv&, const std::vector<mapbox::geometry::value>&); - static std::vector<mapbox::geometry::value> convert(JNIEnv&, jni::Object<JsonArray>); - static jni::Class<JsonArray> 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 5eaaf531f4..d5304ed674 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<JsonElement> operator()(const JsonPrimitive::value value) const { - return jni::Cast(env, JsonPrimitive::New(env, value), JsonElement::javaClass); + return JsonPrimitive::New(env, value); } jni::Object<JsonElement> operator()(const std::vector<mapbox::geometry::value> &values) const { - return jni::Cast(env, JsonArray::New(env, values), JsonElement::javaClass); + return JsonArray::New(env, values); } jni::Object<JsonElement> operator()(const std::unordered_map<std::string, mapbox::geometry::value> &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<JsonE if (jsonElement) { if (isJsonPrimitive(env, jsonElement)) { - auto primitive = JsonPrimitive::convert(env, jni::Cast(env, jsonElement, JsonPrimitive::javaClass)); + static auto primitiveClass = jni::Class<JsonPrimitive>::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<JsonObject>::Singleton(env); + mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, objectClass, jsonElement)); value = mapbox::util::recursive_wrapper<std::unordered_map<std::string, mapbox::geometry::value>> { map } ; } else if (isJsonArray(env, jsonElement)) { - value = JsonArray::convert(env, jni::Cast(env, jsonElement, JsonArray::javaClass)); + static auto arrayClass = jni::Class<JsonArray>::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<JsonE } bool JsonElement::isJsonObject(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonObject"); + static auto javaClass = jni::Class<JsonElement>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isJsonObject"); return jsonElement.Call(env, method); } bool JsonElement::isJsonArray(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonArray"); + static auto javaClass = jni::Class<JsonElement>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isJsonArray"); return jsonElement.Call(env, method); } bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive"); + static auto javaClass = jni::Class<JsonElement>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive"); return jsonElement.Call(env, method); } bool JsonElement::isJsonNull(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonNull"); + static auto javaClass = jni::Class<JsonElement>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isJsonNull"); return jsonElement.Call(env, method); } void JsonElement::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<JsonElement>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonElement>::Singleton(env); } -jni::Class<JsonElement> 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 d850caa526..5c68934871 100644 --- a/platform/android/src/gson/json_element.hpp +++ b/platform/android/src/gson/json_element.hpp @@ -1,7 +1,6 @@ #pragma once #include <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #include <jni/jni.hpp> @@ -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<JsonElement> New(jni::JNIEnv&, const mapbox::geometry::value&); - static mapbox::geometry::value convert(JNIEnv&, jni::Object<JsonElement>); static bool isJsonObject(JNIEnv&, jni::Object<JsonElement>); - static bool isJsonArray(JNIEnv&, jni::Object<JsonElement>); - static bool isJsonPrimitive(JNIEnv&, jni::Object<JsonElement>); - static bool isJsonNull(JNIEnv&, jni::Object<JsonElement>); - static jni::Class<JsonElement> 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 61b55f8b9e..4a2ec07563 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> JsonObject::New(jni::JNIEnv& env, const std::unordered_map<std::string, mapbox::geometry::value>& values) { - static auto constructor = JsonObject::javaClass.GetConstructor(env); - static auto addMethod = JsonObject::javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add"); + static auto javaClass = jni::Class<JsonObject>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add"); - jni::Object<JsonObject> jsonObject = JsonObject::javaClass.New(env, constructor); + jni::Object<JsonObject> jsonObject = javaClass.New(env, constructor); for (auto &item : values) { - jni::Object<JsonElement> jsonElement = JsonElement::New(env, item.second); - jni::String key = jni::Make<jni::String>(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<jni::String>(env, item.first)), + *jni::SeizeLocal(env, JsonElement::New(env, item.second))); } return jsonObject; @@ -29,32 +28,22 @@ jni::Object<JsonObject> JsonObject::New(jni::JNIEnv& env, const std::unordered_m template <typename F> // void (jni::String, jni::Object<gson::JsonElement>) static void iterateEntrySet(jni::JNIEnv& env, jni::Object<JsonObject> jsonObject, F callback) { // Get Set<Map.Entry<String, JsonElement>> - static auto method = JsonObject::javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet"); - auto entrySet = jsonObject.Call(env, method); - jni::Array<jni::Object<java::util::Map::Entry>> entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, entrySet); + static auto javaClass = jni::Class<JsonObject>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet"); - size_t size = entryArray.Length(env); + auto entryArray = + jni::SeizeLocal(env, java::util::Set::toArray<java::util::Map::Entry>(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<jni::ObjectTag>(env, entry); - auto jKeyString = jni::String(reinterpret_cast<jni::jstring*>(jKey.Get())); - auto jValue = java::util::Map::Entry::getValue<gson::JsonElement>(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<jni::StringTag>(env, *entry)), + *jni::SeizeLocal(env, java::util::Map::Entry::getValue<gson::JsonElement>(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> 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<JsonObject>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonObject>::Singleton(env); } -jni::Class<JsonObject> 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 4bc61e51a2..85e8828d91 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 <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #include <jni/jni.hpp> @@ -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<JsonObject> New(jni::JNIEnv&, const std::unordered_map<std::string, mapbox::geometry::value>&); - static mapbox::geometry::property_map convert(JNIEnv&, jni::Object<JsonObject>); - static jni::Class<JsonObject> 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 4e171c4845..2b03629135 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<JsonPrimitive> operator()(const std::string value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::String>(env); - auto jvalue = jni::Make<jni::String>(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, jvalue); - jni::DeleteLocalRef(env, jvalue); - return jsonPrimitive; + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::String>(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, value))); } /** * Create a primitive containing a number value with type double */ jni::Object<JsonPrimitive> operator()(const double value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(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<JsonPrimitive>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::Number>(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<JsonPrimitive> operator()(const int64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(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<JsonPrimitive>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::Number>(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<JsonPrimitive> operator()(const uint64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(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<JsonPrimitive>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::Number>(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<JsonPrimitive> operator()(const bool value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Boolean>>(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<JsonPrimitive>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::Boolean>(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<JsonPr } bool JsonPrimitive::isBoolean(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isBoolean"); + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isBoolean"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::isString(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isString"); + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isString"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isNumber"); + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "isNumber"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean"); + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean"); return jsonPrimitive.Call(env, method); } std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::String ()>(env, "getAsString"); - auto jString = jsonPrimitive.Call(env, method); - auto string = jni::Make<std::string>(env, jString); - jni::DeleteLocalRef(env, jString); - return string; + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "getAsString"); + return jni::Make<std::string>(env, *jni::SeizeLocal(env, jsonPrimitive.Call(env, method))); } double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jdouble ()>(env, "getAsDouble"); + static auto javaClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jdouble ()>(env, "getAsDouble"); return jsonPrimitive.Call(env, method); } void JsonPrimitive::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<JsonPrimitive>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonPrimitive>::Singleton(env); } -jni::Class<JsonPrimitive> 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 c418e0ebe8..d9e90507f9 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 <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #include <jni/jni.hpp> @@ -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<mapbox::geometry::null_value_t, bool, uint64_t, int64_t, double, std::string>; static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; static jni::Object<JsonPrimitive> New(jni::JNIEnv&, const value&); - static value convert(JNIEnv&, jni::Object<JsonPrimitive>); static bool isBoolean(JNIEnv&, jni::Object<JsonPrimitive>); - static bool isString(JNIEnv&, jni::Object<JsonPrimitive>); - static bool isNumber(JNIEnv&, jni::Object<JsonPrimitive>); static bool getAsBoolean(JNIEnv&, jni::Object<JsonPrimitive>); - static std::string getAsString(JNIEnv&, jni::Object<JsonPrimitive>); - static double getAsDouble(JNIEnv&, jni::Object<JsonPrimitive>); - static jni::Class<JsonPrimitive> 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 fc7ffbec8c..6b359aab8c 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<jni::jbyte> body); - static jni::Class<HTTPRequest> javaClass; - jni::UniqueObject<HTTPRequest> javaRequest; + jni::Global<jni::Object<HTTPRequest>> javaRequest; private: Resource resource; @@ -52,16 +51,14 @@ private: static const int permanentError = 2; }; -jni::Class<HTTPRequest> HTTPRequest::javaClass; - namespace android { void RegisterNativeHTTPRequest(jni::JNIEnv& env) { - HTTPRequest::javaClass = *jni::Class<HTTPRequest>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<HTTPRequest>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) - jni::RegisterNativePeer<HTTPRequest>(env, HTTPRequest::javaClass, "nativePtr", + jni::RegisterNativePeer<HTTPRequest>(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<HTTPRequest>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::jlong, jni::String, jni::String, jni::String>(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<HTTPRequest>::Singleton(*env); static auto cancel = javaClass.GetMethod<void ()>(*env, "cancel"); javaRequest->Call(*env, cancel); diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp index 0456381578..a85e9aeaa2 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<jni::jbyte>::New(*env, string.size()); - jni::SetArrayRegion(*env, *array, 0, string.size(), + auto array = jni::SeizeLocal(*env, jni::Array<jni::jbyte>::New(*env, string.size())); + jni::SetArrayRegion(*env, **array, 0, string.size(), reinterpret_cast<const signed char*>(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 3c95737169..0000000000 --- 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> Float::valueOf(JNIEnv &env, jfloat value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Float> (jni::jfloat)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Float::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Float>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Float> Float::javaClass; - -// Long - -jni::Object<Long> Long::valueOf(JNIEnv &env, jlong value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Long> (jni::jlong)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Long::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Long>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Long> Long::javaClass; - -// Double - -jni::Object<Double> Double::valueOf(JNIEnv &env, jdouble value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Double> (jni::jdouble)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Double::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Double>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Double> Double::javaClass; - -// Boolean - -jni::Object<Boolean> Boolean::valueOf(JNIEnv &env, jboolean value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Boolean> (jni::jboolean)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Boolean::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Boolean>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Boolean> Boolean::javaClass; - -// Number - -void Number::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Number>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Number> 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 981e3b14b7..0000000000 --- a/platform/android/src/java/lang.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include <jni/jni.hpp> -#include <mbgl/util/noncopyable.hpp> - -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<Float> valueOf(JNIEnv&, jfloat); - - static jni::Class<Float> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Double : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Double"; }; - - static jni::Object<Double> valueOf(JNIEnv&, jdouble); - - static jni::Class<Double> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Long : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Long"; }; - - static jni::Object<Long> valueOf(JNIEnv&, jlong); - - static jni::Class<Long> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Boolean : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Boolean"; }; - - static jni::Object<Boolean> valueOf(JNIEnv&, jboolean); - - static jni::Class<Boolean> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Number : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Number"; }; - - static jni::Class<Number> 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 89c4c77794..b3aebb36cc 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> Arrays::javaClass; -jni::Class<List> List::javaClass; -jni::Class<Set> Set::javaClass; -jni::Class<Map> Map::javaClass; -jni::Class<Map::Entry> Map::Entry::javaClass; - void registerNative(jni::JNIEnv& env) { - Arrays::javaClass = *jni::Class<Arrays>::Find(env).NewGlobalRef(env).release(); - List::javaClass = *jni::Class<List>::Find(env).NewGlobalRef(env).release(); - Set::javaClass = *jni::Class<Set>::Find(env).NewGlobalRef(env).release(); - Map::javaClass = *jni::Class<Map>::Find(env).NewGlobalRef(env).release(); - Map::Entry::javaClass = *jni::Class<Map::Entry>::Find(env).NewGlobalRef(env).release(); + jni::Class<Arrays>::Singleton(env); + jni::Class<List>::Singleton(env); + jni::Class<Set>::Singleton(env); + jni::Class<Map>::Singleton(env); + jni::Class<Map::Entry>::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 c6b07acac5..808f14be15 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<class T> static jni::Array<jni::Object<T>> toArray(jni::JNIEnv& env, jni::Object<List> list) { - static auto toArray = List::javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); + static auto javaClass = jni::Class<List>::Singleton(env); + static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); return (jni::Array<jni::Object<T>>) list.Call(env, toArray); }; - - static jni::Class<List> javaClass; - }; class Arrays : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Arrays"; }; template <class T> static jni::Object<List> asList(jni::JNIEnv& env, jni::Array<jni::Object<T>> array) { - static auto asList = Arrays::javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList"); + static auto javaClass = jni::Class<Arrays>::Singleton(env); + static auto asList = javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList"); return javaClass.Call(env, asList, (jni::Array<jni::Object<>>) array); } - - static jni::Class<Arrays> javaClass; - }; class Set : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Set"; }; template<class T> static jni::Array<jni::Object<T>> toArray(jni::JNIEnv& env, jni::Object<Set> list) { - static auto toArray = Set::javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); + static auto javaClass = jni::Class<Set>::Singleton(env); + static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); return (jni::Array<jni::Object<T>>) list.Call(env, toArray); }; - - static jni::Class<Set> 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 <class T> static jni::Object<T> getKey(jni::JNIEnv& env, jni::Object<Entry> entry) { - static auto method = Entry::javaClass.GetMethod<jni::Object<> ()>(env, "getKey"); - return (jni::Object<T>) entry.Call(env, method); + static auto javaClass = jni::Class<Map::Entry>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getKey"); + return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method)); } template <class T> static jni::Object<T> getValue(jni::JNIEnv& env, jni::Object<Entry> entry) { - static auto method = Entry::javaClass.GetMethod<jni::Object<> ()>(env, "getValue"); - return (jni::Object<T>) entry.Call(env, method).Get(); + static auto javaClass = jni::Class<Map::Entry>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getValue"); + return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method)); } - - static jni::Class<Entry> javaClass; }; - - static constexpr auto Name() { return "java/util/Map"; }; - - static jni::Class<Map> 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 872d8bc89a..abea7f4502 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 7239e361a7..b865ee9f8b 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)); } } }; +struct GenericWeakGlobalRefDeleter { + void operator()(jni::jobject* p) const { + if (p) { + AttachEnv()->DeleteWeakGlobalRef(jni::Unwrap(p)); + } + } +}; -template < class TagType > -class GenericWeakObjectRefDeleter; - -template < class TagType = jni::ObjectTag > -using GenericUniqueWeakObject = std::unique_ptr< const jni::Object<TagType>, GenericWeakObjectRefDeleter<TagType> >; +template < class T > +using GenericGlobal = jni::UniquePointerlike< T, GenericGlobalRefDeleter >; -template < class TagType > -class GenericWeakObjectRefDeleter -{ -public: - using pointer = jni::PointerToValue< jni::Object<TagType> >; +template < class T > +using GenericWeak = jni::UniquePointerlike< T, GenericWeakGlobalRefDeleter >; - void operator()(pointer p) const - { - if (p) - { - auto env = AttachEnv(); - env->DeleteWeakGlobalRef(jni::Unwrap(p->Get())); - } - } +template < class T > +GenericGlobal<T> SeizeGenericGlobal(T&& t) { + return GenericGlobal<T>(std::move(t), GenericGlobalRefDeleter()); }; -template < class TagType > -GenericUniqueWeakObject<TagType> SeizeGenericWeakRef(JNIEnv&, jni::Object<TagType>&& object) -{ - return GenericUniqueWeakObject<TagType>(jni::PointerToValue<jni::Object<TagType>>(std::move(object)), GenericWeakObjectRefDeleter<TagType>()); +template < class T > +GenericWeak<T> SeizeGenericWeak(T&& t) { + return GenericWeak<T>(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 00fc4a1933..0000000000 --- a/platform/android/src/jni/local_object.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <jni/jni.hpp> - -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<T> NewLocalObject(JNIEnv& env, T* t) { - return LocalObject<T>(t, LocalRefDeleter(env)); - } -} diff --git a/platform/android/src/logger.cpp b/platform/android/src/logger.cpp index 0ade914604..ddc4d84525 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<Logger>::Find(env).NewGlobalRef(env).release(); + jni::Class<Logger>::Singleton(env); } -jni::Class<Logger> Logger::_class; - void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) { - auto tag = jni::Make<jni::String>(env, "Mbgl"); - auto message = jni::Make<jni::String>(env, msg); + static auto _class = jni::Class<Logger>::Singleton(env); + + auto tag = jni::SeizeLocal(env, jni::Make<jni::String>(env, "Mbgl")); + auto message = jni::SeizeLocal(env, jni::Make<jni::String>(env, msg)); using Signature = void(jni::String, jni::String); if (severity == EventSeverity::Debug) { auto static debug = _class.GetStaticMethod<Signature>(env, "d"); - _class.Call(env, debug, tag, message); + _class.Call(env, debug, *tag, *message); } else if (severity == EventSeverity::Info) { auto static info = _class.GetStaticMethod<Signature>(env, "i"); - _class.Call(env, info, tag, message); + _class.Call(env, info, *tag, *message); } else if(severity == EventSeverity::Warning) { auto static warning = _class.GetStaticMethod<Signature>(env, "w"); - _class.Call(env, warning, tag, message); + _class.Call(env, warning, *tag, *message); } else { auto static error = _class.GetStaticMethod<Signature>(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 d4805fccd8..7481ecb265 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<Logger> _class; }; } // namespace android diff --git a/platform/android/src/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp index 01ffc6530b..5700341d65 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> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { - static auto constructor = CameraPosition::javaClass.GetConstructor<jni::Object<LatLng>, double, double, double>(env); + static auto javaClass = jni::Class<CameraPosition>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::Object<LatLng>, double, double, double>(env); // wrap LatLng values coming from core auto center = options.center.value(); @@ -24,18 +25,17 @@ jni::Object<CameraPosition> 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<CameraPosition> position) { - static auto bearing = CameraPosition::javaClass.GetField<jni::jdouble>(env, "bearing"); - static auto target = CameraPosition::javaClass.GetField<jni::Object<LatLng>>(env, "target"); - static auto tilt = CameraPosition::javaClass.GetField<jni::jdouble>(env, "tilt"); - static auto zoom = CameraPosition::javaClass.GetField<jni::jdouble>(env, "zoom"); + static auto javaClass = jni::Class<CameraPosition>::Singleton(env); + static auto bearing = javaClass.GetField<jni::jdouble>(env, "bearing"); + static auto target = javaClass.GetField<jni::Object<LatLng>>(env, "target"); + static auto tilt = javaClass.GetField<jni::jdouble>(env, "tilt"); + static auto zoom = javaClass.GetField<jni::jdouble>(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<CameraPosition>::Find(env).NewGlobalRef(env).release(); + jni::Class<CameraPosition>::Singleton(env); } -jni::Class<CameraPosition> 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 4eee8be758..d577811915 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<CameraPosition> New(jni::JNIEnv&, mbgl::CameraOptions); static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, jni::Object<CameraPosition>); - static jni::Class<CameraPosition> 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 ce89e22d7a..ee3c7012a7 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> image) { - static auto widthField = Image::javaClass.GetField<jni::jint>(env, "width"); - static auto heightField = Image::javaClass.GetField<jni::jint>(env, "height"); - static auto pixelRatioField = Image::javaClass.GetField<jni::jfloat>(env, "pixelRatio"); - static auto bufferField = Image::javaClass.GetField<jni::Array<jbyte>>(env, "buffer"); - static auto nameField = Image::javaClass.GetField<jni::String>(env, "name"); - static auto sdfField = Image::javaClass.GetField<jni::jboolean>(env, "sdf"); + static auto javaClass = jni::Class<Image>::Singleton(env); + static auto widthField = javaClass.GetField<jni::jint>(env, "width"); + static auto heightField = javaClass.GetField<jni::jint>(env, "height"); + static auto pixelRatioField = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); + static auto bufferField = javaClass.GetField<jni::Array<jbyte>>(env, "buffer"); + static auto nameField = javaClass.GetField<jni::String>(env, "name"); + static auto sdfField = javaClass.GetField<jni::jboolean>(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<std::string>(env, jName); + auto pixels = jni::SeizeLocal(env, image.Get(env, bufferField)); + auto name = jni::Make<std::string>(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<uint32_t>(width), static_cast<uint32_t>(height) }); if (premultipliedImage.bytes() != uint32_t(size)) { throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch"); } - jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get())); - jni::DeleteLocalRef(env, pixels); + jni::GetArrayRegion(env, **pixels, 0, size, reinterpret_cast<jbyte*>(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<Image>::Find(env).NewGlobalRef(env).release(); + jni::Class<Image>::Singleton(env); } -jni::Class<Image> Image::javaClass; - - } // namespace android } // namespace mb - diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp index 1513e13ee7..17ed4cbef8 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<Image>); - static jni::Class<Image> 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 ba6fdc63b0..1f8c82ac05 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<MapRenderer> obj, jni::Object<FileSource> _fileSource, jni::jfloat pixelRatio_, jni::String programCacheDir_, jni::String localIdeographFontFamily_) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object<MapRenderer>(jni::NewWeakGlobalRef(_env, obj.Get()).release()))), pixelRatio(pixelRatio_) + : javaPeer(SeizeGenericWeak(obj.NewWeakGlobalRef(_env).release())) + , pixelRatio(pixelRatio_) , fileSource(FileSource::getDefaultFileSource(_env, _fileSource)) , programCacheDir(jni::Make<std::string>(_env, programCacheDir_)) , localIdeographFontFamily(localIdeographFontFamily_ == nullptr ? optional<std::string>{} : jni::Make<std::string>(_env, localIdeographFontFamily_ )) @@ -52,6 +53,7 @@ void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) { auto peer = runnable->peer(); // Queue the event on the Java Peer + static auto javaClass = jni::Class<MapRenderer>::Singleton(*_env); static auto queueEvent = javaClass.GetMethod<void( jni::Object<MapRendererRunnable>)>(*_env, "queueEvent"); javaPeer->Call(*_env, queueEvent, *peer); @@ -62,6 +64,7 @@ void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) { void MapRenderer::requestRender() { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class<MapRenderer>::Singleton(*_env); static auto onInvalidate = javaClass.GetMethod<void()>(*_env, "requestRender"); javaPeer->Call(*_env, onInvalidate); } @@ -179,16 +182,14 @@ void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) { // Static methods // -jni::Class<MapRenderer> MapRenderer::javaClass; - void MapRenderer::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRenderer::javaClass = *jni::Class<MapRenderer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<MapRenderer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<MapRenderer>(env, MapRenderer::javaClass, "nativePtr", + jni::RegisterNativePeer<MapRenderer>(env, javaClass, "nativePtr", std::make_unique<MapRenderer, JNIEnv&, jni::Object<MapRenderer>, jni::Object<FileSource>, 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<MapRenderer> jObject) { - static auto field = MapRenderer::javaClass.GetField<jlong>(env, "nativePtr"); + static auto javaClass = jni::Class<MapRenderer>::Singleton(env); + static auto field = javaClass.GetField<jlong>(env, "nativePtr"); MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(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 97d2db4a91..6fcf2fee71 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<MapRenderer> javaClass; - static void registerNative(jni::JNIEnv&); static MapRenderer& getNativePeer(JNIEnv&, jni::Object<MapRenderer>); @@ -99,7 +97,7 @@ private: void onSurfaceChanged(JNIEnv&, jint width, jint height); private: - GenericUniqueWeakObject<MapRenderer> javaPeer; + GenericWeak<jni::Object<MapRenderer>> javaPeer; float pixelRatio; DefaultFileSource& fileSource; diff --git a/platform/android/src/map_renderer_runnable.cpp b/platform/android/src/map_renderer_runnable.cpp index 4dc6611c40..1bfccebd2d 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<Mailbox // Not using a weak reference here as this might oerflow // the weak reference table on some devices jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 5); + static auto javaClass = jni::Class<MapRendererRunnable>::Singleton(env); static auto constructor = javaClass.GetConstructor<jlong>(env); auto instance = javaClass.New(env, constructor, reinterpret_cast<jlong>(this)); javaPeer = instance.NewGlobalRef(env); @@ -23,23 +24,21 @@ void MapRendererRunnable::run(jni::JNIEnv&) { Mailbox::maybeReceive(mailbox); } -jni::UniqueObject<MapRendererRunnable> MapRendererRunnable::peer() { +jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() { return std::move(javaPeer); } // Static methods // -jni::Class<MapRendererRunnable> MapRendererRunnable::javaClass; - void MapRendererRunnable::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRendererRunnable::javaClass = *jni::Class<MapRendererRunnable>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<MapRendererRunnable>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) jni::RegisterNativePeer<MapRendererRunnable>( env, - MapRendererRunnable::javaClass, + javaClass, "nativePtr", std::make_unique<MapRendererRunnable, JNIEnv&>, "nativeInitialize", diff --git a/platform/android/src/map_renderer_runnable.hpp b/platform/android/src/map_renderer_runnable.hpp index 46fb028d26..21c4369b69 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<MapRendererRunnable> javaClass; - static void registerNative(jni::JNIEnv&); MapRendererRunnable(jni::JNIEnv&, std::weak_ptr<Mailbox>); @@ -38,10 +36,10 @@ public: void run(jni::JNIEnv&); // Transfers ownership of the Peer object to the caller - jni::UniqueObject<MapRendererRunnable> peer(); + jni::Global<jni::Object<MapRendererRunnable>> peer(); private: - jni::UniqueObject<MapRendererRunnable> javaPeer; + jni::Global<jni::Object<MapRendererRunnable>> javaPeer; std::weak_ptr<Mailbox> mailbox; }; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 8c76332b39..26814fd6b8 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<NativeMapView>::Singleton(*_env); static auto onMapChanged = javaClass.GetMethod<void (int)>(*_env, "onMapChanged"); javaPeer->Call(*_env, onMapChanged, (int) change); } @@ -376,9 +377,7 @@ void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array<jni::Obje latLngs.reserve(count); for (std::size_t i = 0; i < count; i++) { - auto latLng = coordinates.Get(env, i); - latLngs.push_back(LatLng::getLatLng(env, latLng)); - jni::DeleteLocalRef(env, latLng); + latLngs.push_back(LatLng::getLatLng(env, *jni::SeizeLocal(env, coordinates.Get(env, i)))); } mbgl::EdgeInsets mbglInsets = { RectF::getTop(env, padding), RectF::getLeft(env, padding), RectF::getBottom(env, padding), RectF::getRight(env, padding) }; @@ -409,6 +408,7 @@ void NativeMapView::scheduleSnapshot(jni::JNIEnv&) { auto bitmap = Bitmap::CreateBitmap(*_env, std::move(image)); // invoke Mapview#OnSnapshotReady + static auto javaClass = jni::Class<NativeMapView>::Singleton(*_env); static auto onSnapshotReady = javaClass.GetMethod<void (jni::Object<Bitmap>)>(*_env, "onSnapshotReady"); javaPeer->Call(*_env, onSnapshotReady, bitmap); }); @@ -436,13 +436,11 @@ jni::Array<jni::jlong> NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array<jn ids.reserve(len); for (std::size_t i = 0; i < len; i++) { - jni::Object<Marker> 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<jni::jlong>::New(env, len); @@ -505,12 +503,8 @@ jni::Array<jlong> NativeMapView::addPolylines(JNIEnv& env, jni::Array<jni::Objec ids.reserve(len); for (std::size_t i = 0; i < len; i++) { - auto polyline = polylines.Get(env, i); - - mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, polyline); + mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, *jni::SeizeLocal(env, polylines.Get(env, i))); ids.push_back(map->addAnnotation(annotation)); - - jni::DeleteLocalRef(env, polyline); } auto result = jni::Array<jni::jlong>::New(env, len); @@ -528,12 +522,8 @@ jni::Array<jlong> NativeMapView::addPolygons(JNIEnv& env, jni::Array<jni::Object ids.reserve(len); for (std::size_t i = 0; i < len; i++) { - auto polygon = polygons.Get(env, i); - - mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygon); + mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, *jni::SeizeLocal(env, polygons.Get(env, i))); ids.push_back(map->addAnnotation(annotation)); - - jni::DeleteLocalRef(env, polygon); } auto result = jni::Array<jni::jlong>::New(env, len); @@ -670,7 +660,7 @@ jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesFo return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>( env, - rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); + rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, @@ -690,7 +680,7 @@ jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesFo return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>( env, - rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); + rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } jni::Object<Light> NativeMapView::getLight(JNIEnv& env) { @@ -708,12 +698,10 @@ jni::Array<jni::Object<Layer>> NativeMapView::getLayers(JNIEnv& env) { std::vector<style::Layer*> layers = map->getStyle().getLayers(); // Convert - jni::Array<jni::Object<Layer>> jLayers = jni::Array<jni::Object<Layer>>::New(env, layers.size(), Layer::javaClass); + jni::Array<jni::Object<Layer>> jLayers = jni::Array<jni::Object<Layer>>::New(env, layers.size()); int index = 0; for (auto layer : layers) { - auto jLayer = jni::Object<Layer>(createJavaLayerPeer(env, *map, *layer)); - jLayers.Set(env, index, jLayer); - jni::DeleteLocalRef(env, jLayer); + jLayers.Set(env, index, *jni::SeizeLocal(env, jni::Object<Layer>(createJavaLayerPeer(env, *map, *layer)))); index++; } @@ -855,7 +843,7 @@ jni::Array<jni::Object<Source>> NativeMapView::getSources(JNIEnv& env) { std::vector<style::Source*> sources = map->getStyle().getSources(); // Convert - jni::Array<jni::Object<Source>> jSources = jni::Array<jni::Object<Source>>::New(env, sources.size(), Source::javaClass); + jni::Array<jni::Object<Source>> jSources = jni::Array<jni::Object<Source>>::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<jni::Object<mbgl::android: std::size_t len = jimages.Length(env); for (std::size_t i = 0; i < len; i++) { - jni::Object<mbgl::android::Image> 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<mbgl::style::Image>(image)); - jni::DeleteLocalRef(env, jimage); } } @@ -948,16 +934,14 @@ mbgl::Map& NativeMapView::getMap() { // Static methods // -jni::Class<NativeMapView> NativeMapView::javaClass; - void NativeMapView::registerNative(jni::JNIEnv& env) { // Lookup the class - NativeMapView::javaClass = *jni::Class<NativeMapView>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<NativeMapView>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<NativeMapView>(env, NativeMapView::javaClass, "nativePtr", + jni::RegisterNativePeer<NativeMapView>(env, javaClass, "nativePtr", std::make_unique<NativeMapView, JNIEnv&, jni::Object<NativeMapView>, jni::Object<FileSource>, jni::Object<MapRenderer>, jni::jfloat>, "nativeInitialize", "nativeDestroy", diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index e577670323..d398b39bf7 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<NativeMapView> javaClass; - static void registerNative(jni::JNIEnv&); NativeMapView(jni::JNIEnv&, @@ -254,7 +252,7 @@ private: std::unique_ptr<AndroidRendererFrontend> rendererFrontend; JavaVM *vm = nullptr; - jni::UniqueWeakObject<NativeMapView> javaPeer; + jni::Weak<jni::Object<NativeMapView>> javaPeer; MapRenderer& mapRenderer; diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index e96ed7e4d2..263f7b9d8b 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<FileSourc // list regions fileSource.listOfflineRegions([ //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<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> 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<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable { // Reattach, the callback comes from a different thread @@ -77,13 +77,11 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, }); } -jni::Class<OfflineManager> OfflineManager::javaClass; - void OfflineManager::registerNative(jni::JNIEnv& env) { - OfflineManager::ListOfflineRegionsCallback::registerNative(env); - OfflineManager::CreateOfflineRegionCallback::registerNative(env); + jni::Class<ListOfflineRegionsCallback>::Singleton(env); + jni::Class<CreateOfflineRegionCallback>::Singleton(env); - javaClass = *jni::Class<OfflineManager>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<OfflineManager>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) @@ -101,37 +99,28 @@ void OfflineManager::registerNative(jni::JNIEnv& env) { void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env, jni::Object<OfflineManager::ListOfflineRegionsCallback> callback, std::exception_ptr error) { + static auto javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, mbgl::util::toString(error)))); } void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env, jni::Object<FileSource> jFileSource, jni::Object<OfflineManager::ListOfflineRegionsCallback> callback, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) { - //Convert the regions to java peer objects + static auto javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env); + static auto method = javaClass.GetMethod<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onList"); + std::size_t index = 0; - auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions->size(), OfflineRegion::javaClass); + auto jregions = jni::SeizeLocal(env, jni::Array<jni::Object<OfflineRegion>>::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<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onList"); - callback.Call(env, method, jregions); - jni::DeleteLocalRef(env, jregions); -} - -jni::Class<OfflineManager::ListOfflineRegionsCallback> OfflineManager::ListOfflineRegionsCallback::javaClass; - -void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineManager::ListOfflineRegionsCallback>::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<OfflineManager::CreateOfflineRegionCallback> callback, std::exception_ptr error) { + static auto javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, mbgl::util::toString(error)))); } void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env, jni::Object<FileSource> jFileSource, jni::Object<OfflineManager::CreateOfflineRegionCallback> callback, mbgl::optional<mbgl::OfflineRegion> region) { - // Convert the region to java peer object - auto jregion = OfflineRegion::New(env, jFileSource, std::move(*region)); - - // Trigger callback + static auto javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegion>)>(env, "onCreate"); - callback.Call(env, method, jregion); - jni::DeleteLocalRef(env, jregion); -} - -jni::Class<OfflineManager::CreateOfflineRegionCallback> OfflineManager::CreateOfflineRegionCallback::javaClass; -void OfflineManager::CreateOfflineRegionCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineManager::CreateOfflineRegionCallback>::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 9ae2714ca2..43f5045c71 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -26,10 +26,6 @@ public: jni::Object<FileSource>, jni::Object<OfflineManager::ListOfflineRegionsCallback>, mbgl::optional<std::vector<mbgl::OfflineRegion>>); - - static jni::Class<OfflineManager::ListOfflineRegionsCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; class CreateOfflineRegionCallback { @@ -42,16 +38,10 @@ public: jni::Object<FileSource>, jni::Object<OfflineManager::CreateOfflineRegionCallback>, mbgl::optional<mbgl::OfflineRegion>); - - static jni::Class<OfflineManager::CreateOfflineRegionCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; }; - static jni::Class<OfflineManager> javaClass; - static void registerNative(jni::JNIEnv&); OfflineManager(jni::JNIEnv&, jni::Object<FileSource>); diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 5ed37eda73..949377e221 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<Offl // Define the observer class Observer : public mbgl::OfflineRegionObserver { public: - Observer(jni::UniqueObject<OfflineRegion::OfflineRegionObserver>&& callback_) + Observer(jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>>&& 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<Offl // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); - // Status object - auto jStatus = OfflineRegionStatus::New(*env, status); + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged"); - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod<void (jni::Object<OfflineRegionStatus>)>(*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); - - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError"); - callback.Call(*env, method, jError); + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError"); - // 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<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded"); + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded"); + callback.Call(*env, method, jlong(limit)); } @@ -106,7 +96,7 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<Offlin fileSource.getOfflineRegionStatus(*region, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> 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<OfflineRe // Delete fileSource.deleteOfflineRegion(std::move(*region), [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr<jni::jobject>(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::Array<jn fileSource.updateOfflineMetadata(region->getID(), metadata, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> 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<jn jni::Object<OfflineRegion> OfflineRegion::New(jni::JNIEnv& env, jni::Object<FileSource> 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<OfflineRegionDefinition>( *OfflineTilePyramidRegionDefinition::New(env, def)); }, [&](const mbgl::OfflineGeometryRegionDefinition def) { return jni::Object<OfflineRegionDefinition>( *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<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env); - auto jregion = OfflineRegion::javaClass.New(env, constructor, - reinterpret_cast<jni::jlong>(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); + static auto javaClass = jni::Class<OfflineRegion>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong, jni::Object<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env); - return jregion; + return javaClass.New(env, constructor, + reinterpret_cast<jni::jlong>(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap + jFileSource, + jni::jlong(region.getID()), + *definition, + *jni::SeizeLocal(env, OfflineRegion::metadata(env, region.getMetadata()))); } jni::Array<jni::jbyte> 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> 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<OfflineRegionObserver>::Singleton(env); + jni::Class<OfflineRegionStatusCallback>::Singleton(env); + jni::Class<OfflineRegionDeleteCallback>::Singleton(env); + jni::Class<OfflineRegionUpdateMetadataCallback>::Singleton(env); - javaClass = *jni::Class<OfflineRegion>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<OfflineRegion>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) @@ -227,94 +211,68 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { // OfflineRegionObserver // -jni::Class<OfflineRegion::OfflineRegionObserver> OfflineRegion::OfflineRegionObserver::javaClass; - -void OfflineRegion::OfflineRegionObserver::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegion::OfflineRegionObserver>::Find(env).NewGlobalRef(env).release(); -} - // OfflineRegionStatusCallback // -jni::Class<OfflineRegion::OfflineRegionStatusCallback> OfflineRegion::OfflineRegionStatusCallback::javaClass; - -void OfflineRegion::OfflineRegionStatusCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionStatusCallback>::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, std::exception_ptr error) { + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, mbgl::optional<mbgl::OfflineRegionStatus> status) { - //Convert to java peer object - auto jStatus = OfflineRegionStatus::New(env, std::move(*status)); - - // Trigger callback + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(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> OfflineRegion::OfflineRegionDeleteCallback::javaClass; - -void OfflineRegion::OfflineRegionDeleteCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionDeleteCallback>::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback, std::exception_ptr error) { + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback) { // Trigger callback + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env); static auto method = javaClass.GetMethod<void ()>(env, "onDelete"); + callback.Call(env, method); } // OfflineRegionUpdateMetadataCallback // -jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback> OfflineRegion::OfflineRegionUpdateMetadataCallback::javaClass; - -void OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionUpdateMetadataCallback>::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, std::exception_ptr error) { + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make<jni::String>(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, mbgl::optional<mbgl::OfflineRegionMetadata> metadata) { - //Convert to java peer object - auto jMetadata = OfflineRegion::metadata(env, std::move(*metadata)); - - // Trigger callback + static auto javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Array<jni::jbyte>)>(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 c05383a91a..11aecb82a9 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<OfflineRegionObserver> javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionStatusCallback { @@ -30,10 +26,6 @@ public: static void onStatus(jni::JNIEnv&, jni::Object<OfflineRegionStatusCallback>, mbgl::optional<mbgl::OfflineRegionStatus>); - - static jni::Class<OfflineRegionStatusCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionDeleteCallback { @@ -43,10 +35,6 @@ public: static void onError(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>, std::exception_ptr); static void onDelete(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>); - - static jni::Class<OfflineRegionDeleteCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionUpdateMetadataCallback { @@ -58,10 +46,6 @@ public: static void onUpdate(jni::JNIEnv&, jni::Object<OfflineRegionUpdateMetadataCallback>, mbgl::optional<mbgl::OfflineRegionMetadata>); - - static jni::Class<OfflineRegionUpdateMetadataCallback> 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<jni::jbyte>); - static jni::Class<OfflineRegion> 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 a856672902..2a69181f5b 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> OfflineRegionDefinition::javaClass; - void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionDefinition>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineRegionDefinition>::Singleton(env); } mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env, jni::Object<OfflineRegionDefinition> jDefinition) { - - if (jDefinition.IsInstanceOf(env, OfflineTilePyramidRegionDefinition::javaClass)) { + if (jDefinition.IsInstanceOf(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env))) { return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Object<OfflineTilePyramidRegionDefinition>(*jDefinition)); - } else if (jDefinition.IsInstanceOf(env, OfflineGeometryRegionDefinition::javaClass)) { + } else if (jDefinition.IsInstanceOf(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env))) { return OfflineGeometryRegionDefinition::getDefinition(env, jni::Object<OfflineGeometryRegionDefinition>(*jDefinition)); } @@ -31,104 +28,73 @@ mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env // OfflineTilePyramidRegionDefinition // jni::Object<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { - - //Convert objects - auto styleURL = jni::Make<jni::String>(env, definition.styleURL); - auto bounds = LatLngBounds::New(env, definition.bounds); - + static auto javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<LatLngBounds>, 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<jni::String>(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<OfflineTilePyramidRegionDefinition> jDefinition) { // Field references + static auto javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env); static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL"); static auto boundsF = javaClass.GetField<jni::Object<LatLngBounds>>(env, "bounds"); static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom"); static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jBounds = jDefinition.Get(env, boundsF); - - // Create definition - mbgl::OfflineTilePyramidRegionDefinition definition( - jni::Make<std::string>(env, jStyleURL), - LatLngBounds::getLatLngBounds(env, jBounds), + return mbgl::OfflineTilePyramidRegionDefinition( + jni::Make<std::string>(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> OfflineTilePyramidRegionDefinition::javaClass; - void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineTilePyramidRegionDefinition>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env); } // OfflineGeometryRegionDefinition // jni::Object<OfflineGeometryRegionDefinition> OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { - //Convert objects - auto styleURL = jni::Make<jni::String>(env, definition.styleURL); - auto geometry = geojson::Geometry::New(env, definition.geometry); - + static auto javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<geojson::Geometry>, 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<jni::String>(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<OfflineGeometryRegionDefinition> jDefinition) { // Field references + static auto javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env); static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL"); static auto geometryF = javaClass.GetField<jni::Object<geojson::Geometry>>(env, "geometry"); static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom"); static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jGeometry = jDefinition.Get(env, geometryF); - - // Create definition - mbgl::OfflineGeometryRegionDefinition definition( - jni::Make<std::string>(env, jStyleURL), - geojson::Geometry::convert(env, jGeometry), - jDefinition.Get(env, minZoomF), - jDefinition.Get(env, maxZoomF), - jDefinition.Get(env, pixelRatioF) + return mbgl::OfflineGeometryRegionDefinition( + jni::Make<std::string>(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> OfflineGeometryRegionDefinition::javaClass; - void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineGeometryRegionDefinition>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineGeometryRegionDefinition>::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 a9dfb54634..853cc833bf 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<OfflineRegionDefinition> javaClass; - static void registerNative(jni::JNIEnv&); static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, jni::Object<OfflineRegionDefinition> jDefinition); @@ -25,10 +23,7 @@ public: static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineTilePyramidRegionDefinition>); - static jni::Class<OfflineTilePyramidRegionDefinition> javaClass; - static void registerNative(jni::JNIEnv&); - }; class OfflineGeometryRegionDefinition: public OfflineRegionDefinition { @@ -39,10 +34,7 @@ public: static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineGeometryRegionDefinition>); - static jni::Class<OfflineGeometryRegionDefinition> 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 b0a19f934f..02432757d4 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> OfflineRegionError::New(jni::JNIEnv& env, mbgl:: break; } - // Convert - auto jReason = jni::Make<jni::String>(env, reason); - auto jMessage = jni::Make<jni::String>(env, error.message); - - // Create java object + static auto javaClass = jni::Class<OfflineRegionError>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(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<jni::String>(env, reason)), + *jni::SeizeLocal(env, jni::Make<jni::String>(env, error.message))); } -jni::Class<OfflineRegionError> OfflineRegionError::javaClass; - void OfflineRegionError::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionError>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineRegionError>::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 61efaca67e..c51f08a745 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<OfflineRegionError> New(jni::JNIEnv&, mbgl::Response::Error); - static jni::Class<OfflineRegionError> 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 d0bbae124f..0a415bdb5f 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> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl } // Create java object + static auto javaClass = jni::Class<OfflineRegionStatus>::Singleton(env); static auto constructor = javaClass.GetConstructor<jint, jlong, jlong, jlong, jlong, jlong, jboolean>(env); return javaClass.New(env, constructor, downloadState, @@ -29,10 +30,8 @@ jni::Object<OfflineRegionStatus> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl ); } -jni::Class<OfflineRegionStatus> OfflineRegionStatus::javaClass; - void OfflineRegionStatus::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionStatus>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineRegionStatus>::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 b29a653655..9f638e1093 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<OfflineRegionStatus> New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); - static jni::Class<OfflineRegionStatus> 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 379ac89d52..d626ae68b7 100644 --- a/platform/android/src/snapshotter/map_snapshot.cpp +++ b/platform/android/src/snapshotter/map_snapshot.cpp @@ -38,21 +38,20 @@ jni::Object<MapSnapshot> MapSnapshot::New(JNIEnv& env, auto bitmap = Bitmap::CreateBitmap(env, std::move(image)); // Create the Mapsnapshot peers + static auto javaClass = jni::Class<MapSnapshot>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::jlong, jni::Object<Bitmap>, jni::Array<jni::String>, jni::jboolean>(env); auto nativePeer = std::make_unique<MapSnapshot>(pixelRatio, pointForFn, latLngForFn); return javaClass.New(env, constructor, reinterpret_cast<jlong>(nativePeer.release()), bitmap, conversion::toArray(env, attributions), (jni::jboolean) showLogo); } -jni::Class<MapSnapshot> MapSnapshot::javaClass; - void MapSnapshot::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshot::javaClass = *jni::Class<MapSnapshot>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<MapSnapshot>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<MapSnapshot>(env, MapSnapshot::javaClass, + jni::RegisterNativePeer<MapSnapshot>(env, javaClass, "nativePtr", std::make_unique<MapSnapshot, JNIEnv&>, "initialize", diff --git a/platform/android/src/snapshotter/map_snapshot.hpp b/platform/android/src/snapshotter/map_snapshot.hpp index f168be85b4..3cd293b621 100644 --- a/platform/android/src/snapshotter/map_snapshot.hpp +++ b/platform/android/src/snapshotter/map_snapshot.hpp @@ -39,8 +39,6 @@ public: jni::Object<LatLng> latLngForPixel(jni::JNIEnv&, jni::Object<PointF>); private: - static jni::Class<MapSnapshot> 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 a93404dbfb..4df0749aa0 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<CameraPosition> position, jni::jboolean _showLogo, jni::String _programCacheDir) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object<MapSnapshotter>(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<std::string> attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { MBGL_VERIFY_THREAD(tid); android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class<MapSnapshotter>::Singleton(*_env); if (err) { // error handler callback static auto onSnapshotFailed = javaClass.GetMethod<void (jni::String)>(*_env, "onSnapshotFailed"); - auto message = jni::Make<jni::String>(*_env, util::toString(err)); - javaPeer->Call(*_env, onSnapshotFailed, message); - jni::DeleteLocalRef(*_env, message); + javaPeer->Call(*_env, onSnapshotFailed, + *jni::SeizeLocal(*_env, jni::Make<jni::String>(*_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> MapSnapshotter::javaClass; - void MapSnapshotter::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshotter::javaClass = *jni::Class<MapSnapshotter>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<MapSnapshotter>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<MapSnapshotter>(env, MapSnapshotter::javaClass, "nativePtr", + jni::RegisterNativePeer<MapSnapshotter>(env, javaClass, "nativePtr", std::make_unique<MapSnapshotter, JNIEnv&, jni::Object<MapSnapshotter>, jni::Object<FileSource>, jni::jfloat, jni::jint, jni::jint, jni::String, jni::String, jni::Object<LatLngBounds>, jni::Object<CameraPosition>, 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 7b72452c45..05a27256aa 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<MapSnapshotter> javaClass; - static void registerNative(jni::JNIEnv&); MapSnapshotter(jni::JNIEnv&, @@ -60,7 +58,7 @@ private: MBGL_STORE_THREAD(tid); JavaVM *vm = nullptr; - GenericUniqueWeakObject<MapSnapshotter> javaPeer; + GenericWeak<jni::Object<MapSnapshotter>> javaPeer; float pixelRatio; bool showLogo; diff --git a/platform/android/src/style/conversion/filter.cpp b/platform/android/src/style/conversion/filter.cpp index 4eac0cf82b..44b5a71aa3 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<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) { +optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Local<jni::Array<jni::Object<>>> jfilter) { mbgl::optional<mbgl::style::Filter> filter; if (jfilter) { mbgl::style::conversion::Error error; - auto converted = mbgl::style::conversion::convert<mbgl::style::Filter>(Value(env, jfilter), error); + auto converted = mbgl::style::conversion::convert<mbgl::style::Filter>(Value(env, std::move(jfilter)), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error converting filter: " + error.message); } @@ -23,4 +23,4 @@ optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object< } // namespace conversion } // namespace android -} // namespace mbgl
\ No newline at end of file +} // namespace mbgl diff --git a/platform/android/src/style/conversion/filter.hpp b/platform/android/src/style/conversion/filter.hpp index df482de8f3..f638a853a1 100644 --- a/platform/android/src/style/conversion/filter.hpp +++ b/platform/android/src/style/conversion/filter.hpp @@ -9,7 +9,7 @@ namespace mbgl { namespace android { namespace conversion { -optional<mbgl::style::Filter> toFilter(jni::JNIEnv&, jni::Array<jni::Object<>>); +optional<mbgl::style::Filter> toFilter(jni::JNIEnv&, jni::Local<jni::Array<jni::Object<>>>); } // 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 a8f013b230..00c348b232 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> BackgroundLayer::javaClass; - jni::jobject* BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = BackgroundLayer::javaClass.template GetConstructor<jni::jlong>(env); - return BackgroundLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<BackgroundLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void BackgroundLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - BackgroundLayer::javaClass = *jni::Class<BackgroundLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<BackgroundLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<BackgroundLayer>( - env, BackgroundLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<BackgroundLayer, JNIEnv&, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp index 95555a2d78..3b7f03ddb6 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<BackgroundLayer> 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 4c7f69e956..47a492dd43 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> CircleLayer::javaClass; - jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CircleLayer::javaClass.template GetConstructor<jni::jlong>(env); - return CircleLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<CircleLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void CircleLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CircleLayer::javaClass = *jni::Class<CircleLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<CircleLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<CircleLayer>( - env, CircleLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<CircleLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp index 9d323e92bb..03063b1fc1 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<CircleLayer> 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 61e74a9cf5..c0dcc24f06 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> CustomLayer::javaClass; - jni::jobject* CustomLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomLayer::javaClass.template GetConstructor<jni::jlong>(env); - return CustomLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<CustomLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void CustomLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomLayer::javaClass = *jni::Class<CustomLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<CustomLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<CustomLayer>( - env, CustomLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<CustomLayer, JNIEnv&, jni::String, jni::jlong>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/custom_layer.hpp b/platform/android/src/style/layers/custom_layer.hpp index 7eb649d923..75e1957717 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<CustomLayer> 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<mbgl::style::CustomLayer>); - ~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 492e1729b9..6c6a0bef5a 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> FillExtrusionLayer::javaClass; - jni::jobject* FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillExtrusionLayer::javaClass.template GetConstructor<jni::jlong>(env); - return FillExtrusionLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<FillExtrusionLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void FillExtrusionLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillExtrusionLayer::javaClass = *jni::Class<FillExtrusionLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<FillExtrusionLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<FillExtrusionLayer>( - env, FillExtrusionLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<FillExtrusionLayer, JNIEnv&, jni::String, jni::String>, "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 11a74bc8ef..233c3cc334 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<FillExtrusionLayer> 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 f4cddc8858..5182c546c8 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> FillLayer::javaClass; - jni::jobject* FillLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillLayer::javaClass.template GetConstructor<jni::jlong>(env); - return FillLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<FillLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void FillLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillLayer::javaClass = *jni::Class<FillLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<FillLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<FillLayer>( - env, FillLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<FillLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp index a773cf785b..db1fee1667 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<FillLayer> 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 b3d90faab7..e83d92873f 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> HeatmapLayer::javaClass; - jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HeatmapLayer::javaClass.template GetConstructor<jni::jlong>(env); - return HeatmapLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<HeatmapLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void HeatmapLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HeatmapLayer::javaClass = *jni::Class<HeatmapLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<HeatmapLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<HeatmapLayer>( - env, HeatmapLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<HeatmapLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp index 9e8908b062..00ab27d854 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<HeatmapLayer> 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 d98e3ee074..b6409b3b3e 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> HillshadeLayer::javaClass; - jni::jobject* HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HillshadeLayer::javaClass.template GetConstructor<jni::jlong>(env); - return HillshadeLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<HillshadeLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void HillshadeLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HillshadeLayer::javaClass = *jni::Class<HillshadeLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<HillshadeLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<HillshadeLayer>( - env, HillshadeLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<HillshadeLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/hillshade_layer.hpp b/platform/android/src/style/layers/hillshade_layer.hpp index 4b68251775..f824698058 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<HillshadeLayer> 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 48e09674e8..fe4fb9aeb6 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<mbgl::style::conversion::Error> error = layer.setLayoutProperty(jni::Make<std::string>(env, jname), Value(env, jvalue)); + optional<mbgl::style::conversion::Error> error = layer.setLayoutProperty(jni::Make<std::string>(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(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<mbgl::style::conversion::Error> error = layer.setPaintProperty(jni::Make<std::string>(env, jname), Value(env, jvalue)); + optional<mbgl::style::conversion::Error> error = layer.setPaintProperty(jni::Make<std::string>(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message); return; @@ -128,7 +128,7 @@ namespace android { using namespace mbgl::style::conversion; Error error; - optional<Filter> converted = convert<Filter>(Value(env, jfilter), error); + optional<Filter> converted = convert<Filter>(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<jni::ObjectTag>(*convert<jni::jobject*>(env, layer.getVisibility())); } - jni::Class<Layer> Layer::javaClass; - void Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - Layer::javaClass = *jni::Class<Layer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<Layer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Layer>(env, Layer::javaClass, "nativePtr", + jni::RegisterNativePeer<Layer>(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 b08f0ec4dc..7dbb031b25 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<jni::jlong>(env); - return <%- camelize(type) %>Layer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(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<decltype(MethodPtr), (MethodPtr)>(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 41022bf74a..8112dd18d6 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<Layer> 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 837049b4c3..dd599d71df 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 f143ecc236..2656bd9c09 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> LineLayer::javaClass; - jni::jobject* LineLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = LineLayer::javaClass.template GetConstructor<jni::jlong>(env); - return LineLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<LineLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void LineLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - LineLayer::javaClass = *jni::Class<LineLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<LineLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<LineLayer>( - env, LineLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<LineLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp index 9eef1349cb..4d1e759c1b 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<LineLayer> 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 53086951e4..c52891b662 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> RasterLayer::javaClass; - jni::jobject* RasterLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterLayer::javaClass.template GetConstructor<jni::jlong>(env); - return RasterLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<RasterLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void RasterLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterLayer::javaClass = *jni::Class<RasterLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<RasterLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<RasterLayer>( - env, RasterLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<RasterLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp index d1c1b45234..4e268c36e5 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<RasterLayer> 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 d44744a6cf..953c73e221 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> SymbolLayer::javaClass; - jni::jobject* SymbolLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = SymbolLayer::javaClass.template GetConstructor<jni::jlong>(env); - return SymbolLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<SymbolLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void SymbolLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - SymbolLayer::javaClass = *jni::Class<SymbolLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<SymbolLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<SymbolLayer>( - env, SymbolLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<SymbolLayer, JNIEnv&, jni::String, jni::String>, "initialize", "finalize", diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp index 417e5e143f..3835e01bf1 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<SymbolLayer> 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 8ffda82bfc..9f877e4896 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> UnknownLayer::javaClass; - jni::jobject* UnknownLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownLayer::javaClass.template GetConstructor<jni::jlong>(env); - return UnknownLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<UnknownLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void UnknownLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownLayer::javaClass = *jni::Class<UnknownLayer>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<UnknownLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) @@ -39,7 +38,7 @@ namespace android { // Register the peer jni::RegisterNativePeer<UnknownLayer>( - 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 67992ea007..0610c843f1 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<UnknownLayer> 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 71f1cb076e..64afb89204 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> Light::javaClass; - jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor<jni::jlong>(env); - return Light::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<Light>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(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<Light>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<Light>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Light>(env, Light::javaClass, "nativePtr", + jni::RegisterNativePeer<Light>(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 17f0bba09d..f18dc57a4f 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> Light::javaClass; - jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor<jni::jlong>(env); - return Light::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + static auto javaClass = jni::Class<Light>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(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<Light>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<Light>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Light>(env, Light::javaClass, "nativePtr",<% for(var i = 0; i < properties.length; i++) {%> + jni::RegisterNativePeer<Light>(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 0bbcefcbcd..c6918a2e9a 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> Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { - static auto method = Position::javaClass.GetStaticMethod<jni::Object<Position> (jfloat, jfloat, jfloat)>(env, "fromPosition"); - return Position::javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); + static auto javaClass = jni::Class<Position>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Position> (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<Position>::Find(env).NewGlobalRef(env).release(); + jni::Class<Position>::Singleton(env); } -jni::Class<Position> Position::javaClass; - float Position::getRadialCoordinate(jni::JNIEnv& env, jni::Object<Position> position){ - static auto field = Position::javaClass.GetField<jfloat>(env, "radialCoordinate"); + static auto javaClass = jni::Class<Position>::Singleton(env); + static auto field = javaClass.GetField<jfloat>(env, "radialCoordinate"); return position.Get(env, field); } float Position::getAzimuthalAngle(jni::JNIEnv& env, jni::Object<Position> position){ - static auto field = Position::javaClass.GetField<jfloat>(env, "azimuthalAngle"); + static auto javaClass = jni::Class<Position>::Singleton(env); + static auto field = javaClass.GetField<jfloat>(env, "azimuthalAngle"); return position.Get(env, field); } float Position::getPolarAngle(jni::JNIEnv& env, jni::Object<Position> position){ - static auto field = Position::javaClass.GetField<jfloat>(env, "polarAngle"); + static auto javaClass = jni::Class<Position>::Singleton(env); + static auto field = javaClass.GetField<jfloat>(env, "polarAngle"); return position.Get(env, field); } diff --git a/platform/android/src/style/position.hpp b/platform/android/src/style/position.hpp index 4aafa853db..4f3738da9f 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<Position> fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); - static jni::Class<Position> javaClass; - static void registerNative(jni::JNIEnv&); static float getRadialCoordinate(jni::JNIEnv&, jni::Object<Position>); static float getAzimuthalAngle(jni::JNIEnv&, jni::Object<Position>); static float getPolarAngle(jni::JNIEnv&, jni::Object<Position>); - }; - } // 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 e9a530f75b..029824eae0 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<jni::Object<>> 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<style::CustomGeometrySource::Options> result = convert<style::CustomGeometrySource::Options>(Value(env, options), error); + optional<style::CustomGeometrySource::Options> result = convert<style::CustomGeometrySource::Options>(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<mbgl::style::CustomGeometrySource>( jni::Make<std::string>(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<CustomGeometrySource>::Singleton(*_env); static auto fetchTile = javaClass.GetMethod<void (jni::jint, jni::jint, jni::jint)>(*_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<CustomGeometrySource>::Singleton(*_env); static auto cancelTile = javaClass.GetMethod<void (jni::jint, jni::jint, jni::jint)>(*_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<CustomGeometrySource>::Singleton(*_env); static auto startThreads = javaClass.GetMethod<void ()>(*_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<CustomGeometrySource>::Singleton(*_env); static auto releaseThreads = javaClass.GetMethod<void ()>(*_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<CustomGeometrySource>::Singleton(*_env); static auto isCancelled = javaClass.GetMethod<jboolean (jni::jint, jni::jint, jni::jint)>(*_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<mbgl::Feature> 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<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); } - jni::Class<CustomGeometrySource> CustomGeometrySource::javaClass; - jni::Object<Source> CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomGeometrySource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<CustomGeometrySource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } void CustomGeometrySource::addToMap(JNIEnv& env, jni::Object<Source> 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<CustomGeometrySource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<CustomGeometrySource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<CustomGeometrySource>( - env, CustomGeometrySource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<CustomGeometrySource, JNIEnv&, jni::String, jni::Object<>>, "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 801f81b089..ecfadd659c 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<CustomGeometrySource> 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<Source>, 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<geojson::FeatureCollection> jf); void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y); @@ -44,7 +42,6 @@ public: jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, jni::Array<jni::Object<>> ); -private: jni::Object<Source> 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 9d6ca704eb..b9f3f73801 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<jni::Object<>> options) { using namespace mbgl::style::conversion; if (!options) { return style::GeoJSONOptions(); } Error error; - optional<style::GeoJSONOptions> result = convert<style::GeoJSONOptions>(mbgl::android::Value(env, options), error); + optional<style::GeoJSONOptions> result = convert<style::GeoJSONOptions>( + 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<mbgl::style::GeoJSONSource>( jni::Make<std::string>(env, sourceId), - convertGeoJSONOptions(env, options))) + convertGeoJSONOptions(env, jni::SeizeLocal(env, std::move(options))))) , threadPool(sharedThreadPool()) , converter(std::make_unique<Actor<FeatureConverter>>(*threadPool)) { } @@ -100,22 +101,22 @@ namespace android { std::vector<mbgl::Feature> 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<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); } - jni::Class<GeoJSONSource> GeoJSONSource::javaClass; - jni::Object<Source> GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = GeoJSONSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<GeoJSONSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } template <class JNIType> void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, jni::Object<JNIType> jObject) { - std::shared_ptr<jni::jobject> object = std::shared_ptr<jni::jobject>(jObject.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter()); + std::shared_ptr<jni::jobject> object = std::shared_ptr<jni::jobject>(jObject.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter()); Update::Converter converterFn = [this, object](ActorRef<Callback> _callback) { converter->self().invoke(&FeatureConverter::convertObject<JNIType>, jni::Object<JNIType>(*object), _callback); @@ -158,13 +159,13 @@ namespace android { void GeoJSONSource::registerNative(jni::JNIEnv& env) { // Lookup the class - GeoJSONSource::javaClass = *jni::Class<GeoJSONSource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<GeoJSONSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<GeoJSONSource>( - env, GeoJSONSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<GeoJSONSource, JNIEnv&, jni::String, jni::Object<>>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 24ea3c73f8..eb28e2470b 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<GeoJSONSource> 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<geojson::FeatureCollection>); - void setFeature(jni::JNIEnv&, jni::Object<geojson::Feature>); - void setGeometry(jni::JNIEnv&, jni::Object<geojson::Geometry>); - void setURL(jni::JNIEnv&, jni::String); - jni::String getURL(jni::JNIEnv&); - jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, - jni::Array<jni::Object<>> jfilter); + jni::Array<jni::Object<>>); + + jni::String getURL(jni::JNIEnv&); -private: jni::Object<Source> createJavaPeer(jni::JNIEnv&); std::unique_ptr<Update> awaitingUpdate; std::unique_ptr<Update> update; diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp index 278564485d..343b7439c8 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> ImageSource::javaClass; - jni::Object<Source> ImageSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = ImageSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(ImageSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<ImageSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } void ImageSource::registerNative(jni::JNIEnv& env) { // Lookup the class - ImageSource::javaClass = *jni::Class<ImageSource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<ImageSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<ImageSource>( - env, ImageSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<ImageSource, JNIEnv&, jni::String, jni::Object<LatLngQuad>>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp index 6021a03dc3..b09d4f8c95 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<ImageSource> javaClass; - static void registerNative(jni::JNIEnv&); ImageSource(jni::JNIEnv&, jni::String, jni::Object<LatLngQuad>); diff --git a/platform/android/src/style/sources/raster_dem_source.cpp b/platform/android/src/style/sources/raster_dem_source.cpp index 75e0159d7c..73d04f27c1 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<mbgl::style::RasterDEMSource>( jni::Make<std::string>(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<jni::String>(env, *url) : jni::String(); } - jni::Class<RasterDEMSource> RasterDEMSource::javaClass; - jni::Object<Source> RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterDEMSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(RasterDEMSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<RasterDEMSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } void RasterDEMSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterDEMSource::javaClass = *jni::Class<RasterDEMSource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<RasterDEMSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<RasterDEMSource>( - env, RasterDEMSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<RasterDEMSource, JNIEnv&, jni::String, jni::Object<>, 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 56924c1f8d..25d9fe90cd 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<RasterDEMSource> 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 33223a5b69..4eef41c8b1 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<mbgl::style::RasterSource>( jni::Make<std::string>(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<jni::String>(env, *url) : jni::String(); } - jni::Class<RasterSource> RasterSource::javaClass; - jni::Object<Source> RasterSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(RasterSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<RasterSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } void RasterSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterSource::javaClass = *jni::Class<RasterSource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<RasterSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<RasterSource>( - env, RasterSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<RasterSource, JNIEnv&, jni::String, jni::Object<>, 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 a1da22f40d..888d9f601d 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<RasterSource> 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 d2e2426c0b..c7968786ec 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<Source>::Singleton(*env); static auto nativePtrField = javaClass.GetField<jlong>(*env, "nativePtr"); javaPeer->Set(*env, nativePtrField, (jlong) 0); javaPeer.reset(); @@ -140,16 +141,14 @@ namespace android { rendererFrontend = nullptr; } - jni::Class<Source> Source::javaClass; - void Source::registerNative(jni::JNIEnv& env) { // Lookup the class - Source::javaClass = *jni::Class<Source>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<Source>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Source>(env, Source::javaClass, "nativePtr", + jni::RegisterNativePeer<Source>(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 6b906eb9c0..492be8dfec 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<Source> javaClass; - static void registerNative(jni::JNIEnv&); static jni::Object<Source> 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<Source> javaPeer; + jni::Global<jni::Object<Source>> 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 4b5510c1db..8e91798392 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> UnknownSource::javaClass; - jni::Object<Source> UnknownSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(UnknownSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<UnknownSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } void UnknownSource::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownSource::javaClass = *jni::Class<UnknownSource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<UnknownSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<UnknownSource>( - 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 414d420c61..855aea7c63 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<UnknownSource> 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 9a9548d283..69052bd98c 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<mbgl::style::VectorSource>( jni::Make<std::string>(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)) + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))) ) ) { } @@ -51,27 +51,27 @@ namespace android { std::vector<mbgl::Feature> 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<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); } - jni::Class<VectorSource> VectorSource::javaClass; - jni::Object<Source> VectorSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = VectorSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(VectorSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + static auto javaClass = jni::Class<VectorSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return jni::Object<Source>(javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); } void VectorSource::registerNative(jni::JNIEnv& env) { // Lookup the class - VectorSource::javaClass = *jni::Class<VectorSource>::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class<VectorSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<VectorSource>( - env, VectorSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique<VectorSource, JNIEnv&, jni::String, jni::Object<>>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index 16049f5c77..587a4be208 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<VectorSource> javaClass; - static void registerNative(jni::JNIEnv&); VectorSource(jni::JNIEnv&, jni::String, jni::Object<>); - VectorSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~VectorSource(); +private: jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, jni::Array<jni::String>, jni::Array<jni::Object<>> jfilter); jni::String getURL(jni::JNIEnv&); -private: jni::Object<Source> createJavaPeer(jni::JNIEnv&); }; // class VectorSource diff --git a/platform/android/src/style/transition_options.cpp b/platform/android/src/style/transition_options.cpp index c70aa5fe2e..84bd909125 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> TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { - static auto method = TransitionOptions::javaClass.GetStaticMethod<jni::Object<TransitionOptions> (jlong, jlong)>(env, "fromTransitionOptions"); - return TransitionOptions::javaClass.Call(env, method, duration, delay); + static auto javaClass = jni::Class<TransitionOptions>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<TransitionOptions> (jlong, jlong)>(env, "fromTransitionOptions"); + return javaClass.Call(env, method, duration, delay); } void TransitionOptions::registerNative(jni::JNIEnv& env) { - // Lookup the class - TransitionOptions::javaClass = *jni::Class<TransitionOptions>::Find(env).NewGlobalRef(env).release(); + jni::Class<TransitionOptions>::Singleton(env); } -jni::Class<TransitionOptions> 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 3e6b0bc488..83276ca1d8 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<TransitionOptions> fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); - static jni::Class<TransitionOptions> 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 70bdea6677..6cdf134931 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<jni::Object<>> _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<jni::jstring*>(value.get()); + jni::jstring* string = reinterpret_cast<jni::jstring*>(value->Get()); return jni::Make<std::string>(env, jni::String(string)); } float Value::toFloat() const { - return jni::CallMethod<jni::jfloat>(env, value.get(), *java::Number::floatValueMethodId); + return jni::CallMethod<jni::jfloat>(env, value->Get(), *java::Number::floatValueMethodId); } double Value::toDouble() const { - return jni::CallMethod<jni::jdouble>(env, value.get(), *java::Number::doubleValueMethodId); + return jni::CallMethod<jni::jdouble>(env, value->Get(), *java::Number::doubleValueMethodId); } long Value::toLong() const { - return jni::CallMethod<jni::jlong>(env, value.get(), *java::Number::longValueMethodId); + return jni::CallMethod<jni::jlong>(env, value->Get(), *java::Number::longValueMethodId); } bool Value::toBool() const { - return jni::CallMethod<jni::jboolean>(env, value.get(), *java::Boolean::booleanValueMethodId); + return jni::CallMethod<jni::jboolean>(env, value->Get(), *java::Boolean::booleanValueMethodId); } Value Value::get(const char* key) const { - jni::jobject* member = jni::CallMethod<jni::jobject*>(env, value.get(), *java::Map::getMethodId, jni::Make<jni::String>(env, std::string(key)).Get()); - return Value(env, member); + jni::jobject* member = jni::CallMethod<jni::jobject*>(env, value->Get(), *java::Map::getMethodId, jni::Make<jni::String>(env, std::string(key)).Get()); + return Value(env, jni::SeizeLocal(env, jni::Object<>(member))); } int Value::getLength() const { - auto array = (jni::jarray<jni::jobject>*) value.get(); + auto array = (jni::jarray<jni::jobject>*) value->Get(); return jni::GetArrayLength(env, *array); } Value Value::get(const int index) const { - auto array = (jni::jarray<jni::jobject>*) value.get(); - return Value(env, jni::GetObjectArrayElement(env, *array, index)); + auto array = (jni::jarray<jni::jobject>*) 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 2057b93454..bd1c552be0 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<jni::Object<>>); Value(Value&&) = default; Value& operator=(Value&&) = default; @@ -34,7 +34,7 @@ public: Value get(const int index ) const; jni::JNIEnv& env; - std::shared_ptr<jni::jobject> value; + jni::Local<jni::Object<>> value; }; } diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/text/collator.cpp index 37af0a1c5b..86e72a1dac 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<Collator>::Find(env).NewGlobalRef(env).release(); + jni::Class<Collator>::Singleton(env); } -jni::Class<Collator> Collator::javaClass; - jni::Object<Collator> Collator::getInstance(jni::JNIEnv& env, jni::Object<Locale> locale) { - using Signature = jni::Object<Collator>(jni::Object<Locale>); - auto method = javaClass.GetStaticMethod<Signature>(env, "getInstance"); + static auto javaClass = jni::Class<Collator>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Collator> (jni::Object<Locale>)>(env, "getInstance"); return javaClass.Call(env, method, locale); } void Collator::setStrength(jni::JNIEnv& env, jni::Object<Collator> collator, jni::jint strength) { - using Signature = void(jni::jint); - auto static method = javaClass.GetMethod<Signature>(env, "setStrength"); + static auto javaClass = jni::Class<Collator>::Singleton(env); + static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setStrength"); collator.Call(env, method, strength); } jni::jint Collator::compare(jni::JNIEnv& env, jni::Object<Collator> collator, jni::String lhs, jni::String rhs) { - using Signature = jni::jint(jni::String, jni::String); - auto static method = javaClass.GetMethod<Signature>(env, "compare"); + static auto javaClass = jni::Class<Collator>::Singleton(env); + auto static method = javaClass.GetMethod<jni::jint (jni::String, jni::String)>(env, "compare"); return collator.Call(env, method, lhs, rhs); } void Locale::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<Locale>::Find(env).NewGlobalRef(env).release(); + jni::Class<Locale>::Singleton(env); } - /* +/* We would prefer to use for/toLanguageTag, but they're only available in API level 21+ jni::Object<Locale> Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) { @@ -54,39 +52,38 @@ jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object<Locale> locale) auto static method = javaClass.GetMethod<Signature>(env, "toLanguageTag"); return locale.Call(env, method); } - */ - +*/ jni::String Locale::getLanguage(jni::JNIEnv& env, jni::Object<Locale> locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod<Signature>(env, "getLanguage"); + static auto javaClass = jni::Class<Locale>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "getLanguage"); return locale.Call(env, method); } jni::String Locale::getCountry(jni::JNIEnv& env, jni::Object<Locale> locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod<Signature>(env, "getCountry"); + static auto javaClass = jni::Class<Locale>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "getCountry"); return locale.Call(env, method); } jni::Object<Locale> Locale::getDefault(jni::JNIEnv& env) { - using Signature = jni::Object<Locale>(); - auto method = javaClass.GetStaticMethod<Signature>(env, "getDefault"); + static auto javaClass = jni::Class<Locale>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Locale> ()>(env, "getDefault"); return javaClass.Call(env, method); } jni::Object<Locale> Locale::New(jni::JNIEnv& env, jni::String language) { + static auto javaClass = jni::Class<Locale>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String>(env); return javaClass.New(env, constructor, language); } jni::Object<Locale> Locale::New(jni::JNIEnv& env, jni::String language, jni::String region) { + static auto javaClass = jni::Class<Locale>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env); return javaClass.New(env, constructor, language, region); } -jni::Class<Locale> 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<jni::String>(*env, useUnaccent ? + jni::Local<jni::String> jlhs = jni::SeizeLocal(*env, jni::Make<jni::String>(*env, useUnaccent ? platform::unaccent(lhs) : - lhs); - jni::String jrhs = jni::Make<jni::String>(*env, useUnaccent ? + lhs)); + jni::Local<jni::String> jrhs = jni::SeizeLocal(*env, jni::Make<jni::String>(*env, useUnaccent ? platform::unaccent(rhs) : - rhs); - - jni::jint result = android::Collator::compare(*env, *collator, jlhs, jrhs);; + rhs)); - 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<std::string>(*env, jLanguage); - jni::DeleteLocalRef(*env, jLanguage); - jni::String jRegion = android::Locale::getCountry(*env, *locale); - std::string region = jni::Make<std::string>(*env, jRegion); - jni::DeleteLocalRef(*env, jRegion); + std::string language = jni::Make<std::string>(*env, + *jni::SeizeLocal(*env, android::Locale::getLanguage(*env, *locale))); + std::string region = jni::Make<std::string>(*env, + *jni::SeizeLocal(*env, android::Locale::getCountry(*env, *locale))); optional<std::string> 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<android::Collator> collator; - jni::UniqueObject<android::Locale> locale; + jni::Global<jni::Object<android::Collator>> collator; + jni::Global<jni::Object<android::Locale>> locale; }; diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/text/collator_jni.hpp index 96c381b1c1..30fb6a4369 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<Locale> New(jni::JNIEnv&, jni::String); static jni::Object<Locale> New(jni::JNIEnv&, jni::String, jni::String); - static jni::Class<Locale> javaClass; static void registerNative(jni::JNIEnv&); - }; class Collator { @@ -47,10 +45,8 @@ public: static jni::jint compare(jni::JNIEnv&, jni::Object<Collator>, jni::String, jni::String); - static jni::Class<Collator> 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 3dc1eb275a..adfa0559f3 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<LocalGlyphRasterizer>::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<Bitmap>(jni::String, jni::jboolean, jni::jchar); - static auto method = javaClass.GetMethod<Signature>(*env, "drawGlyphBitmap"); + static auto javaClass = jni::Class<LocalGlyphRasterizer>::Singleton(*env); + static auto drawGlyphBitmap = javaClass.GetMethod<jni::Object<Bitmap> (jni::String, jni::jboolean, jni::jchar)>(*env, "drawGlyphBitmap"); - jni::String jniFontFamily = jni::Make<jni::String>(*env, fontFamily); + auto javaBitmap = jni::SeizeLocal(*env, + javaObject->Call(*env, drawGlyphBitmap, + *jni::SeizeLocal(*env, jni::Make<jni::String>(*env, fontFamily)), + static_cast<jni::jboolean>(bold), + static_cast<jni::jchar>(glyphID))); - auto javaBitmap = javaObject->Call(*env, - method, - jniFontFamily, - static_cast<jni::jboolean>(bold), - static_cast<jni::jchar>(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<LocalGlyphRasterizer>::Find(env).NewGlobalRef(env).release(); + jni::Class<LocalGlyphRasterizer>::Singleton(env); } -jni::Class<LocalGlyphRasterizer> 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 1c83ea5f58..e80e848338 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<LocalGlyphRasterizer> 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<LocalGlyphRasterizer> javaObject; + jni::Global<jni::Object<LocalGlyphRasterizer>> javaObject; }; } // namespace android |