diff options
Diffstat (limited to 'platform/android/src')
25 files changed, 1248 insertions, 0 deletions
diff --git a/platform/android/src/java_types.cpp b/platform/android/src/java_types.cpp new file mode 100644 index 0000000000..6383426387 --- /dev/null +++ b/platform/android/src/java_types.cpp @@ -0,0 +1,37 @@ +#include "java_types.hpp" + +namespace mbgl { +namespace android { +namespace java { + + jni::jclass* ObjectArray::jclass; + + jni::jclass* String::jclass; + + jni::jclass* Boolean::jclass; + jni::jmethodID* Boolean::booleanValueMethodId; + + jni::jclass* Number::jclass; + jni::jmethodID* Number::floatValueMethodId; + + jni::jclass* Map::jclass; + jni::jmethodID* Map::getMethodId; + + void registerNatives(JNIEnv& env) { + ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release(); + + String::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release(); + + Boolean::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release(); + Boolean::booleanValueMethodId = &jni::GetMethodID(env, *Boolean::jclass, "booleanValue", "()Z"); + + Number::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Number")).release(); + Number::floatValueMethodId = &jni::GetMethodID(env, *Number::jclass, "floatValue", "()F"); + + Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release(); + Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + } + +} +} +} diff --git a/platform/android/src/java_types.hpp b/platform/android/src/java_types.hpp new file mode 100644 index 0000000000..2e2c5fc2d6 --- /dev/null +++ b/platform/android/src/java_types.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { +namespace java { + + struct ObjectArray { + static jni::jclass* jclass; + }; + + struct String { + static jni::jclass* jclass; + }; + + struct Boolean { + static jni::jclass* jclass; + static jni::jmethodID* booleanValueMethodId; + }; + + struct Number { + static jni::jclass* jclass; + static jni::jmethodID* floatValueMethodId; + }; + + struct Map { + static jni::jclass* jclass; + static jni::jmethodID* getMethodId; + }; + + void registerNatives(JNIEnv&); +} +} +}
\ No newline at end of file diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index c9670bfcb9..18a22cb8b3 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -9,11 +9,15 @@ #include <sys/system_properties.h> #include "jni.hpp" +#include "java_types.hpp" #include "native_map_view.hpp" +#include "style/layers/layers.hpp" +#include "style/sources/sources.hpp" #include <mbgl/map/map.hpp> #include <mbgl/map/camera.hpp> #include <mbgl/annotation/annotation.hpp> +#include <mbgl/style/layer.hpp> #include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/sprite/sprite_image.hpp> #include <mbgl/platform/event.hpp> @@ -1085,6 +1089,81 @@ void nativeRemoveCustomLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapView nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id)); } +jni::jobject* nativeGetLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* layerId) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLayer"); + + assert(env); + assert(nativeMapViewPtr != 0); + + //Get the native map peer + NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); + + //Find the layer + mbgl::style::Layer* coreLayer = nativeMapView->getMap().getLayer(std_string_from_jstring(env, layerId)); + if (!coreLayer) { + mbgl::Log::Debug(mbgl::Event::JNI, "No layer found"); + return jni::Object<Layer>(); + } + + //Create and return the layer's native peer + return createJavaLayerPeer(*env, nativeMapView->getMap(), *coreLayer); +} + +void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong nativeLayerPtr, jni::jstring* before) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddLayer"); + assert(nativeMapViewPtr != 0); + assert(nativeLayerPtr != 0); + + NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); + Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr); + + nativeMapView->getMap().addLayer( + layer->releaseCoreLayer(), + before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>() + ); +} + +void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveLayer"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); + try { + nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id)); + } catch (const std::runtime_error& error) { + jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what()); + } +} + +void nativeAddSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id, jni::jobject* jsource) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddSource"); + assert(nativeMapViewPtr != 0); + assert(id != nullptr); + assert(jsource != nullptr); + + //Convert + mbgl::optional<std::unique_ptr<mbgl::style::Source>> source = convertToNativeSource( + *env, + jni::Object<jni::jobject>(jsource), jni::String(id) + ); + + //Add to map view + if (source) { + NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); + nativeMapView->getMap().addSource(std::move(*source)); + } +} + +void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveSource"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); + try { + nativeMapView->getMap().removeSource(std_string_from_jstring(env, id)); + } catch (const std::runtime_error& error) { + jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchSourceException"), error.what()); + } +} + // Offline calls begin jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* assetRoot_, jlong maximumCacheSize) { @@ -1545,6 +1624,9 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { mbgl::android::RegisterNativeHTTPRequest(env); + java::registerNatives(env); + registerNativeLayers(env); + latLngClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLng"); latLngClass = jni::NewGlobalRef(env, latLngClass).release(); latLngConstructorId = &jni::GetMethodID(env, *latLngClass, "<init>", "(DD)V"); @@ -1699,6 +1781,11 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { MAKE_NATIVE_METHOD(nativeFlyTo, "(JDDDJDD)V"), MAKE_NATIVE_METHOD(nativeAddCustomLayer, "(JLcom/mapbox/mapboxsdk/layers/CustomLayer;Ljava/lang/String;)V"), MAKE_NATIVE_METHOD(nativeRemoveCustomLayer, "(JLjava/lang/String;)V"), + MAKE_NATIVE_METHOD(nativeGetLayer, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/layers/Layer;"), + MAKE_NATIVE_METHOD(nativeAddLayer, "(JJLjava/lang/String;)V"), + MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JLjava/lang/String;)V"), + MAKE_NATIVE_METHOD(nativeAddSource, "(JLjava/lang/String;Lcom/mapbox/mapboxsdk/style/sources/Source;)V"), + MAKE_NATIVE_METHOD(nativeRemoveSource, "(JLjava/lang/String;)V"), MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V") ); diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp new file mode 100644 index 0000000000..5128cce51f --- /dev/null +++ b/platform/android/src/style/android_conversion.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include "value.hpp" + +#include <mbgl/platform/log.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/util/feature.hpp> +#include <mbgl/util/optional.hpp> + +#include <jni/jni.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + + +//XXX +#pragma GCC diagnostic ignored "-Wunused-parameter" + +inline bool isUndefined(const mbgl::android::Value& value) { + return value.isNull(); +} + +inline bool isArray(const mbgl::android::Value& value) { + return value.isArray(); +} + +inline bool isObject(const mbgl::android::Value& value) { + return value.isObject(); +} + +inline std::size_t arrayLength(const mbgl::android::Value& value) { + return value.getLength();; +} + +inline mbgl::android::Value arrayMember(const mbgl::android::Value& value, std::size_t i) { + return value.get(i); +} + +inline optional<mbgl::android::Value> objectMember(const mbgl::android::Value& value, const char* key) { + mbgl::android::Value member = value.get(key); + + if (!member.isNull()) { + return member; + } else { + return {}; + } +} + +template <class Fn> +optional<Error> eachMember(const mbgl::android::Value& value, Fn&& fn) { + //TODO + mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented"); + return {}; +} + +inline optional<bool> toBool(const mbgl::android::Value& value) { + if (value.isBool()) { + return value.toBool(); + } else { + return {}; + } +} + +inline optional<float> toNumber(const mbgl::android::Value& value) { + if (value.isNumber()) { + return value.toNumber(); + } else { + return {}; + } +} + +inline optional<std::string> toString(const mbgl::android::Value& value) { + if (value.isString()) { + return value.toString(); + } else { + return {}; + } +} + +inline optional<Value> toValue(const mbgl::android::Value& value) { + if (value.isBool()) { + return { value.toBool() }; + } else if (value.isString()) { + return { value.toString() }; + } else if (value.isNumber()) { + return { value.toNumber() }; + } else { + return {}; + } +} + +} // namespace conversion +} // namespace style +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/android_geojson.hpp b/platform/android/src/style/android_geojson.hpp new file mode 100644 index 0000000000..b2e0ca0a4a --- /dev/null +++ b/platform/android/src/style/android_geojson.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "value.hpp" + +#include <mapbox/geojson.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/geojson.hpp> +#include <mbgl/util/rapidjson.hpp> +#include <mbgl/platform/log.hpp> +#include <jni/jni.hpp> + +#include <sstream> +#include <string> + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +Result<GeoJSON> convertGeoJSON(const mbgl::android::Value& value) { + + //Value should be a string wrapped in an object + mbgl::android::Value jsonValue = value.get("data"); + if(value.isNull()) { + return Error { "no json data found" }; + } + std::string jsonString = value.get("data").toString(); + + rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d; + d.Parse(jsonString.c_str()); + + if (d.HasParseError()) { + std::stringstream message; + message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError()); + return Error { message.str() }; + } + + conversion::Result<GeoJSON> geoJSON = conversion::convertGeoJSON<JSValue>(d); + if (!geoJSON) { + return Error { geoJSON.error().message }; + } + + return geoJSON; +} + +} // namespace conversion +} // namespace style +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/layers/background_layer.cpp b/platform/android/src/style/layers/background_layer.cpp new file mode 100644 index 0000000000..4847d59420 --- /dev/null +++ b/platform/android/src/style/layers/background_layer.cpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "background_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + + BackgroundLayer::BackgroundLayer(jni::JNIEnv& env, jni::String layerId) + : Layer(env, std::make_unique<mbgl::style::BackgroundLayer>(jni::Make<std::string>(env, layerId))) { + mbgl::Log::Debug(mbgl::Event::JNI, "BackgroundLayer constructed, owning reference"); + } + + BackgroundLayer::BackgroundLayer(mbgl::Map& map, mbgl::style::BackgroundLayer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "BackgroundLayer Non-owning reference constructor"); + } + + BackgroundLayer::~BackgroundLayer() = default; + + 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)); + } + + void BackgroundLayer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + BackgroundLayer::javaClass = *jni::Class<BackgroundLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<BackgroundLayer>( + env, BackgroundLayer::javaClass, "nativePtr", + std::make_unique<BackgroundLayer, JNIEnv&, jni::String>, + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp new file mode 100644 index 0000000000..b253b4861c --- /dev/null +++ b/platform/android/src/style/layers/background_layer.hpp @@ -0,0 +1,31 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/background_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class BackgroundLayer : public Layer { +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); + + BackgroundLayer(mbgl::Map&, mbgl::style::BackgroundLayer&); + + ~BackgroundLayer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp new file mode 100644 index 0000000000..ad0d0b34ce --- /dev/null +++ b/platform/android/src/style/layers/circle_layer.cpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "circle_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + + CircleLayer::CircleLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::CircleLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { + mbgl::Log::Debug(mbgl::Event::JNI, "CircleLayer constructed, owning reference"); + } + + CircleLayer::CircleLayer(mbgl::Map& map, mbgl::style::CircleLayer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "CircleLayer Non-owning reference constructor"); + } + + CircleLayer::~CircleLayer() = default; + + 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)); + } + + void CircleLayer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + CircleLayer::javaClass = *jni::Class<CircleLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<CircleLayer>( + env, CircleLayer::javaClass, "nativePtr", + std::make_unique<CircleLayer, JNIEnv&, jni::String, jni::String>, + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp new file mode 100644 index 0000000000..e0dc94eb00 --- /dev/null +++ b/platform/android/src/style/layers/circle_layer.hpp @@ -0,0 +1,31 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/circle_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class CircleLayer : public Layer { +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); + + CircleLayer(mbgl::Map&, mbgl::style::CircleLayer&); + + ~CircleLayer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/fill_layer.cpp b/platform/android/src/style/layers/fill_layer.cpp new file mode 100644 index 0000000000..1056c8353b --- /dev/null +++ b/platform/android/src/style/layers/fill_layer.cpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "fill_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + + FillLayer::FillLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::FillLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { + mbgl::Log::Debug(mbgl::Event::JNI, "FillLayer constructed, owning reference"); + } + + FillLayer::FillLayer(mbgl::Map& map, mbgl::style::FillLayer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "FillLayer Non-owning reference constructor"); + } + + FillLayer::~FillLayer() = default; + + 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)); + } + + void FillLayer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + FillLayer::javaClass = *jni::Class<FillLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<FillLayer>( + env, FillLayer::javaClass, "nativePtr", + std::make_unique<FillLayer, JNIEnv&, jni::String, jni::String>, + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp new file mode 100644 index 0000000000..5ed80d401f --- /dev/null +++ b/platform/android/src/style/layers/fill_layer.hpp @@ -0,0 +1,31 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/fill_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class FillLayer : public Layer { +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); + + FillLayer(mbgl::Map&, mbgl::style::FillLayer&); + + ~FillLayer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp new file mode 100644 index 0000000000..aec7079698 --- /dev/null +++ b/platform/android/src/style/layers/layer.cpp @@ -0,0 +1,158 @@ +#include "layer.hpp" +#include "../android_conversion.hpp" + +#include <jni/jni.hpp> + +#include <mbgl/platform/log.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/layer.hpp> +#include <mbgl/style/conversion/source.hpp> + +#include <string> + +namespace mbgl { +namespace android { + + /** + * Invoked when the construction is initiated from the jvm through a subclass + */ + Layer::Layer(jni::JNIEnv& env, std::unique_ptr<mbgl::style::Layer> coreLayer) + : ownedLayer(std::move(coreLayer)) + , layer(*ownedLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "Layer constructed, owning reference"); + } + + Layer::Layer(mbgl::Map& coreMap, mbgl::style::Layer& coreLayer) : layer(coreLayer) , map(&coreMap) { + mbgl::Log::Debug(mbgl::Event::JNI, "Non-owning reference constructor"); + } + + Layer::~Layer() { + mbgl::Log::Debug(mbgl::Event::JNI, "Layer destroyed"); + } + + jni::String Layer::getId(jni::JNIEnv& env) { + return jni::Make<jni::String>(env, layer.getID()); + } + + std::unique_ptr<mbgl::style::Layer> Layer::releaseCoreLayer() { + assert(ownedLayer != nullptr); + return std::move(ownedLayer); + } + + void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { + mbgl::Log::Debug(mbgl::Event::JNI, "Set layout property"); + + Value value(env, jvalue); + + //Convert and set property + optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setLayoutProperty(layer, jni::Make<std::string>(env, jname), value); + if (error) { + mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message); + return; + } + + //Update the style if attached + if (ownedLayer == nullptr) { + map->update(mbgl::Update::RecalculateStyle); + } + } + + void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { + mbgl::Log::Debug(mbgl::Event::JNI, "Set paint property"); + + Value value(env, jvalue); + + //Convert and set property + optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setPaintProperty(layer, jni::Make<std::string>(env, jname), value, mbgl::optional<std::string>()); + if (error) { + mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message); + return; + } + } + + void Layer::updateStyle(jni::JNIEnv&, jni::jboolean updateClasses) { + mbgl::Log::Debug(mbgl::Event::JNI, "Update style property. Update classes: " + std::to_string(updateClasses)); + + //Update the style only if attached + if (ownedLayer == nullptr) { + Update flags = mbgl::Update::RecalculateStyle; + if(updateClasses) { + flags = flags | mbgl::Update::Classes; + } + map->update(flags); + } else { + mbgl::Log::Debug(mbgl::Event::JNI, "Not updating as layer is not attached to map (yet)"); + } + } + + void Layer::setFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + mbgl::Log::Debug(mbgl::Event::JNI, "Set filter"); + + Value wrapped(env, jfilter); + Filter filter; + + Result<Filter> converted = convert<Filter>(wrapped); + if (!converted) { + mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + converted.error().message); + return; + } + filter = std::move(*converted); + + if (layer.is<FillLayer>()) { + layer.as<FillLayer>()->setFilter(filter); + } else if (layer.is<LineLayer>()) { + layer.as<LineLayer>()->setFilter(filter); + } else if (layer.is<SymbolLayer>()) { + layer.as<SymbolLayer>()->setFilter(filter); + } else if (layer.is<CircleLayer>()) { + layer.as<CircleLayer>()->setFilter(filter); + } else { + mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support filters"); + } + } + + void Layer::setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer) { + using namespace mbgl::style; + + std::string layerId = jni::Make<std::string>(env, sourceLayer); + mbgl::Log::Debug(mbgl::Event::JNI, "Set source layer: " + layerId); + + if (layer.is<FillLayer>()) { + layer.as<FillLayer>()->setSourceLayer(layerId); + } else if (layer.is<LineLayer>()) { + layer.as<LineLayer>()->setSourceLayer(layerId); + } else if (layer.is<SymbolLayer>()) { + layer.as<SymbolLayer>()->setSourceLayer(layerId); + } else if (layer.is<CircleLayer>()) { + layer.as<CircleLayer>()->setSourceLayer(layerId); + } else { + mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support source layer"); + } + } + + jni::Class<Layer> Layer::javaClass; + + void Layer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native base layer"); + + //Lookup the class + Layer::javaClass = *jni::Class<Layer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<Layer>(env, Layer::javaClass, "nativePtr", + METHOD(&Layer::getId, "nativeGetId"), + METHOD(&Layer::setLayoutProperty, "nativeSetLayoutProperty"), + METHOD(&Layer::setPaintProperty, "nativeSetPaintProperty"), + METHOD(&Layer::updateStyle, "nativeUpdateStyle"), + METHOD(&Layer::setFilter, "nativeSetFilter"), + METHOD(&Layer::setSourceLayer, "nativeSetSourceLayer") + ); + + } +} +}
\ No newline at end of file diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp new file mode 100644 index 0000000000..8b3487551b --- /dev/null +++ b/platform/android/src/style/layers/layer.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/map/map.hpp> +#include <mbgl/style/layer.hpp> + +#include "../value.hpp" + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class Layer : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/Layer"; }; + + static jni::Class<Layer> javaClass; + + static void registerNative(jni::JNIEnv&); + + /* + * Called when a Java object is created on the c++ side + */ + Layer(mbgl::Map&, mbgl::style::Layer&); + + /* + * Called when a Java object was created from the jvm side + */ + Layer(jni::JNIEnv&, std::unique_ptr<mbgl::style::Layer>); + + virtual ~Layer(); + + virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0; + + jni::String getId(jni::JNIEnv&); + + //Release the owned view and return it + std::unique_ptr<mbgl::style::Layer> releaseCoreLayer(); + + void setLayoutProperty(jni::JNIEnv&, jni::String, jni::Object<> value); + + void setPaintProperty(jni::JNIEnv&, jni::String, jni::Object<> value); + + void updateStyle(jni::JNIEnv&, jni::jboolean updateClasses); + + /* common properties, but not shared by all */ + + void setFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter); + + void setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer); + +protected: + std::unique_ptr<mbgl::style::Layer> ownedLayer; + mbgl::style::Layer& layer; + mbgl::Map* map; + +}; + +} //android +} //mbgl + + + + diff --git a/platform/android/src/style/layers/layers.cpp b/platform/android/src/style/layers/layers.cpp new file mode 100644 index 0000000000..4ccdc829f2 --- /dev/null +++ b/platform/android/src/style/layers/layers.cpp @@ -0,0 +1,60 @@ +#include "layers.hpp" + +#include <mbgl/style/layers/background_layer.hpp> +#include <mbgl/style/layers/circle_layer.hpp> +#include <mbgl/style/layers/fill_layer.hpp> +#include <mbgl/style/layers/line_layer.hpp> +#include <mbgl/style/layers/raster_layer.hpp> +#include <mbgl/style/layers/symbol_layer.hpp> + +#include "background_layer.hpp" +#include "circle_layer.hpp" +#include "fill_layer.hpp" +#include "line_layer.hpp" +#include "raster_layer.hpp" +#include "symbol_layer.hpp" + +namespace mbgl { +namespace android { + +Layer* initializeLayerPeer(mbgl::Map& map, mbgl::style::Layer& coreLayer) { + Layer* layer; + if (coreLayer.is<mbgl::style::BackgroundLayer>()) { + layer = new BackgroundLayer(map, *coreLayer.as<mbgl::style::BackgroundLayer>()); + } else if (coreLayer.is<mbgl::style::CircleLayer>()) { + layer = new CircleLayer(map, *coreLayer.as<mbgl::style::CircleLayer>()); + } else if (coreLayer.is<mbgl::style::FillLayer>()) { + layer = new FillLayer(map, *coreLayer.as<mbgl::style::FillLayer>()); + } else if (coreLayer.is<mbgl::style::LineLayer>()) { + layer = new LineLayer(map, *coreLayer.as<mbgl::style::LineLayer>()); + } else if (coreLayer.is<mbgl::style::RasterLayer>()) { + layer = new RasterLayer(map, *coreLayer.as<mbgl::style::RasterLayer>()); + } else if (coreLayer.is<mbgl::style::SymbolLayer>()) { + layer = new SymbolLayer(map, *coreLayer.as<mbgl::style::SymbolLayer>()); + } else { + throw new std::runtime_error("Layer type not implemented"); + } + + return layer; +} + +jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& coreLayer) { + std::unique_ptr<Layer> peerLayer = std::unique_ptr<Layer>(initializeLayerPeer(map, coreLayer)); + jni::jobject* result = peerLayer->createJavaPeer(env); + peerLayer.release(); + + return result; +} + +void registerNativeLayers(jni::JNIEnv& env) { + Layer::registerNative(env); + BackgroundLayer::registerNative(env); + CircleLayer::registerNative(env); + FillLayer::registerNative(env); + LineLayer::registerNative(env); + RasterLayer::registerNative(env); + SymbolLayer::registerNative(env); +} + +} +}
\ No newline at end of file diff --git a/platform/android/src/style/layers/layers.hpp b/platform/android/src/style/layers/layers.hpp new file mode 100644 index 0000000000..0c979ec2cf --- /dev/null +++ b/platform/android/src/style/layers/layers.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include <mbgl/map/map.hpp> +#include <mbgl/style/layer.hpp> + +#include "layer.hpp" + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +mbgl::android::Layer* initializeLayerPeer(mbgl::Map&, mbgl::style::Layer&); + +jni::jobject* createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&); + +void registerNativeLayers(jni::JNIEnv&); + +} +}
\ No newline at end of file diff --git a/platform/android/src/style/layers/line_layer.cpp b/platform/android/src/style/layers/line_layer.cpp new file mode 100644 index 0000000000..fdf2af7973 --- /dev/null +++ b/platform/android/src/style/layers/line_layer.cpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "line_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + + LineLayer::LineLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::LineLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { + mbgl::Log::Debug(mbgl::Event::JNI, "LineLayer constructed, owning reference"); + } + + LineLayer::LineLayer(mbgl::Map& map, mbgl::style::LineLayer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "LineLayer Non-owning reference constructor"); + } + + LineLayer::~LineLayer() = default; + + 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)); + } + + void LineLayer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + LineLayer::javaClass = *jni::Class<LineLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<LineLayer>( + env, LineLayer::javaClass, "nativePtr", + std::make_unique<LineLayer, JNIEnv&, jni::String, jni::String>, + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp new file mode 100644 index 0000000000..cb53d82940 --- /dev/null +++ b/platform/android/src/style/layers/line_layer.hpp @@ -0,0 +1,31 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/line_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class LineLayer : public Layer { +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); + + LineLayer(mbgl::Map&, mbgl::style::LineLayer&); + + ~LineLayer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/raster_layer.cpp b/platform/android/src/style/layers/raster_layer.cpp new file mode 100644 index 0000000000..3da246e128 --- /dev/null +++ b/platform/android/src/style/layers/raster_layer.cpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "raster_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + + RasterLayer::RasterLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::RasterLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { + mbgl::Log::Debug(mbgl::Event::JNI, "RasterLayer constructed, owning reference"); + } + + RasterLayer::RasterLayer(mbgl::Map& map, mbgl::style::RasterLayer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "RasterLayer Non-owning reference constructor"); + } + + RasterLayer::~RasterLayer() = default; + + 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)); + } + + void RasterLayer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + RasterLayer::javaClass = *jni::Class<RasterLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<RasterLayer>( + env, RasterLayer::javaClass, "nativePtr", + std::make_unique<RasterLayer, JNIEnv&, jni::String, jni::String>, + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp new file mode 100644 index 0000000000..f77771631c --- /dev/null +++ b/platform/android/src/style/layers/raster_layer.hpp @@ -0,0 +1,31 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/raster_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class RasterLayer : public Layer { +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); + + RasterLayer(mbgl::Map&, mbgl::style::RasterLayer&); + + ~RasterLayer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp new file mode 100644 index 0000000000..5de08f6511 --- /dev/null +++ b/platform/android/src/style/layers/symbol_layer.cpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "symbol_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + + SymbolLayer::SymbolLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::SymbolLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { + mbgl::Log::Debug(mbgl::Event::JNI, "SymbolLayer constructed, owning reference"); + } + + SymbolLayer::SymbolLayer(mbgl::Map& map, mbgl::style::SymbolLayer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "SymbolLayer Non-owning reference constructor"); + } + + SymbolLayer::~SymbolLayer() = default; + + 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)); + } + + void SymbolLayer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + SymbolLayer::javaClass = *jni::Class<SymbolLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<SymbolLayer>( + env, SymbolLayer::javaClass, "nativePtr", + std::make_unique<SymbolLayer, JNIEnv&, jni::String, jni::String>, + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp new file mode 100644 index 0000000000..3f3b0e1fe6 --- /dev/null +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -0,0 +1,31 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/symbol_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class SymbolLayer : public Layer { +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); + + SymbolLayer(mbgl::Map&, mbgl::style::SymbolLayer&); + + ~SymbolLayer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/sources/sources.cpp b/platform/android/src/style/sources/sources.cpp new file mode 100644 index 0000000000..47c9757e9d --- /dev/null +++ b/platform/android/src/style/sources/sources.cpp @@ -0,0 +1,28 @@ +#include "sources.hpp" + +#include "../value.hpp" +#include "../android_conversion.hpp" +#include "../android_geojson.hpp" + +#include <mbgl/util/constants.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/source.hpp> + +#include <string> + +namespace mbgl { +namespace android { + + mbgl::optional<std::unique_ptr<mbgl::style::Source>> convertToNativeSource(jni::JNIEnv& env, jni::Object<jni::jobject> jvalue, jni::String id) { + using namespace mbgl::style; + + Value value(env, jvalue); + conversion::Result<std::unique_ptr<Source>> source = conversion::convert<std::unique_ptr<Source>>(value, jni::Make<std::string>(env, id)); + if (!source) { + mbgl::Log::Error(mbgl::Event::JNI, "Unable to add source: " + source.error().message); + return {}; + } + return std::move(*source); + } +} +}
\ No newline at end of file diff --git a/platform/android/src/style/sources/sources.hpp b/platform/android/src/style/sources/sources.hpp new file mode 100644 index 0000000000..b967685dfb --- /dev/null +++ b/platform/android/src/style/sources/sources.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include <mbgl/style/source.hpp> +#include <mbgl/util/optional.hpp> + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + + mbgl::optional<std::unique_ptr<mbgl::style::Source>> convertToNativeSource(jni::JNIEnv& env, jni::Object<jni::jobject> jsource, jni::String id); + +} +}
\ No newline at end of file diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp new file mode 100644 index 0000000000..daad3e998d --- /dev/null +++ b/platform/android/src/style/value.cpp @@ -0,0 +1,67 @@ +#include "value.hpp" + +#include "../java_types.hpp" + +namespace mbgl { +namespace android { + + //Instance + + Value::Value(jni::JNIEnv& env, jni::jobject* _value) : jenv(env), value(_value) {} + + Value::~Value() {} + + bool Value::isNull() const { + return value == nullptr; + } + + bool Value::isArray() const { + return jni::IsInstanceOf(jenv, value, *java::ObjectArray::jclass); + } + + bool Value::isObject() const { + return jni::IsInstanceOf(jenv, value, *java::Map::jclass);; + } + + bool Value::isString() const { + return jni::IsInstanceOf(jenv, value, *java::String::jclass); + } + + bool Value::isBool() const { + return jni::IsInstanceOf(jenv, value, *java::Boolean::jclass); + } + + bool Value::isNumber() const { + return jni::IsInstanceOf(jenv, value, *java::Number::jclass); + } + + std::string Value::toString() const { + jni::jstring* string = reinterpret_cast<jni::jstring*>(value); + return jni::Make<std::string>(jenv, jni::String(string)); + } + + float Value::toNumber() const { + return jni::CallMethod<jni::jfloat>(jenv, value, *java::Number::floatValueMethodId); + } + + bool Value::toBool() const { + return jni::CallMethod<jni::jboolean>(jenv, value, *java::Boolean::booleanValueMethodId); + } + + Value Value::get(const char* key) const { + jni::jobject* member = jni::CallMethod<jni::jobject*>(jenv, value, *java::Map::getMethodId, jni::Make<jni::String>(jenv, std::string(key)).Get()); + return Value(jenv, member); + } + + int Value::getLength() const { + auto array = (jni::jarray<jni::jobject>*) value; + return jni::GetArrayLength(jenv, *array); + } + + Value Value::get(const int index ) const { + auto array = (jni::jarray<jni::jobject>*) value; + return Value(jenv, jni::GetObjectArrayElement(jenv, *array, index)); + } +} +} + diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp new file mode 100644 index 0000000000..2f0b1d9706 --- /dev/null +++ b/platform/android/src/style/value.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <jni/jni.hpp> + +#include <string> + +namespace mbgl { +namespace android { + +class Value { +public: + + Value(jni::JNIEnv&, jni::jobject*); + virtual ~Value(); + + bool isNull() const; + bool isArray() const; + bool isObject() const; + bool isString() const; + bool isBool() const; + bool isNumber() const; + + std::string toString() const; + float toNumber() const; + bool toBool() const; + Value get(const char* key) const; + int getLength() const; + Value get(const int index ) const; + + jni::JNIEnv& jenv; + jni::jobject* value; +}; + +} +} |