summaryrefslogtreecommitdiff
path: root/platform/android/src
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/src')
-rw-r--r--platform/android/src/java_types.cpp37
-rw-r--r--platform/android/src/java_types.hpp35
-rwxr-xr-xplatform/android/src/jni.cpp87
-rw-r--r--platform/android/src/style/android_conversion.hpp95
-rw-r--r--platform/android/src/style/android_geojson.hpp48
-rw-r--r--platform/android/src/style/layers/background_layer.cpp52
-rw-r--r--platform/android/src/style/layers/background_layer.hpp31
-rw-r--r--platform/android/src/style/layers/circle_layer.cpp52
-rw-r--r--platform/android/src/style/layers/circle_layer.hpp31
-rw-r--r--platform/android/src/style/layers/fill_layer.cpp52
-rw-r--r--platform/android/src/style/layers/fill_layer.hpp31
-rw-r--r--platform/android/src/style/layers/layer.cpp158
-rw-r--r--platform/android/src/style/layers/layer.hpp66
-rw-r--r--platform/android/src/style/layers/layers.cpp60
-rw-r--r--platform/android/src/style/layers/layers.hpp20
-rw-r--r--platform/android/src/style/layers/line_layer.cpp52
-rw-r--r--platform/android/src/style/layers/line_layer.hpp31
-rw-r--r--platform/android/src/style/layers/raster_layer.cpp52
-rw-r--r--platform/android/src/style/layers/raster_layer.hpp31
-rw-r--r--platform/android/src/style/layers/symbol_layer.cpp52
-rw-r--r--platform/android/src/style/layers/symbol_layer.hpp31
-rw-r--r--platform/android/src/style/sources/sources.cpp28
-rw-r--r--platform/android/src/style/sources/sources.hpp14
-rw-r--r--platform/android/src/style/value.cpp67
-rw-r--r--platform/android/src/style/value.hpp35
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;
+};
+
+}
+}