diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp index 84bbf7098..4f0a2759a 100644 --- a/android/cpp/jni.cpp +++ b/android/cpp/jni.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -227,7 +228,9 @@ mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobjec } segment.push_back(mbgl::LatLng(latitude, longitude)); + env->DeleteLocalRef(latLng); } + env->DeleteLocalRef(array); return segment; } @@ -248,6 +251,27 @@ jobject std_vector_string_to_jobject(JNIEnv *env, std::vector vecto return jlist; } + +jlongArray std_vector_uint_to_jobject(JNIEnv *env, std::vector vector) { + jlongArray jarray = env->NewLongArray(vector.size()); + if (jarray == nullptr) { + env->ExceptionDescribe(); + return nullptr; + } + + std::vector v; + for (const uint32_t& id : vector) { + v.push_back((jlong)id); + } + + env->SetLongArrayRegion(jarray, 0, v.size(), &(v[0])); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + return jarray; +} } } @@ -509,6 +533,27 @@ void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, j nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration)); } +void JNICALL nativeSetSprite(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, + jstring symbol, jint width, jint height, jfloat scale, jbyteArray jpixels) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetSprite"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + const std::string symbolName = std_string_from_jstring(env, symbol); + + jbyte* pixelData = env->GetByteArrayElements(jpixels, nullptr); + std::string pixels((char*)pixelData, width * height * 4); + env->ReleaseByteArrayElements(jpixels, pixelData, JNI_ABORT); + + auto spriteImage = std::make_shared( + uint16_t(width), + uint16_t(height), + float(scale), + std::move(pixels)); + + nativeMapView->getMap().setSprite(symbolName, spriteImage); +} + jlong JNICALL nativeAddMarker(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject marker) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker"); assert(nativeMapViewPtr != 0); @@ -584,7 +629,7 @@ jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr mbgl::StyleProperties shapeProperties; mbgl::LineProperties lineProperties; lineProperties.opacity = alpha; - lineProperties.color = {{ (float)r, (float)g, (float)b, (float)a }}; + lineProperties.color = {{ (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f }}; lineProperties.width = width; shapeProperties.set(lineProperties); @@ -599,11 +644,8 @@ jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr 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(nativeMapViewPtr); +std::pair readPolygon(JNIEnv *env, jobject polygon) { // ***** Java fields ***** // // float alpha; // boolean visible; @@ -614,29 +656,10 @@ jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, // List> 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; @@ -657,21 +680,87 @@ jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, 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 }}; + fillProperties.stroke_color = {{ (float)rS / 255.0f, (float)gS / 255.0f, (float)bS / 255.0f, (float)aS / 255.0f }}; + fillProperties.fill_color = {{ (float)rF / 255.0f, (float)gF / 255.0f, (float)bF / 255.0f, (float)aF / 255.0f }}; shapeProperties.set(fillProperties); jobject points = env->GetObjectField(polygon, polygonPointsId); mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); + env->DeleteLocalRef(points); + + return std::make_pair(segment, shapeProperties); +} + + +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(nativeMapViewPtr); std::vector shapes; - shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties); + std::pair segment = readPolygon(env, polygon); + + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + + shapes.emplace_back(mbgl::AnnotationSegments {{ segment.first }}, segment.second); std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); uint32_t id = shapeAnnotationIDs.at(0); return (jlong) id; } +jlongArray JNICALL nativeAddPolygons(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject jlist) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygons"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + std::vector shapes; + + if (jlist == nullptr) { + if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) { + env->ExceptionDescribe(); + return nullptr; + } + return nullptr; + } + + jobjectArray array = + reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); + if (env->ExceptionCheck() || (array == nullptr)) { + env->ExceptionDescribe(); + return nullptr; + } + + jsize len = env->GetArrayLength(array); + if (len < 0) { + env->ExceptionDescribe(); + return nullptr; + } + + shapes.reserve(len); + + for (jsize i = 0; i < len; i++) { + jobject polygon = reinterpret_cast(env->GetObjectArrayElement(array, i)); + + std::pair segment = readPolygon(env, polygon); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + shapes.emplace_back(mbgl::AnnotationSegments {{ segment.first }}, segment.second); + + env->DeleteLocalRef(polygon); + } + + std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); + return std_vector_uint_to_jobject(env, shapeAnnotationIDs); +} + + void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong annotationId) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation"); assert(nativeMapViewPtr != 0); @@ -679,6 +768,38 @@ void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapVie nativeMapView->getMap().removeAnnotation((uint32_t)annotationId); } +void JNICALL nativeRemoveAnnotations(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlongArray array) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotations"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + std::vector ids; + + if (env->ExceptionCheck() || (array == nullptr)) { + env->ExceptionDescribe(); + return; + } + + jsize len = env->GetArrayLength(array); + if (len < 0) { + env->ExceptionDescribe(); + return; + } + + ids.reserve(len); + jlong* jids = env->GetLongArrayElements(array, nullptr); + + for (jsize i = 0; i < len; i++) { + if(jids[i] == -1L) + continue; + ids.push_back((uint32_t) jids[i]); + } + + env->ReleaseLongArrayElements(array, jids, JNI_ABORT); + + nativeMapView->getMap().removeAnnotations(ids); +} + jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng"); assert(nativeMapViewPtr != 0); @@ -1342,13 +1463,17 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { {"nativeMoveBy", "(JDDJ)V", reinterpret_cast(&nativeMoveBy)}, {"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V", reinterpret_cast(&nativeSetLatLng)}, + {"nativeSetSprite", "(JLjava/lang/String;IIF[B)V", reinterpret_cast(&nativeSetSprite)}, {"nativeAddMarker", "(JLcom/mapbox/mapboxgl/annotations/Marker;)J", reinterpret_cast(&nativeAddMarker)}, {"nativeAddPolyline", "(JLcom/mapbox/mapboxgl/annotations/Polyline;)J", reinterpret_cast(&nativeAddPolyline)}, {"nativeAddPolygon", "(JLcom/mapbox/mapboxgl/annotations/Polygon;)J", reinterpret_cast(&nativeAddPolygon)}, + {"nativeAddPolygons", "(JLjava/util/List;)[J", + reinterpret_cast(&nativeAddPolygons)}, {"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast(&nativeRemoveAnnotation)}, + {"nativeRemoveAnnotations", "(J[J)V", reinterpret_cast(&nativeRemoveAnnotations)}, {"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeGetLatLng)}, {"nativeResetPosition", "(J)V", reinterpret_cast(&nativeResetPosition)}, diff --git a/android/java/.gitignore b/android/java/.gitignore index 5f00b1092..866441810 100644 --- a/android/java/.gitignore +++ b/android/java/.gitignore @@ -18,3 +18,6 @@ local.properties # Token file MapboxGLAndroidSDKTestApp/src/main/res/raw/token.txt + +# Twitter Fabric / Crashlytics +fabric.properties 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 index e38af77cd..6feb733f0 100644 --- 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 @@ -23,7 +23,7 @@ public abstract class Annotation { return alpha; } - public long getId() { + public Long getId() { return id; } 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 index f0c53a36c..515852ae6 100644 --- 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 @@ -49,17 +49,6 @@ public class Marker extends Annotation { 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; } 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 4a8ed42a5..17ace8741 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 @@ -7,6 +7,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.TypedArray; +import android.graphics.Bitmap; import android.graphics.PointF; import android.net.ConnectivityManager; import android.net.NetworkInfo; @@ -41,6 +42,8 @@ import com.mapbox.mapboxgl.geometry.LatLngZoom; import org.apache.commons.validator.routines.UrlValidator; +import java.nio.Buffer; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -216,6 +219,16 @@ public class MapView extends SurfaceView { } } + public void setSprite(String symbol, float scale, Bitmap bitmap) { + if(bitmap.getConfig() != Bitmap.Config.ARGB_8888) { + bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false); + } + ByteBuffer buffer = ByteBuffer.allocate(bitmap.getByteCount()); + bitmap.copyPixelsToBuffer(buffer); + + mNativeMapView.setSprite(symbol, bitmap.getWidth(), bitmap.getHeight(), scale, buffer.array()); + } + public Marker addMarker(MarkerOptions markerOptions) { Marker marker = markerOptions.getMarker(); Long id = mNativeMapView.addMarker(marker); @@ -243,6 +256,23 @@ public class MapView extends SurfaceView { return polygon; } + public List addPolygons(List polygonOptions) { + List polygons = new ArrayList<>(); + for(PolygonOptions popts : polygonOptions) { + polygons.add(popts.getPolygon()); + } + + long[] ids = mNativeMapView.addPolygons(polygons); + + for(int i=0; i polygon) { + // NH TODO Throw exception if returns -1 + return nativeAddPolygons(mNativeMapViewPtr, polygon); + } + public void removeAnnotation(long id) { nativeRemoveAnnotation(mNativeMapViewPtr, id); } + public void removeAnnotations(long[] ids) { + nativeRemoveAnnotations(mNativeMapViewPtr, ids); + } + public LatLng getLatLng() { return nativeGetLatLng(mNativeMapViewPtr); } @@ -466,14 +479,21 @@ class NativeMapView { private native void nativeSetLatLng(long nativeMapViewPtr, LatLng latLng, long duration); + private native void nativeSetSprite(long nativeMapViewPtr, String symbol, + int width, int height, float scale, byte[] pixels); + 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 long[] nativeAddPolygons(long mNativeMapViewPtr, List polygon); + private native void nativeRemoveAnnotation(long nativeMapViewPtr, long id); + private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id); + private native LatLng nativeGetLatLng(long nativeMapViewPtr); private native void nativeResetPosition(long nativeMapViewPtr); diff --git a/android/java/MapboxGLAndroidSDKTestApp/build.gradle b/android/java/MapboxGLAndroidSDKTestApp/build.gradle index 46c95c21e..d407629b2 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/build.gradle +++ b/android/java/MapboxGLAndroidSDKTestApp/build.gradle @@ -1,15 +1,23 @@ buildscript { repositories { mavenCentral() + maven { url 'https://maven.fabric.io/public' } } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0' + classpath 'io.fabric.tools:gradle:1.+' } } apply plugin: 'android-sdk-manager' apply plugin: 'com.android.application' +apply plugin: 'io.fabric' + +repositories { + maven { url 'https://maven.fabric.io/public' } +} + apply plugin: 'checkstyle' task accessToken { @@ -78,6 +86,9 @@ dependencies { compile 'com.android.support:support-v4:22.1.1' compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.mapzen.android:lost:1.0.0' + compile('com.crashlytics.sdk.android:crashlytics:2.4.0@aar') { + transitive = true; + } } checkstyle { diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index 901a63f57..fa21e4a12 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -20,6 +20,10 @@ + + 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 f8c35897c..87f076670 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 @@ -24,6 +24,7 @@ import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; +import com.crashlytics.android.Crashlytics; import com.mapbox.mapboxgl.annotations.Marker; import com.mapbox.mapboxgl.annotations.MarkerOptions; import com.mapbox.mapboxgl.annotations.Polygon; @@ -37,6 +38,7 @@ import com.mapzen.android.lost.api.LocationRequest; import com.mapzen.android.lost.api.LocationServices; import com.mapzen.android.lost.api.LostApiClient; +import io.fabric.sdk.android.Fabric; import org.json.JSONException; import java.io.IOException; @@ -100,6 +102,7 @@ public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + Fabric.with(this, new Crashlytics()); if (savedInstanceState != null) { mIsGpsOn = savedInstanceState.getBoolean(STATE_IS_GPS_ON, false); @@ -327,10 +330,12 @@ public class MainActivity extends ActionBarActivity { 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)); + ArrayList opts = new ArrayList(); + opts.add(new PolygonOptions() + .add(latLngs) + .strokeColor(Color.MAGENTA) + .fillColor(Color.BLUE)); + Polygon polygon = map.addPolygons(opts).get(0); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index 9795c44ad..7e4d3488e 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.5.2-symbols' + m.version = '0.5.3-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' diff --git a/scripts/ios/package.sh b/scripts/ios/package.sh index b6a927dd0..b499f4a10 100755 --- a/scripts/ios/package.sh +++ b/scripts/ios/package.sh @@ -101,7 +101,8 @@ step "Copying Resources..." cp -pv LICENSE.md "${OUTPUT}/static" mkdir -p "${OUTPUT}/static/${NAME}.bundle" cp -pv platform/ios/resources/* "${OUTPUT}/static/${NAME}.bundle" -cp -prv styles/styles "${OUTPUT}/static/${NAME}.bundle/styles" +mkdir -p "${OUTPUT}/static/${NAME}.bundle/styles" +cp -pv styles/styles/{dark,emerald,light,mapbox-streets,satellite}-v7.json "${OUTPUT}/static/${NAME}.bundle/styles" step "Creating API Docs..." if [ -z `which appledoc` ]; then diff --git a/styles b/styles index 6b0f8a9b1..44bdcec81 160000 --- a/styles +++ b/styles @@ -1 +1 @@ -Subproject commit 6b0f8a9b10ad96c43ec1e0e72ab23a48bcda8c21 +Subproject commit 44bdcec816407ba16765a556135915652e5e5b22