summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Leege <bleege@gmail.com>2015-07-22 10:15:34 -0500
committerBrad Leege <bleege@gmail.com>2015-07-22 10:15:34 -0500
commit93e1ced3bb0f204ff7747bd13e563959be8d35ae (patch)
tree825b40aaaf8ff7d4645353041a23d04778de5ff7
parent38f3bed63ece0214d02a755991ee7f1d7b54ba10 (diff)
parent0f56c2b0d5766996d51c73f5e131ec8df21d5fca (diff)
downloadqtlocation-mapboxgl-93e1ced3bb0f204ff7747bd13e563959be8d35ae.tar.gz
Merge branch 'android-annotations' of git://github.com/hallahan/mapbox-gl-native into hallahan-android-annotations
-rw-r--r--android/cpp/jni.cpp418
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java64
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/AnnotationOptions.java22
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Circle.java67
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/CircleOptions.java64
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java154
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MarkerOptions.java125
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPoint.java53
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPointOptions.java15
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polygon.java99
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolygonOptions.java125
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polyline.java51
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolylineOptions.java75
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java55
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java30
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_line.geojson1
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_poly.geojson1
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java93
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java3
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/Util.java61
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_main.xml12
-rw-r--r--android/java/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml2
22 files changed, 1584 insertions, 6 deletions
diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp
index cfb1291bcd..1e2288c61b 100644
--- a/android/cpp/jni.cpp
+++ b/android/cpp/jni.cpp
@@ -16,6 +16,8 @@
#include <mbgl/android/jni.hpp>
#include <mbgl/android/native_map_view.hpp>
#include <mbgl/map/map.hpp>
+#include <mbgl/annotation/point_annotation.hpp>
+#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/platform/event.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/storage/network_status.hpp>
@@ -39,6 +41,30 @@ jmethodID latLngConstructorId = nullptr;
jfieldID latLngLatitudeId = nullptr;
jfieldID latLngLongitudeId = nullptr;
+jclass markerClass = nullptr;
+jmethodID markerConstructorId = nullptr;
+jfieldID markerPositionId = nullptr;
+jfieldID markerSpriteId = nullptr;
+
+jclass polylineClass = nullptr;
+jmethodID polylineConstructorId = nullptr;
+jfieldID polylineAlphaId = nullptr;
+jfieldID polylineVisibleId = nullptr;
+jfieldID polylineColorId = nullptr;
+jfieldID polylineWidthId = nullptr;
+jfieldID polylinePointsId = nullptr;
+
+jclass polygonClass = nullptr;
+jmethodID polygonConstructorId = nullptr;
+jfieldID polygonAlphaId = nullptr;
+jfieldID polygonVisibleId = nullptr;
+jfieldID polygonFillColorId = nullptr;
+jfieldID polygonStrokeColorId = nullptr;
+jfieldID polygonStrokeWidthId = nullptr;
+jfieldID polygonPointsId = nullptr;
+jfieldID polygonHolesId = nullptr;
+
+
jclass latLngZoomClass = nullptr;
jmethodID latLngZoomConstructorId = nullptr;
jfieldID latLngZoomLatitudeId = nullptr;
@@ -155,6 +181,56 @@ std::vector<std::string> std_vector_string_from_jobject(JNIEnv *env, jobject jli
return vector;
}
+mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobject jlist) {
+ mbgl::AnnotationSegment segment;
+
+ if (jlist == nullptr) {
+ if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+ return segment;
+ }
+
+ jobjectArray array =
+ reinterpret_cast<jobjectArray>(env->CallObjectMethod(jlist, listToArrayId));
+ if (env->ExceptionCheck() || (array == nullptr)) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ jsize len = env->GetArrayLength(array);
+ if (len < 0) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ segment.reserve(len);
+
+ for (jsize i = 0; i < len; i++) {
+ jobject latLng = reinterpret_cast<jobject>(env->GetObjectArrayElement(array, i));
+ if (latLng == nullptr) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ segment.push_back(mbgl::LatLng(latitude, longitude));
+ }
+ return segment;
+}
+
jobject std_vector_string_to_jobject(JNIEnv *env, std::vector<std::string> vector) {
jobject jlist = env->NewObject(arrayListClass, arrayListConstructorId);
if (jlist == nullptr) {
@@ -433,6 +509,176 @@ void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, j
nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration));
}
+jlong JNICALL nativeAddMarker(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject marker) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+
+ jobject position = env->GetObjectField(marker, markerPositionId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jstring jsprite = (jstring)env->GetObjectField(marker, markerSpriteId);
+ std::string sprite = std_string_from_jstring(env, jsprite);
+
+ jdouble latitude = env->GetDoubleField(position, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jdouble longitude = env->GetDoubleField(position, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
+ return (jlong) nativeMapView->getMap().addPointAnnotation(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), sprite));
+}
+
+jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polyline) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolyline");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+
+ // ***** Java fields ***** //
+ // float alpha;
+ // boolean visible;
+ // int color
+ // float width
+ // List<LatLng> points
+
+ jfloat alpha = env->GetFloatField(polyline, polylineAlphaId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jboolean visible = env->GetBooleanField(polyline, polylineVisibleId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+ visible = JNI_TRUE;
+
+ jint color = env->GetIntField(polyline, polylineColorId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ int r = (color>>16)&0xFF;
+ int g = (color>>8)&0xFF;
+ int b = (color)&0xFF;
+ int a = (color>>24)&0xFF;
+
+ jfloat width = env->GetFloatField(polyline, polylineWidthId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ mbgl::StyleProperties shapeProperties;
+ mbgl::LineProperties lineProperties;
+ lineProperties.opacity = alpha;
+ lineProperties.color = {{ (float)r, (float)g, (float)b, (float)a }};
+ lineProperties.width = width;
+ shapeProperties.set<mbgl::LineProperties>(lineProperties);
+
+ jobject points = env->GetObjectField(polyline, polylinePointsId);
+ mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
+
+ std::vector<mbgl::ShapeAnnotation> shapes;
+ shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties);
+
+ std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
+ uint32_t id = shapeAnnotationIDs.at(0);
+ return (jlong) id;
+}
+
+jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polygon) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygon");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+
+ // ***** Java fields ***** //
+ // float alpha;
+ // boolean visible;
+ // int fillColor
+ // int strokeColor
+ // float strokeWidth
+ // List<LatLng> points
+ // List<List<LatLng>> holes
+
+ jfloat alpha = env->GetFloatField(polygon, polygonAlphaId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jboolean visible = env->GetBooleanField(polygon, polygonVisibleId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+ visible = JNI_TRUE;
+
+ jint fillColor = env->GetIntField(polygon, polygonFillColorId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ int rF = (fillColor>>16)&0xFF;
+ int gF = (fillColor>>8)&0xFF;
+ int bF = (fillColor)&0xFF;
+ int aF = (fillColor>>24)&0xFF;
+
+ int rS = (strokeColor>>16)&0xFF;
+ int gS = (strokeColor>>8)&0xFF;
+ int bS = (strokeColor)&0xFF;
+ int aS = (strokeColor>>24)&0xFF;
+
+ // jfloat strokeWidth = env->GetFloatField(polygon, polygonStrokeWidthId);
+ // if (env->ExceptionCheck()) {
+ // env->ExceptionDescribe();
+ // return -1;
+ // }
+
+ mbgl::StyleProperties shapeProperties;
+ mbgl::FillProperties fillProperties;
+ fillProperties.opacity = alpha;
+ fillProperties.stroke_color = {{ (float)rS, (float)gS, (float)bS, (float)aS }};
+ fillProperties.fill_color = {{ (float)rF, (float)gF, (float)bF, (float)aF }};
+ shapeProperties.set<mbgl::FillProperties>(fillProperties);
+
+ jobject points = env->GetObjectField(polygon, polygonPointsId);
+ mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
+
+ std::vector<mbgl::ShapeAnnotation> shapes;
+ shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties);
+
+ std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
+ uint32_t id = shapeAnnotationIDs.at(0);
+ return (jlong) id;
+}
+
+void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong annotationId) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ nativeMapView->getMap().removeAnnotation((uint32_t)annotationId);
+}
+
jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng");
assert(nativeMapViewPtr != 0);
@@ -783,6 +1029,126 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_ERR;
}
+ markerClass = env->FindClass("com/mapbox/mapboxgl/annotations/Marker");
+ if (markerClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerConstructorId = env->GetMethodID(markerClass, "<init>", "()V");
+ if (markerConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerPositionId = env->GetFieldID(markerClass, "position", "Lcom/mapbox/mapboxgl/geometry/LatLng;");
+ if (markerPositionId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerSpriteId = env->GetFieldID(markerClass, "sprite", "Ljava/lang/String;");
+ if (markerSpriteId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineClass = env->FindClass("com/mapbox/mapboxgl/annotations/Polyline");
+ if (polylineClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineConstructorId = env->GetMethodID(polylineClass, "<init>", "()V");
+ if (polylineConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineAlphaId = env->GetFieldID(polylineClass, "alpha", "F");
+ if (polylineAlphaId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineVisibleId = env->GetFieldID(polylineClass, "visible", "Z");
+ if (polylineVisibleId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineColorId = env->GetFieldID(polylineClass, "color", "I");
+ if (polylineColorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineWidthId = env->GetFieldID(polylineClass, "width", "F");
+ if (polylineWidthId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylinePointsId = env->GetFieldID(polylineClass, "points", "Ljava/util/List;");
+ if (polylineWidthId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonClass = env->FindClass("com/mapbox/mapboxgl/annotations/Polygon");
+ if (polygonClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonConstructorId = env->GetMethodID(polygonClass, "<init>", "()V");
+ if (polygonConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonAlphaId = env->GetFieldID(polygonClass, "alpha", "F");
+ if (polygonAlphaId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonVisibleId = env->GetFieldID(polygonClass, "visible", "Z");
+ if (polygonVisibleId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonFillColorId = env->GetFieldID(polygonClass, "fillColor", "I");
+ if (polygonFillColorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonStrokeColorId = env->GetFieldID(polygonClass, "strokeColor", "I");
+ if (polygonStrokeColorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonStrokeWidthId = env->GetFieldID(polygonClass, "strokeWidth", "F");
+ if (polygonStrokeWidthId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonPointsId = env->GetFieldID(polygonClass, "points", "Ljava/util/List;");
+ if (polygonPointsId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonHolesId = env->GetFieldID(polygonClass, "holes", "Ljava/util/List;");
+ if (polygonHolesId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom");
if (latLngZoomClass == nullptr) {
env->ExceptionDescribe();
@@ -976,6 +1342,13 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
{"nativeMoveBy", "(JDDJ)V", reinterpret_cast<void *>(&nativeMoveBy)},
{"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V",
reinterpret_cast<void *>(&nativeSetLatLng)},
+ {"nativeAddMarker", "(JLcom/mapbox/mapboxgl/annotations/Marker;)J",
+ reinterpret_cast<void *>(&nativeAddMarker)},
+ {"nativeAddPolyline", "(JLcom/mapbox/mapboxgl/annotations/Polyline;)J",
+ reinterpret_cast<void *>(&nativeAddPolyline)},
+ {"nativeAddPolygon", "(JLcom/mapbox/mapboxgl/annotations/Polygon;)J",
+ reinterpret_cast<void *>(&nativeAddPolygon)},
+ {"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast<void *>(&nativeRemoveAnnotation)},
{"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;",
reinterpret_cast<void *>(&nativeGetLatLng)},
{"nativeResetPosition", "(J)V", reinterpret_cast<void *>(&nativeResetPosition)},
@@ -1026,6 +1399,24 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_ERR;
}
+ markerClass = reinterpret_cast<jclass>(env->NewGlobalRef(markerClass));
+ if (markerClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineClass = reinterpret_cast<jclass>(env->NewGlobalRef(polylineClass));
+ if (polylineClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonClass = reinterpret_cast<jclass>(env->NewGlobalRef(polygonClass));
+ if (polygonClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
latLngZoomClass = reinterpret_cast<jclass>(env->NewGlobalRef(latLngZoomClass));
if (latLngZoomClass == nullptr) {
env->ExceptionDescribe();
@@ -1109,6 +1500,33 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
latLngLongitudeId = nullptr;
latLngLatitudeId = nullptr;
+ env->DeleteGlobalRef(markerClass);
+ markerClass = nullptr;
+ markerConstructorId = nullptr;
+ markerPositionId = nullptr;
+ markerSpriteId = nullptr;
+
+ env->DeleteGlobalRef(polylineClass);
+ polylineClass = nullptr;
+ polylineConstructorId = nullptr;
+ polylineAlphaId = nullptr;
+ polylineVisibleId = nullptr;
+ polylineColorId = nullptr;
+ polylineWidthId = nullptr;
+ polylinePointsId = nullptr;
+
+ env->DeleteGlobalRef(polygonClass);
+ polygonClass = nullptr;
+ polygonConstructorId = nullptr;
+ polygonAlphaId = nullptr;
+ polygonVisibleId = nullptr;
+ polygonFillColorId = nullptr;
+ polygonStrokeColorId = nullptr;
+ polygonStrokeWidthId = nullptr;
+ polygonPointsId = nullptr;
+ polygonHolesId = nullptr;
+
+
env->DeleteGlobalRef(latLngZoomClass);
latLngZoomClass = nullptr;
latLngZoomConstructorId = nullptr;
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java
new file mode 100644
index 0000000000..e38af77cd8
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Annotation.java
@@ -0,0 +1,64 @@
+package com.mapbox.mapboxgl.annotations;
+
+import com.mapbox.mapboxgl.views.MapView;
+
+
+public abstract class Annotation {
+
+ /**
+ * The annotation id
+ *
+ * Internal C++ id is stored as unsigned int.
+ */
+ protected Long id; // null unless added to a MapView
+ private MapView mapView;
+
+ float alpha = 1;
+ boolean visible = true;
+
+
+ public Annotation() {}
+
+ public float getAlpha() {
+ return alpha;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public boolean isVisible() {
+ return visible;
+ }
+
+ public void remove() {
+ if (mapView == null) return;
+ mapView.removeAnnotation(this);
+ }
+
+ public void setAlpha(float alpha) {
+ this.alpha = alpha;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public void setMapView(MapView mapView) {
+ this.mapView = mapView;
+ }
+
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ // TODO: Implement getZIndex of Google Maps Android API
+// public float getZIndex() {
+//
+// }
+
+ // TODO: Implement setZIndex of Google Maps Android API
+// public void setZIndex(float zIndex) {
+//
+// }
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/AnnotationOptions.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/AnnotationOptions.java
new file mode 100644
index 0000000000..f03ff45f76
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/AnnotationOptions.java
@@ -0,0 +1,22 @@
+package com.mapbox.mapboxgl.annotations;
+
+public abstract class AnnotationOptions {
+
+ protected Annotation annotation;
+
+ public AnnotationOptions() {}
+
+ public AnnotationOptions alpha(float alpha) {
+ annotation.alpha = alpha;
+ return this;
+ }
+
+ public float getAlpha() {
+ return annotation.alpha;
+ }
+
+ public boolean isVisible() {
+ return annotation.visible;
+ }
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Circle.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Circle.java
new file mode 100644
index 0000000000..f8908465b9
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Circle.java
@@ -0,0 +1,67 @@
+package com.mapbox.mapboxgl.annotations;
+
+
+import android.graphics.Color;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+/**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ *
+ * https://github.com/mapbox/mapbox-gl-native/issues/1882
+ * https://github.com/mapbox/mapbox-gl-native/issues/1726
+ */
+public class Circle extends Annotation {
+
+ LatLng center;
+ int fillColor = Color.BLACK;
+ double radius;
+ int strokeColor = Color.BLACK;
+ float strokeWidth = 10; // Google Maps API defaults to 10
+
+ public LatLng getCenter() {
+ return center;
+ }
+
+ public int getFillColor() {
+ return fillColor;
+ }
+
+ /**
+ * Returns the circle's radius, in meters.
+ *
+ * @return radius in meters
+ */
+ public double getRadius() {
+ return radius;
+ }
+
+ public int getStrokeColor() {
+ return strokeColor;
+ }
+
+ public float getStrokeWidth() {
+ return strokeWidth;
+ }
+
+ public void setCenter(LatLng center) {
+ this.center = center;
+ }
+
+ public void setFillColor(int color) {
+ fillColor = color;
+ }
+
+ public void setRadius(double radius) {
+ this.radius = radius;
+ }
+
+ public void setStrokeColor (int color) {
+ strokeColor = color;
+ }
+
+ public void setStrokeWidth (float width) {
+ strokeWidth = width;
+ }
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/CircleOptions.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/CircleOptions.java
new file mode 100644
index 0000000000..5e97d5b5e4
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/CircleOptions.java
@@ -0,0 +1,64 @@
+package com.mapbox.mapboxgl.annotations;
+
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+/**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ *
+ * https://github.com/mapbox/mapbox-gl-native/issues/1882
+ * https://github.com/mapbox/mapbox-gl-native/issues/1726
+ */
+public class CircleOptions extends AnnotationOptions {
+
+ private Circle circle;
+
+ public CircleOptions() {
+ circle = new Circle();
+ }
+ public CircleOptions center(LatLng center) {
+ circle.center = center;
+ return this;
+ }
+
+ public CircleOptions fillColor(int color) {
+ circle.fillColor = color;
+ return this;
+ }
+
+ public LatLng getCenter() {
+ return circle.center;
+ }
+
+ public int getFillColor() {
+ return circle.fillColor;
+ }
+
+ public double getRadius() {
+ return circle.radius;
+ }
+
+ public int getStrokeColor () {
+ return circle.strokeColor;
+ }
+
+ public float getStrokeWidth() {
+ return circle.strokeWidth;
+ }
+
+ public CircleOptions radius (double radius) {
+ circle.radius = radius;
+ return this;
+ }
+
+ public CircleOptions strokeColor(int color) {
+ circle.strokeColor = color;
+ return this;
+ }
+
+ public CircleOptions strokeWidth (float width) {
+ circle.strokeWidth = width;
+ return this;
+ }
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java
new file mode 100644
index 0000000000..f0c53a36c0
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java
@@ -0,0 +1,154 @@
+package com.mapbox.mapboxgl.annotations;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+
+public class Marker extends Annotation {
+
+ float anchorU;
+ float anchorV;
+ boolean draggable;
+ boolean flat;
+ float infoWindowAnchorU;
+ float infoWindowAnchorV;
+ LatLng position;
+ float rotation;
+ String snippet;
+ String sprite = "default_marker";
+ String title;
+
+ private boolean infoWindowShown = false;
+
+ public Marker() {}
+
+ /**
+ * If two markers have the same LatLng, they are equal.
+ *
+ * @param other object
+ * @return boolean - do they have the same LatLng
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof Marker)) return false;
+ double lat = position.getLatitude();
+ double lng = position.getLongitude();
+ LatLng otherPosition = ((Marker)other).getPosition();
+ double otherLat = otherPosition.getLatitude();
+ double otherLng = otherPosition.getLongitude();
+ return (lat == otherLat && otherLng == lng);
+ }
+
+ public float getAlpha() {
+ return alpha;
+ }
+
+ public float getAnchorU() {
+ return anchorU;
+ }
+
+ public float getAnchorV() {
+ return anchorV;
+ }
+
+ /**
+ * NOTE: Google Maps Android API uses String for IDs.
+ *
+ * Internal C++ id is stored as unsigned int.
+ *
+ * @return the annotation id
+ */
+ public long getId() {
+ return id;
+ }
+
+ public LatLng getPosition() {
+ return position;
+ }
+
+ public float getRotation() {
+ return rotation;
+ }
+
+ public String getSnippet() {
+ return snippet;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void hideInfoWindow() {
+ //TODO hideInfoWindow
+ infoWindowShown = false;
+ }
+
+ public boolean isDraggable() {
+ return draggable;
+ }
+
+ public boolean isFlat() {
+ return flat;
+ }
+
+ public boolean isInfoWindowShown () {
+ return infoWindowShown;
+ }
+
+ void setAnchor(float u, float v) {
+ this.anchorU = u;
+ this.anchorV = v;
+ }
+
+ void setDraggable(boolean draggable) {
+ this.draggable = draggable;
+ }
+
+ void setFlat(boolean flat) {
+ this.flat = flat;
+ }
+
+ void setInfoWindowAnchor(float u, float v) {
+ infoWindowAnchorU = u;
+ infoWindowAnchorV = v;
+ }
+
+ void setPosition(LatLng latlng) {
+ this.position = position;
+ }
+
+ void setRotation(float rotation) {
+ this.rotation = rotation;
+ }
+
+ void setSnippet(String snippet) {
+ this.snippet = snippet;
+ }
+
+ /**
+ * You can specify the name of a sprite to get a marker other than the default marker.
+ * This name can be found in the sprite json file:
+ *
+ * https://github.com/mapbox/mapbox-gl-styles/blob/mb-pages/sprites/mapbox-streets.json
+ *
+ * @param sprite
+ */
+ void setSprite(String sprite) {
+ this.sprite = sprite;
+ }
+
+ void setTitle(String title) {
+ this.title = title;
+ }
+
+ void showInfoWindow() {
+ infoWindowShown = true;
+ }
+
+
+ // TODO Method in Google Maps Android API
+// public int hashCode()
+
+ // TODO: Implement this method of Google Maps Android API
+// void setIcon(BitmapDescriptor icon) {
+//
+// }
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MarkerOptions.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MarkerOptions.java
new file mode 100644
index 0000000000..2e577067db
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MarkerOptions.java
@@ -0,0 +1,125 @@
+package com.mapbox.mapboxgl.annotations;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+public class MarkerOptions extends AnnotationOptions {
+
+ public MarkerOptions() {
+ annotation = new Marker();
+ }
+
+ public MarkerOptions anchor(float u, float v) {
+ ((Marker)annotation).anchorU = u;
+ ((Marker)annotation).anchorV = v;
+ return this;
+ }
+
+ public MarkerOptions draggable(boolean draggable) {
+ ((Marker)annotation).draggable = draggable;
+ return this;
+ }
+
+ public MarkerOptions flat(boolean flat) {
+ ((Marker)annotation).flat = flat;
+ return this;
+ }
+
+ public float getAnchorU() {
+ return ((Marker)annotation).anchorU;
+ }
+
+ public float getAnchorV() {
+ return ((Marker)annotation).anchorV;
+ }
+
+ // TODO: Implement this method of Google Maps Android API
+// public BitmapDescriptor getIcon () {
+//
+// }
+
+ public float getInfoWindowAnchorU() {
+ return ((Marker)annotation).infoWindowAnchorU;
+ }
+
+ public float getInfoWindowAnchorV() {
+ return ((Marker)annotation).infoWindowAnchorV;
+ }
+
+ public Marker getMarker() {
+ return (Marker)annotation;
+ }
+
+ public LatLng getPosition() {
+ return ((Marker)annotation).position;
+ }
+
+ public float getRotation() {
+ return ((Marker)annotation).rotation;
+ }
+
+ public String getSnippet() {
+ return ((Marker)annotation).snippet;
+ }
+
+ public String getTitle() {
+ return ((Marker)annotation).title;
+ }
+
+ public MarkerOptions infoWindowAnchor(float u, float v) {
+ ((Marker)annotation).infoWindowAnchorU = u;
+ ((Marker)annotation).infoWindowAnchorV = v;
+ return this;
+ }
+
+ public boolean isDraggable() {
+ return ((Marker)annotation).draggable;
+ }
+
+ public boolean isFlat() {
+ return ((Marker)annotation).flat;
+ }
+
+ public boolean isVisible() {
+ return ((Marker)annotation).visible;
+ }
+
+ public MarkerOptions position(LatLng position) {
+ ((Marker)annotation).position = position;
+ return this;
+ }
+
+ public MarkerOptions rotation(float rotation) {
+ ((Marker)annotation).rotation = rotation;
+ return this;
+ }
+
+ public MarkerOptions snippet(String snippet) {
+ ((Marker)annotation).snippet = snippet;
+ return this;
+ }
+
+ public MarkerOptions sprite(String sprite) {
+ ((Marker)annotation).sprite = sprite;
+ return this;
+ }
+
+ public MarkerOptions title(String title) {
+ ((Marker)annotation).title = title;
+ return this;
+ }
+
+ public MarkerOptions visible(boolean visible) {
+ annotation.visible = visible;
+ return this;
+ }
+
+
+ // TODO: Implement this method of Google Maps Android API
+// public MarkerOptions icon(BitmapDescriptor icon) {
+//
+// }
+
+ // TODO: Implement this method of Google Maps Android API
+// public void writeToParcel (Parcel out, int flags)
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPoint.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPoint.java
new file mode 100644
index 0000000000..4ebdd5071f
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPoint.java
@@ -0,0 +1,53 @@
+package com.mapbox.mapboxgl.annotations;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class MultiPoint extends Annotation {
+
+ List<LatLng> points;
+
+ public MultiPoint() {
+ super();
+ points = new ArrayList<>();
+ }
+
+ /**
+ * Returns a copy of the points.
+ *
+ * @return points - as a copy
+ */
+ public List<LatLng> getPoints() {
+ return new ArrayList<>(points);
+ }
+
+ /**
+ * Sets the points of this polyline. This method will take a copy
+ * of the points, so further mutations to points will have no effect
+ * on this polyline.
+ *
+ * @param points
+ */
+ void setPoints(List<LatLng> points) {
+ this.points = new ArrayList<>(points);
+ }
+
+
+ // TODO: Implement hashCode of Google Maps Android API
+// public int hashCode() {
+//
+// }
+
+ // TODO: Implement isGeodesic of Google Maps Android API
+// public boolean isGeodesic() {
+//
+// }
+
+ // TODO: Implement setGeodesic of Google Maps Android API
+// public void setGeodesic(boolean geodesic) {
+//
+// }
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPointOptions.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPointOptions.java
new file mode 100644
index 0000000000..581c42bfdd
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/MultiPointOptions.java
@@ -0,0 +1,15 @@
+package com.mapbox.mapboxgl.annotations;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import java.util.List;
+
+public abstract class MultiPointOptions extends AnnotationOptions {
+
+ public MultiPointOptions() {}
+
+ public List<LatLng> getPoints() {
+ // the getter gives us a copy, which is the safe thing to do...
+ return ((MultiPoint)annotation).getPoints();
+ }
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polygon.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polygon.java
new file mode 100644
index 0000000000..41edb2a5d7
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polygon.java
@@ -0,0 +1,99 @@
+package com.mapbox.mapboxgl.annotations;
+
+
+import android.graphics.Color;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Polygon extends MultiPoint {
+
+ int fillColor = Color.BLACK; // default fillColor is black
+ float strokeAlpha = 1;
+ int strokeColor = Color.BLACK; // default strokeColor is black
+ float strokeWidth = 10; // As specified by Google API Docs (in pixels)
+
+ List<List<LatLng>> holes;
+
+ public Polygon() {
+ super();
+ holes = new ArrayList<>();
+ }
+
+ public int getFillColor() {
+ return fillColor;
+ }
+
+ public List<List<LatLng>> getHoles () {
+ return holes;
+ }
+
+ public int getStrokeColor() {
+ return strokeColor;
+ }
+
+ /**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ * https://github.com/mapbox/mapbox-gl-native/issues/1737
+ * @return stroke width as float
+ */
+ public float getStrokeWidth() {
+ return strokeWidth;
+ }
+
+ public void setFillAlpha(float alpha) {
+ this.alpha = alpha;
+ }
+
+ public void setFillColor(int color) {
+ fillColor = color;
+ }
+
+ /**
+ * Sets the holes of this polygon. This method will take a copy of the holes,
+ * so further mutations to holes parameter will have no effect on this polygon.
+ *
+ * @param holes
+ */
+ public void setHoles(List<? extends List<LatLng>> holes) {
+ this.holes = new ArrayList<>();
+ for (List<LatLng> hole : holes) {
+ this.holes.add(new ArrayList<>(hole));
+ }
+ }
+
+ /**
+ * Sets the alpha (opacity) of the stroke
+ *
+ * UNIMPLEMENTED: Needs implementation in Native.
+ */
+ public void setStrokeAlpha(float alpha) {
+ strokeAlpha = alpha;
+ }
+
+ public void setStrokeColor(int color) {
+ strokeColor = color;
+ }
+
+ /**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ * https://github.com/mapbox/mapbox-gl-native/issues/1737
+ * @return stroke width as float
+ */
+ public void setStrokeWidth(float width) {
+ strokeWidth = width;
+ }
+
+
+ // TODO: Implement equals of Google Maps Android API
+// public boolean equals (Object other) {
+//
+// }
+
+ // TODO: Implement hashCode of Google Maps Android API
+// public int hashCode () {
+//
+// }
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolygonOptions.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolygonOptions.java
new file mode 100644
index 0000000000..25ee750196
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolygonOptions.java
@@ -0,0 +1,125 @@
+package com.mapbox.mapboxgl.annotations;
+
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PolygonOptions extends MultiPointOptions {
+
+ public PolygonOptions() {
+ annotation = new Polygon();
+ }
+
+ public PolygonOptions add(LatLng point) {
+ ((MultiPoint)annotation).points.add(point);
+ return this;
+ }
+
+ public PolygonOptions add(LatLng... points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ public PolygonOptions addAll(Iterable<LatLng> points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ /**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ * https://github.com/mapbox/mapbox-gl-native/issues/1729
+ *
+ * @param points - an iterable (list) of points for cutting a hole
+ * @return PolygonOptions - the options object
+ */
+ public PolygonOptions addHole (Iterable<LatLng> points) {
+ List<LatLng> hole = new ArrayList<>();
+ for (LatLng point : points) {
+ hole.add(point);
+ }
+ ((Polygon)annotation).holes.add(hole);
+ return this;
+ }
+
+ /**
+ * Sets the color of the polygon.
+ *
+ * @param color - the color in ARGB format
+ * @return PolygonOptions - the options object
+ */
+ public PolygonOptions fillColor(int color) {
+ ((Polygon)annotation).fillColor = color;
+ return this;
+ }
+
+ public int getFillColor() {
+ return ((Polygon)annotation).fillColor;
+ }
+
+ /**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ * https://github.com/mapbox/mapbox-gl-native/issues/1729
+ *
+ * @return a list of lists of points for cutting holes
+ */
+ public List<List<LatLng>> getHoles() {
+ return ((Polygon)annotation).holes;
+ }
+
+ public Polygon getPolygon() {
+ return ((Polygon)annotation);
+ }
+
+ public int getStrokeColor() {
+ return ((Polygon)annotation).strokeColor;
+ }
+
+ /**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ * https://github.com/mapbox/mapbox-gl-native/issues/1737
+ *
+ * @return stroke width as float
+ */
+ public float getStrokeWidth() {
+ return ((Polygon)annotation).strokeWidth;
+ }
+
+ /**
+ * Sets the color of the stroke of the polygon.
+ *
+ * @param color - the color in ARGB format
+ * @return PolygonOptions - the options object
+ */
+ public PolygonOptions strokeColor(int color) {
+ ((Polygon)annotation).strokeColor = color;
+ return this;
+ }
+
+ /**
+ * UNIMPLEMENTED: Needs implementation in Native.
+ * https://github.com/mapbox/mapbox-gl-native/issues/1737
+ *
+ * @return stroke width as float
+ */
+ public PolygonOptions strokeWidth(float width) {
+ ((Polygon)annotation).strokeWidth = width;
+ return this;
+ }
+
+ public PolygonOptions visible(boolean visible) {
+ annotation.visible = visible;
+ return this;
+ }
+
+ // TODO: Implement writeToParcel of Google Maps Android API
+// public void writeToParcel(Parcel out, int flags) {
+//
+// }
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polyline.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polyline.java
new file mode 100644
index 0000000000..7647238331
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Polyline.java
@@ -0,0 +1,51 @@
+package com.mapbox.mapboxgl.annotations;
+
+import android.graphics.Color;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import java.util.List;
+
+public class Polyline extends MultiPoint {
+
+ int color = Color.BLACK; // default color is black
+ float width = 10; // As specified by Google API Docs (in pixels)
+
+ public Polyline() {
+ super();
+ }
+
+ public int getColor() {
+ return color;
+ }
+
+ public float getWidth() {
+ return width;
+ }
+
+
+ /**
+ * Sets the color of the polyline.
+ *
+ * @param color - the color in ARGB format
+ */
+ public void setColor(int color) {
+ this.color = color;
+ }
+
+
+ /**
+ * Sets the width of the polyline.
+ *
+ * @param width in pixels
+ * @return
+ */
+ public void setWidth(float width) {
+ this.width = width;
+ }
+
+ // TODO: Implement equals of Google Maps Android API
+// public boolean equals(Object other) {
+//
+// }
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolylineOptions.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolylineOptions.java
new file mode 100644
index 0000000000..d825399f7d
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/PolylineOptions.java
@@ -0,0 +1,75 @@
+package com.mapbox.mapboxgl.annotations;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import java.util.List;
+
+public class PolylineOptions extends MultiPointOptions {
+
+ public PolylineOptions() {
+ annotation = new Polyline();
+ }
+
+ public PolylineOptions add(LatLng point) {
+ ((MultiPoint)annotation).points.add(point);
+ return this;
+ }
+
+ public PolylineOptions add(LatLng... points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ public PolylineOptions addAll(Iterable<LatLng> points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the color of the polyline.
+ *
+ * @param color - the color in ARGB format
+ */
+ public PolylineOptions color(int color) {
+ ((Polyline)annotation).color = color;
+ return this;
+ }
+
+ public int getColor() {
+ return ((Polyline)annotation).color;
+ }
+
+ public Polyline getPolyline() {
+ return ((Polyline)annotation);
+ }
+
+ public float getWidth() {
+ return ((Polyline)annotation).width;
+ }
+
+ public PolylineOptions visible(boolean visible) {
+ annotation.visible = visible;
+ return this;
+ }
+
+ /**
+ * Sets the width of the polyline.
+ *
+ * @param width in pixels
+ * @return
+ */
+ public PolylineOptions width(float width) {
+ ((Polyline)annotation).width = width;
+ return this;
+ }
+
+ // TODO: Implement writeToParcel of Google Maps Android API
+// public void writeToParcel(Parcel out, int flags) {
+//
+// }
+
+}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java
index 0f359ab100..4a8ed42a54 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java
@@ -26,10 +26,16 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.ZoomButtonsController;
-import android.util.Log;
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
+import com.mapbox.mapboxgl.annotations.Annotation;
+import com.mapbox.mapboxgl.annotations.Marker;
+import com.mapbox.mapboxgl.annotations.MarkerOptions;
+import com.mapbox.mapboxgl.annotations.Polygon;
+import com.mapbox.mapboxgl.annotations.PolygonOptions;
+import com.mapbox.mapboxgl.annotations.Polyline;
+import com.mapbox.mapboxgl.annotations.PolylineOptions;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.geometry.LatLngZoom;
@@ -63,6 +69,11 @@ public class MapView extends SurfaceView {
private static final String STATE_CLASSES = "classes";
private static final String STATE_DEFAULT_TRANSITION_DURATION = "defaultTransitionDuration";
+ /**
+ * Every annotation that has been added to the map.
+ */
+ private List<Annotation> annotations = new ArrayList<>();
+
//
// Instance members
//
@@ -205,6 +216,48 @@ public class MapView extends SurfaceView {
}
}
+ public Marker addMarker(MarkerOptions markerOptions) {
+ Marker marker = markerOptions.getMarker();
+ Long id = mNativeMapView.addMarker(marker);
+ marker.setId(id); // the annotation needs to know its id
+ marker.setMapView(this); // the annotation needs to know which map view it is in
+ annotations.add(marker);
+ return marker;
+ }
+
+ public Polyline addPolyline(PolylineOptions polylineOptions) {
+ Polyline polyline = polylineOptions.getPolyline();
+ Long id = mNativeMapView.addPolyline(polyline);
+ polyline.setId(id);
+ polyline.setMapView(this);
+ annotations.add(polyline);
+ return polyline;
+ }
+
+ public Polygon addPolygon(PolygonOptions polygonOptions) {
+ Polygon polygon = polygonOptions.getPolygon();
+ Long id = mNativeMapView.addPolygon(polygon);
+ polygon.setId(id);
+ polygon.setMapView(this);
+ annotations.add(polygon);
+ return polygon;
+ }
+
+ public void removeAnnotation(Annotation annotation) {
+ long id = annotation.getId();
+ mNativeMapView.removeAnnotation(id);
+ }
+
+ public void removeAnnotation(long annotationId) {
+ mNativeMapView.removeAnnotation(annotationId);
+ }
+
+ public void removeAnnotations() {
+ for (Annotation annotation : annotations) {
+ annotation.remove();
+ }
+ }
+
//
// Property methods
//
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java
index 643fcbd720..6cab4bbd0f 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java
@@ -2,8 +2,10 @@ package com.mapbox.mapboxgl.views;
import android.graphics.PointF;
import android.view.Surface;
-import android.util.Log;
+import com.mapbox.mapboxgl.annotations.Marker;
+import com.mapbox.mapboxgl.annotations.Polygon;
+import com.mapbox.mapboxgl.annotations.Polyline;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.geometry.LatLngZoom;
import com.mapbox.mapboxgl.geometry.ProjectedMeters;
@@ -214,6 +216,24 @@ class NativeMapView {
nativeSetLatLng(mNativeMapViewPtr, latLng, duration);
}
+ public long addMarker(Marker marker) {
+ return nativeAddMarker(mNativeMapViewPtr, marker);
+ }
+
+ public long addPolyline(Polyline polyline) {
+ // NH TODO Throw exception if returns -1
+ return nativeAddPolyline(mNativeMapViewPtr, polyline);
+ }
+
+ public long addPolygon(Polygon polygon) {
+ // NH TODO Throw exception if returns -1
+ return nativeAddPolygon(mNativeMapViewPtr, polygon);
+ }
+
+ public void removeAnnotation(long id) {
+ nativeRemoveAnnotation(mNativeMapViewPtr, id);
+ }
+
public LatLng getLatLng() {
return nativeGetLatLng(mNativeMapViewPtr);
}
@@ -446,6 +466,14 @@ class NativeMapView {
private native void nativeSetLatLng(long nativeMapViewPtr, LatLng latLng,
long duration);
+ private native long nativeAddMarker(long nativeMapViewPtr, Marker marker);
+
+ private native long nativeAddPolyline(long nativeMapViewPtr, Polyline polyline);
+
+ private native long nativeAddPolygon(long mNativeMapViewPtr, Polygon polygon);
+
+ private native void nativeRemoveAnnotation(long nativeMapViewPtr, long id);
+
private native LatLng nativeGetLatLng(long nativeMapViewPtr);
private native void nativeResetPosition(long nativeMapViewPtr);
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_line.geojson b/android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_line.geojson
new file mode 100644
index 0000000000..ef76eaf56d
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_line.geojson
@@ -0,0 +1 @@
+{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"LineString","coordinates":[[-121.3714599609375,38.64583568648869],[-121.48681640624999,38.64047263931154],[-121.53076171875,38.61579745317875],[-121.56509399414061,38.57823196583313],[-121.75186157226561,38.533127435052776],[-121.97021484374999,38.35350340353833],[-122.08007812499999,38.24680876017446],[-122.16796875,38.19718009396176],[-122.23800659179686,38.09457899232253],[-122.27371215820312,38.01455819225337],[-122.33551025390625,37.94094845586459],[-122.27371215820312,37.81846319511331],[-122.4151611328125,37.7652868250379]]}}]} \ No newline at end of file
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_poly.geojson b/android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_poly.geojson
new file mode 100644
index 0000000000..ec61303c72
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/assets/small_poly.geojson
@@ -0,0 +1 @@
+{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-122.28813171386719,38.617406963286136],[-122.26959228515624,38.6833657775237],[-122.18238830566406,38.55568323796419],[-122.10617065429688,38.51378825951165],[-122.11509704589845,38.50465406475561],[-122.18307495117188,38.542795073979015],[-122.19955444335938,38.496593518947556],[-122.28813171386719,38.617406963286136]]]}}]} \ No newline at end of file
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java
index 65cb17462f..f8c35897c2 100644
--- a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java
@@ -1,6 +1,7 @@
package com.mapbox.mapboxgl.testapp;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.hardware.GeomagneticField;
@@ -23,6 +24,12 @@ import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
+import com.mapbox.mapboxgl.annotations.Marker;
+import com.mapbox.mapboxgl.annotations.MarkerOptions;
+import com.mapbox.mapboxgl.annotations.Polygon;
+import com.mapbox.mapboxgl.annotations.PolygonOptions;
+import com.mapbox.mapboxgl.annotations.Polyline;
+import com.mapbox.mapboxgl.annotations.PolylineOptions;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.views.MapView;
import com.mapzen.android.lost.api.LocationListener;
@@ -30,6 +37,9 @@ import com.mapzen.android.lost.api.LocationRequest;
import com.mapzen.android.lost.api.LocationServices;
import com.mapzen.android.lost.api.LostApiClient;
+import org.json.JSONException;
+
+import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends ActionBarActivity {
@@ -77,6 +87,11 @@ public class MainActivity extends ActionBarActivity {
private float mCompassBearing;
private boolean mCompassValid = false;
+ // Used for markers
+ private boolean mIsMarkersOn = false;
+
+ private Marker marker;
+
//
// Lifecycle events
//
@@ -210,6 +225,10 @@ public class MainActivity extends ActionBarActivity {
}
return true;
+ case R.id.action_markers:
+ // Toggle markers
+ toggleMarkers(!mIsMarkersOn);
+
default:
return super.onOptionsItemSelected(item);
}
@@ -249,6 +268,80 @@ public class MainActivity extends ActionBarActivity {
}
}
+ /**
+ * Enable / Disable markers.
+ *
+ * @param enableMarkers
+ */
+ private void toggleMarkers(boolean enableMarkers) {
+ if (enableMarkers) {
+ if (!mIsMarkersOn) {
+ mIsMarkersOn = true;
+ addMarkers();
+ addPolyline();
+ addPolygon();
+ }
+ } else {
+ if (mIsMarkersOn) {
+ mIsMarkersOn = false;
+ removeAnnotations();
+ }
+ }
+ }
+
+ private void addMarkers() {
+ LatLng backLot = new LatLng(38.649441, -121.369064);
+ MapView map = mMapFragment.getMap();
+ marker = map.addMarker(new MarkerOptions()
+ .position(backLot)
+ .title("Back Lot")
+ .snippet("The back lot behind my house"));
+
+ LatLng cheeseRoom = new LatLng(38.531577,-122.010646);
+ map.addMarker(new MarkerOptions()
+ .position(cheeseRoom)
+ .sprite("dog-park-15")
+ .title("Cheese Room")
+ .snippet("The only air conditioned room on the property!"));
+ }
+
+ private void addPolyline() {
+ try {
+ String geojsonStr = Util.loadStringFromAssets(this, "small_line.geojson");
+ LatLng[] latLngs = Util.parseGeoJSONCoordinates(geojsonStr);
+ MapView map = mMapFragment.getMap();
+ Polyline line = map.addPolyline(new PolylineOptions()
+ .add(latLngs)
+ .width(2)
+ .color(Color.RED));
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void addPolygon() {
+ String geojsonStr = null;
+ try {
+ geojsonStr = Util.loadStringFromAssets(this, "small_poly.geojson");
+ LatLng[] latLngs = Util.parseGeoJSONCoordinates(geojsonStr);
+ MapView map = mMapFragment.getMap();
+ Polygon polygon = map.addPolygon(new PolygonOptions()
+ .add(latLngs)
+ .strokeColor(Color.MAGENTA)
+ .fillColor(Color.BLUE));
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void removeAnnotations() {
+ mMapFragment.getMap().removeAnnotations();
+ }
+
// This class forwards location updates to updateLocation()
private class GpsListener implements LocationListener {
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java
index b78926b9e1..d3a6d2ad1f 100644
--- a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java
@@ -7,6 +7,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.views.MapView;
import java.io.BufferedReader;
@@ -77,6 +78,8 @@ public class MapFragment extends Fragment {
// Need to pass on to view
mMap.onStart();
+ mMap.setCenterCoordinate(new LatLng(38.247887,-121.843872));
+ mMap.setZoomLevel(7);
}
// Called when the fragment is invisible
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/Util.java b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/Util.java
new file mode 100644
index 0000000000..74b909cec5
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/Util.java
@@ -0,0 +1,61 @@
+package com.mapbox.mapboxgl.testapp;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.mapbox.mapboxgl.geometry.LatLng;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+public class Util {
+
+ public static String loadStringFromAssets(final Context context, final String fileName) throws IOException {
+ if (TextUtils.isEmpty(fileName)) {
+ throw new NullPointerException("No GeoJSON File Name passed in.");
+ }
+ InputStream is = context.getAssets().open(fileName);
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
+ return readAll(rd);
+ }
+
+ public static LatLng[] parseGeoJSONCoordinates(String geojsonStr) throws JSONException {
+ JSONObject jsonObject = new JSONObject(geojsonStr);
+ JSONArray features = jsonObject.getJSONArray("features");
+ JSONObject feature = features.getJSONObject(0);
+ JSONObject geometry = feature.getJSONObject("geometry");
+ String type = geometry.getString("type");
+ JSONArray coordinates;
+ if (type.equals("Polygon")) {
+ coordinates = geometry.getJSONArray("coordinates").getJSONArray(0);
+ } else {
+ coordinates = geometry.getJSONArray("coordinates");
+ }
+ int len = coordinates.length();
+ LatLng[] latLngs = new LatLng[coordinates.length()];
+ for (int i = 0; i < len; ++i) {
+ JSONArray coord = coordinates.getJSONArray(i);
+ double lng = coord.getDouble(0);
+ double lat = coord.getDouble(1);
+ latLngs[i] = new LatLng(lat, lng);
+ }
+ return latLngs;
+ }
+
+ private static String readAll(Reader rd) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ int cp;
+ while ((cp = rd.read()) != -1) {
+ sb.append((char) cp);
+ }
+ return sb.toString();
+ }
+}
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_main.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_main.xml
index bf6dbbf36d..f16522d99c 100644
--- a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_main.xml
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_main.xml
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
- <item android:id="@+id/action_gps"
- android:icon="@drawable/ic_action_location_searching"
- android:title="@string/action_gps"
- app:showAsAction="ifRoom" />
<item android:id="@+id/action_debug"
android:icon="@drawable/ic_action_about"
android:title="@string/action_debug"
app:showAsAction="ifRoom" />
+ <item android:id="@+id/action_markers"
+ android:icon="@android:drawable/ic_menu_myplaces"
+ android:title="@string/action_point_annotations"
+ app:showAsAction="ifRoom" />
+ <item android:id="@+id/action_gps"
+ android:icon="@drawable/ic_action_location_searching"
+ android:title="@string/action_gps"
+ app:showAsAction="ifRoom" />
</menu>
diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index 901e231929..cddf228bf6 100644
--- a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -7,6 +7,8 @@
<string name="action_debug">Toggle debug mode</string>
+ <string name="action_point_annotations">Toggle point annotations</string>
+
<string name="label_fps">FPS:</string>
<string name="compass_desc">Map compass. Click to reset the map rotation to North.</string>