summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-12-11 16:04:40 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-12-16 11:03:32 -0800
commit8a17d30c50f46b5c702807a840bbfb6395eb456e (patch)
tree94952de29122f9694ca07c032073697dcd0e0fc9
parente304033552fd423db5324545216f9cf3a1e62150 (diff)
downloadqtlocation-mapboxgl-8a17d30c50f46b5c702807a840bbfb6395eb456e.tar.gz
[android] Custom layer bindings
-rw-r--r--android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java21
-rw-r--r--android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java4
-rw-r--r--android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java6
-rw-r--r--android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java7
-rw-r--r--android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java12
-rw-r--r--android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java15
-rw-r--r--android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml6
-rw-r--r--android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml1
-rw-r--r--platform/android/example_custom_layer.cpp104
-rw-r--r--platform/android/jni.cpp52
-rw-r--r--platform/android/mapboxgl-app.gypi43
-rw-r--r--src/mbgl/map/map_context.cpp2
12 files changed, 272 insertions, 1 deletions
diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java
new file mode 100644
index 0000000000..f6fb297dc6
--- /dev/null
+++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java
@@ -0,0 +1,21 @@
+package com.mapbox.mapboxsdk.layers;
+
+public class CustomLayer {
+ public CustomLayer(String id,
+ long context,
+ long initializeFunction,
+ long renderFunction,
+ long deinitializeFunction) {
+ this.mID = id;
+ this.mContext = context;
+ this.mInitializeFunction = initializeFunction;
+ this.mRenderFunction = renderFunction;
+ this.mDeinitializeFunction = deinitializeFunction;
+ }
+
+ public String mID;
+ public long mContext;
+ public long mInitializeFunction;
+ public long mRenderFunction;
+ public long mDeinitializeFunction;
+}
diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java
new file mode 100644
index 0000000000..fda1a493e2
--- /dev/null
+++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * This package contains classes to add and manage layers in your map.
+ */
+package com.mapbox.mapboxsdk.layers;
diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java
index 94cfe23f86..157f1ae955 100644
--- a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java
+++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java
@@ -74,6 +74,7 @@ import com.mapbox.mapboxsdk.geometry.BoundingBox;
import com.mapbox.mapboxsdk.geometry.CoordinateBounds;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngZoom;
+import com.mapbox.mapboxsdk.layers.CustomLayer;
import com.mapbox.mapboxsdk.utils.ApiAccess;
import java.lang.annotation.Retention;
@@ -3782,6 +3783,11 @@ public final class MapView extends FrameLayout {
mAttributionsView.setVisibility(visibility);
}
+ @UiThread
+ public void addCustomLayer(CustomLayer customLayer, String before) {
+ mNativeMapView.addCustomLayer(customLayer, before);
+ }
+
private void setWidgetGravity(@NonNull final View view, int gravity) {
LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
layoutParams.gravity = gravity;
diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java
index f09d0e9027..c142670775 100644
--- a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java
+++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java
@@ -11,6 +11,7 @@ import com.mapbox.mapboxsdk.geometry.BoundingBox;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngZoom;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
+import com.mapbox.mapboxsdk.layers.CustomLayer;
import java.lang.ref.WeakReference;
import java.util.List;
@@ -449,6 +450,10 @@ final class NativeMapView {
return nativeGetTopOffsetPixelsForAnnotationSymbol(mNativeMapViewPtr, symbolName);
}
+ public void addCustomLayer(CustomLayer customLayer, String before) {
+ nativeAddCustomLayer(mNativeMapViewPtr, customLayer, before);
+ }
+
//
// Callbacks
//
@@ -629,4 +634,6 @@ final class NativeMapView {
private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, PointF pixel);
private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName);
+
+ private native void nativeAddCustomLayer(long nativeMapViewPtr, CustomLayer customLayer, String before);
}
diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java
new file mode 100644
index 0000000000..e6c7992145
--- /dev/null
+++ b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java
@@ -0,0 +1,12 @@
+package com.mapbox.mapboxsdk.testapp;
+
+public class ExampleCustomLayer {
+ static {
+ System.loadLibrary("example-custom-layer");
+ }
+
+ public native static long createContext();
+ public static long InitializeFunction;
+ public static long RenderFunction;
+ public static long DeinitializeFunction;
+}
diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java
index c303d94cdc..c6ec8cbd77 100644
--- a/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java
+++ b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java
@@ -34,6 +34,7 @@ import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.layers.CustomLayer;
import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil;
import com.mapbox.mapboxsdk.utils.ApiAccess;
import com.mapbox.mapboxsdk.views.MapView;
@@ -395,6 +396,10 @@ public class MainActivity extends AppCompatActivity {
startActivity(new Intent(getApplicationContext(), PolylineActivity.class));
return true;
+ case R.id.action_custom_layer:
+ addCustomLayer();
+ return true;
+
default:
return changeMapStyle(menuItem.getItemId());
}
@@ -570,6 +575,16 @@ public class MainActivity extends AppCompatActivity {
mMapView.removeAllAnnotations();
}
+ private void addCustomLayer() {
+ mMapView.addCustomLayer(
+ new CustomLayer("custom",
+ ExampleCustomLayer.createContext(),
+ ExampleCustomLayer.InitializeFunction,
+ ExampleCustomLayer.RenderFunction,
+ ExampleCustomLayer.DeinitializeFunction),
+ null);
+ }
+
// Called when FPS changes
private class MyOnFpsChangedListener implements MapView.OnFpsChangedListener {
diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml b/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml
index bfd70a936f..9a81182837 100644
--- a/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml
+++ b/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml
@@ -138,6 +138,12 @@
android:icon="@drawable/ic_trending_up_24dp"
android:title="@string/activity_polyline" />
+ <item
+ android:id="@+id/action_custom_layer"
+ android:checkable="false"
+ android:icon="@drawable/ic_trending_up_24dp"
+ android:title="@string/activity_custom_layer" />
+
</menu>
</item>
diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index 8cc299e39f..10d622d38f 100644
--- a/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -16,6 +16,7 @@
<string name="activity_user_tracking_mode">User tracking mode</string>
<string name="activity_polyline">Polyline Activity</string>
<string name="activity_animate_coordinate_change">Animate Coordinate Change</string>
+ <string name="activity_custom_layer">Custom Layer</string>
<string name="navdrawer_menu_title_mainactivity_controls">Main Activity Controls</string>
<string name="navdrawer_menu_title_mainactivity_styles">Main Activity Styles</string>
diff --git a/platform/android/example_custom_layer.cpp b/platform/android/example_custom_layer.cpp
new file mode 100644
index 0000000000..e853545358
--- /dev/null
+++ b/platform/android/example_custom_layer.cpp
@@ -0,0 +1,104 @@
+#include <jni.h>
+#include <GLES2/gl2.h>
+
+static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
+static const GLchar * fragmentShaderSource = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }";
+
+class ExampleCustomLayer {
+public:
+ ~ExampleCustomLayer() {
+ if (program) {
+ glDeleteBuffers(1, &buffer);
+ glDetachShader(program, vertexShader);
+ glDetachShader(program, fragmentShader);
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ glDeleteProgram(program);
+ }
+ }
+
+ void initialize() {
+ program = glCreateProgram();
+ vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
+ glCompileShader(vertexShader);
+ glAttachShader(program, vertexShader);
+ glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
+ glCompileShader(fragmentShader);
+ glAttachShader(program, fragmentShader);
+ glLinkProgram(program);
+ a_pos = glGetAttribLocation(program, "a_pos");
+
+ GLfloat background[] = { -1,-1, 1,-1, -1,1, 1,1 };
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW);
+ }
+
+ void render() {
+ glUseProgram(program);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ GLuint program = 0;
+ GLuint vertexShader = 0;
+ GLuint fragmentShader = 0;
+ GLuint buffer = 0;
+ GLuint a_pos = 0;
+};
+
+jlong JNICALL nativeCreateContext(JNIEnv*, jobject) {
+ return reinterpret_cast<jlong>(new ExampleCustomLayer());
+}
+
+void nativeInitialize(void *context) {
+ reinterpret_cast<ExampleCustomLayer*>(context)->initialize();
+}
+
+void nativeRender(void *context) {
+ reinterpret_cast<ExampleCustomLayer*>(context)->render();
+}
+
+void nativeDenitialize(void *context) {
+ delete reinterpret_cast<ExampleCustomLayer*>(context);
+}
+
+extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
+ JNIEnv *env = nullptr;
+ vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
+
+ jclass customLayerClass = env->FindClass("com/mapbox/mapboxsdk/testapp/ExampleCustomLayer");
+
+ JNINativeMethod methods[] = {
+ {"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)}
+ };
+
+ if (env->RegisterNatives(customLayerClass, methods, 1) < 0) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ env->SetStaticLongField(customLayerClass,
+ env->GetStaticFieldID(customLayerClass, "InitializeFunction", "J"),
+ reinterpret_cast<jlong>(nativeInitialize));
+
+ env->SetStaticLongField(customLayerClass,
+ env->GetStaticFieldID(customLayerClass, "RenderFunction", "J"),
+ reinterpret_cast<jlong>(nativeRender));
+
+ env->SetStaticLongField(customLayerClass,
+ env->GetStaticFieldID(customLayerClass, "DeinitializeFunction", "J"),
+ reinterpret_cast<jlong>(nativeDenitialize));
+
+ return JNI_VERSION_1_6;
+}
+
+extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *) {
+}
diff --git a/platform/android/jni.cpp b/platform/android/jni.cpp
index acefc87f31..fc657a6cb0 100644
--- a/platform/android/jni.cpp
+++ b/platform/android/jni.cpp
@@ -111,6 +111,13 @@ jclass httpRequestClass = nullptr;
jmethodID httpRequestStartId = nullptr;
jmethodID httpRequestCancelId = nullptr;
+jclass customLayerClass = nullptr;
+jfieldID customLayerIdId = nullptr;
+jfieldID customLayerContextId = nullptr;
+jfieldID customLayerInitializeFunctionId = nullptr;
+jfieldID customLayerRenderFunctionId = nullptr;
+jfieldID customLayerDeinitializeFunctionId = nullptr;
+
bool throw_jni_error(JNIEnv *env, const char *msg) {
if (env->ThrowNew(runtimeExceptionClass, msg) < 0) {
env->ExceptionDescribe();
@@ -1471,6 +1478,19 @@ jdouble JNICALL nativeGetTopOffsetPixelsForAnnotationSymbol(JNIEnv *env, jobject
return nativeMapView->getMap().getTopOffsetPixelsForAnnotationIcon(std_string_from_jstring(env, symbolName));
}
+void JNICALL nativeAddCustomLayer(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject customLayer, jstring before) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddCustomLayer");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ nativeMapView->getMap().addCustomLayer(
+ std_string_from_jstring(env, reinterpret_cast<jstring>(env->GetObjectField(customLayer, customLayerIdId))),
+ reinterpret_cast<mbgl::CustomLayerInitializeFunction>(env->GetLongField(customLayer, customLayerInitializeFunctionId)),
+ reinterpret_cast<mbgl::CustomLayerRenderFunction>(env->GetLongField(customLayer, customLayerRenderFunctionId)),
+ reinterpret_cast<mbgl::CustomLayerDeinitializeFunction>(env->GetLongField(customLayer, customLayerDeinitializeFunctionId)),
+ reinterpret_cast<void*>(env->GetLongField(customLayer, customLayerContextId)),
+ before ? std_string_from_jstring(env, before).c_str() : nullptr);
+}
+
}
@@ -1848,6 +1868,36 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
env->ExceptionDescribe();
}
+ customLayerClass = env->FindClass("com/mapbox/mapboxsdk/layers/CustomLayer");
+ if (customLayerClass == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ customLayerIdId = env->GetFieldID(customLayerClass, "mID", "Ljava/lang/String;");
+ if (customLayerIdId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ customLayerContextId = env->GetFieldID(customLayerClass, "mContext", "J");
+ if (customLayerContextId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ customLayerInitializeFunctionId = env->GetFieldID(customLayerClass, "mInitializeFunction", "J");
+ if (customLayerInitializeFunctionId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ customLayerRenderFunctionId = env->GetFieldID(customLayerClass, "mRenderFunction", "J");
+ if (customLayerRenderFunctionId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ customLayerDeinitializeFunctionId = env->GetFieldID(customLayerClass, "mDeinitializeFunction", "J");
+ if (customLayerDeinitializeFunctionId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
const std::vector<JNINativeMethod> methods = {
{"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;FIJ)J",
reinterpret_cast<void *>(&nativeCreate)},
@@ -1965,6 +2015,8 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
reinterpret_cast<void *>(&nativeLatLngForPixel)},
{"nativeGetTopOffsetPixelsForAnnotationSymbol", "(JLjava/lang/String;)D",
reinterpret_cast<void *>(&nativeGetTopOffsetPixelsForAnnotationSymbol)},
+ {"nativeAddCustomLayer", "(JLcom/mapbox/mapboxsdk/layers/CustomLayer;Ljava/lang/String;)V",
+ reinterpret_cast<void *>(&nativeAddCustomLayer)},
};
if (env->RegisterNatives(nativeMapViewClass, methods.data(), methods.size()) < 0) {
diff --git a/platform/android/mapboxgl-app.gypi b/platform/android/mapboxgl-app.gypi
index 8080b29cd8..ced569a4bc 100644
--- a/platform/android/mapboxgl-app.gypi
+++ b/platform/android/mapboxgl-app.gypi
@@ -59,11 +59,46 @@
],
},
+ { 'target_name': 'example-custom-layer-lib',
+ 'product_name': 'example-custom-layer',
+ 'type': 'shared_library',
+ 'hard_dependency': 1,
+
+ 'sources': [
+ './example_custom_layer.cpp',
+ ],
+
+ 'variables': {
+ 'ldflags': [
+ '-llog',
+ '-landroid',
+ '-lEGL',
+ '-lGLESv2',
+ '-lstdc++',
+ '-latomic',
+ ],
+ },
+
+ 'conditions': [
+ ['OS == "mac"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [ '<@(ldflags)' ],
+ }
+ }, {
+ 'libraries': [ '<@(ldflags)' ],
+ }]
+ ],
+ },
{ 'target_name': 'androidapp',
'type': 'none',
'hard_dependency': 1,
+ 'dependencies': [
+ 'android-lib',
+ 'example-custom-layer-lib',
+ ],
+
'variables': {
'pwd': '<!(pwd)',
},
@@ -85,11 +120,17 @@
'actions': [
{
- 'action_name': 'Strip dynamic library',
+ 'action_name': 'Strip mapbox library',
'inputs': [ '<(PRODUCT_DIR)/lib.target/libmapbox-gl.so' ],
'outputs': [ '<(pwd)/../android/MapboxGLAndroidSDK/src/main/jniLibs/$(JNIDIR)/libmapbox-gl.so' ],
'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ]
},
+ {
+ 'action_name': 'Strip example custom layer library',
+ 'inputs': [ '<(PRODUCT_DIR)/lib.target/libexample-custom-layer.so' ],
+ 'outputs': [ '<(pwd)/../android/MapboxGLAndroidSDKTestApp/src/main/jniLibs/$(JNIDIR)/libexample-custom-layer.so' ],
+ 'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ]
+ }
],
},
],
diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp
index 179df004a7..96f4a68d9b 100644
--- a/src/mbgl/map/map_context.cpp
+++ b/src/mbgl/map/map_context.cpp
@@ -285,6 +285,8 @@ double MapContext::getTopOffsetPixelsForAnnotationIcon(const std::string& name)
void MapContext::addLayer(std::unique_ptr<StyleLayer> layer, mapbox::util::optional<std::string> after) {
style->addLayer(std::move(layer), after);
+ updateFlags |= Update::Classes;
+ asyncUpdate.send();
}
void MapContext::setSourceTileCacheSize(size_t size) {