#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma clang diagnostic ignored "-Wunused-parameter" namespace mbgl { namespace android { JavaVM* theJVM; std::string cachePath; std::string dataPath; std::string apkPath; std::string androidRelease; jmethodID onInvalidateId = nullptr; jmethodID onMapChangedId = nullptr; jmethodID onFpsChangedId = nullptr; jclass latLngClass = nullptr; jmethodID latLngConstructorId = nullptr; jfieldID latLngLatitudeId = nullptr; jfieldID latLngLongitudeId = nullptr; jclass latLngZoomClass = nullptr; jmethodID latLngZoomConstructorId = nullptr; jfieldID latLngZoomLatitudeId = nullptr; jfieldID latLngZoomLongitudeId = nullptr; jfieldID latLngZoomZoomId = nullptr; jclass bboxClass = nullptr; jmethodID bboxConstructorId = nullptr; jfieldID bboxLatNorthId = nullptr; jfieldID bboxLatSouthId = nullptr; jfieldID bboxLonEastId = nullptr; jfieldID bboxLonWestId = 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 runtimeExceptionClass = nullptr; jclass nullPointerExceptionClass = nullptr; jmethodID listToArrayId = nullptr; jclass arrayListClass = nullptr; jmethodID arrayListConstructorId = nullptr; jmethodID arrayListAddId = nullptr; jclass projectedMetersClass = nullptr; jmethodID projectedMetersConstructorId = nullptr; jfieldID projectedMetersNorthingId = nullptr; jfieldID projectedMetersEastingId = nullptr; jclass pointFClass = nullptr; jmethodID pointFConstructorId = nullptr; jfieldID pointFXId = nullptr; jfieldID pointFYId = nullptr; jclass httpContextClass = nullptr; jmethodID httpContextGetInstanceId = nullptr; jmethodID httpContextCreateRequestId = nullptr; jclass httpRequestClass = nullptr; jmethodID httpRequestStartId = nullptr; jmethodID httpRequestCancelId = nullptr; bool throw_jni_error(JNIEnv *env, const char *msg) { if (env->ThrowNew(runtimeExceptionClass, msg) < 0) { env->ExceptionDescribe(); return false; } return true; } bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName) { assert(vm != nullptr); assert(env != nullptr); JavaVMAttachArgs args = {JNI_VERSION_1_2, threadName.c_str(), NULL}; jint ret; *env = nullptr; bool detach = false; ret = vm->GetEnv(reinterpret_cast(env), JNI_VERSION_1_6); if (ret != JNI_OK) { if (ret != JNI_EDETACHED) { mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret); throw new std::runtime_error("GetEnv() failed"); } else { ret = vm->AttachCurrentThread(env, &args); if (ret != JNI_OK) { mbgl::Log::Error(mbgl::Event::JNI, "AttachCurrentThread() failed with %i", ret); throw new std::runtime_error("AttachCurrentThread() failed"); } detach = true; } } return detach; } void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach) { if (detach) { assert(vm != nullptr); assert(env != nullptr); jint ret; if ((ret = vm->DetachCurrentThread()) != JNI_OK) { mbgl::Log::Error(mbgl::Event::JNI, "DetachCurrentThread() failed with %i", ret); throw new std::runtime_error("DetachCurrentThread() failed"); } } *env = nullptr; } std::string std_string_from_jstring(JNIEnv *env, jstring jstr) { std::string str; if (jstr == nullptr) { if (env->ThrowNew(nullPointerExceptionClass, "String cannot be null.") < 0) { env->ExceptionDescribe(); return str; } return str; } jsize len = env->GetStringLength(jstr); if (len < 0) { env->ExceptionDescribe(); return str; } const jchar *chars = env->GetStringChars(jstr, nullptr); if (chars == nullptr) { env->ExceptionDescribe(); return str; } std::u16string ustr(reinterpret_cast(chars), len); env->ReleaseStringChars(jstr, chars); chars = nullptr; str = std::wstring_convert, char16_t>().to_bytes(ustr); return str; } jstring std_string_to_jstring(JNIEnv *env, std::string str) { std::u16string ustr = std::wstring_convert, char16_t>().from_bytes(str); jstring jstr = env->NewString(reinterpret_cast(ustr.c_str()), ustr.size()); if (jstr == nullptr) { env->ExceptionDescribe(); return nullptr; } return jstr; } std::vector std_vector_string_from_jobject(JNIEnv *env, jobject jlist) { std::vector vector; if (jlist == nullptr) { if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) { env->ExceptionDescribe(); return vector; } return vector; } jobjectArray jarray = reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); if (env->ExceptionCheck() || (jarray == nullptr)) { env->ExceptionDescribe(); return vector; } jsize len = env->GetArrayLength(jarray); if (len < 0) { env->ExceptionDescribe(); return vector; } for (jsize i = 0; i < len; i++) { jstring jstr = reinterpret_cast(env->GetObjectArrayElement(jarray, i)); if (jstr == nullptr) { env->ExceptionDescribe(); return vector; } vector.push_back(std_string_from_jstring(env, jstr)); } env->DeleteLocalRef(jarray); jarray = nullptr; return vector; } jobject std_vector_string_to_jobject(JNIEnv *env, std::vector vector) { jobject jlist = env->NewObject(arrayListClass, arrayListConstructorId); if (jlist == nullptr) { env->ExceptionDescribe(); return nullptr; } for (const auto& str : vector) { env->CallBooleanMethod(jlist, arrayListAddId, std_string_to_jstring(env, str)); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } } 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; } 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 jarray = reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); if (env->ExceptionCheck() || (jarray == nullptr)) { env->ExceptionDescribe(); return segment; } jsize len = env->GetArrayLength(jarray); if (len < 0) { env->ExceptionDescribe(); return segment; } segment.reserve(len); for (jsize i = 0; i < len; i++) { jobject latLng = reinterpret_cast(env->GetObjectArrayElement(jarray, 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)); env->DeleteLocalRef(latLng); } env->DeleteLocalRef(jarray); jarray = nullptr; return segment; } std::pair annotation_std_pair_from_polygon_jobject(JNIEnv *env, jobject polygon) { jfloat alpha = env->GetFloatField(polygon, polygonAlphaId); //jboolean visible = env->GetBooleanField(polygon, polygonVisibleId); jint fillColor = env->GetIntField(polygon, polygonFillColorId); jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId); 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; mbgl::StyleProperties shapeProperties; mbgl::FillProperties fillProperties; fillProperties.opacity = alpha; fillProperties.stroke_color = {{ static_cast(rS) / 255.0f, static_cast(gS) / 255.0f, static_cast(bS) / 255.0f, static_cast(aS) / 255.0f }}; fillProperties.fill_color = {{ static_cast(rF) / 255.0f, static_cast(gF) / 255.0f, static_cast(bF) / 255.0f, static_cast(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); } } } namespace { using namespace mbgl::android; jlong JNICALL nativeCreate(JNIEnv *env, jobject obj, jstring cachePath_, jstring dataPath_, jstring apkPath_, jfloat pixelRatio, jint availableProcessors, jlong totalMemory) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeCreate"); cachePath = std_string_from_jstring(env, cachePath_); dataPath = std_string_from_jstring(env, dataPath_); apkPath = std_string_from_jstring(env, apkPath_); NativeMapView *nativeMapView = new NativeMapView(env, obj, pixelRatio, availableProcessors, totalMemory); jlong mapViewPtr = reinterpret_cast(nativeMapView); return mapViewPtr; } void JNICALL nativeDestroy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeDestroy"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); delete nativeMapView; nativeMapView = nullptr; } void JNICALL nativeInitializeDisplay(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeInitializeDisplay"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); try { nativeMapView->initializeDisplay(); } catch(const std::exception& e) { throw_jni_error(env, "Unable to initialize GL display."); } } void JNICALL nativeTerminateDisplay(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminateDisplay"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->terminateDisplay(); } void JNICALL nativeInitializeContext(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeInitializeContext"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); try { nativeMapView->initializeContext(); } catch(const std::exception& e) { throw_jni_error(env, "Unable to initialize GL context."); } } void JNICALL nativeTerminateContext(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminateContext"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->terminateContext(); } void JNICALL nativeCreateSurface(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject surface) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeCreateSurface"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); try { nativeMapView->createSurface(ANativeWindow_fromSurface(env, surface)); } catch(const std::exception& e) { throw_jni_error(env, "Unable to create GL surface."); } } void JNICALL nativeDestroySurface(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeDestroySurface"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->destroySurface(); } void JNICALL nativePause(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativePause"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->pause(); } void JNICALL nativeResume(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeResume"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->resume(); } void JNICALL nativeUpdate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().update(mbgl::Update::Repaint); } void JNICALL nativeRenderSync(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeRenderSync"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->renderSync(); } void JNICALL nativeViewResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeViewResize"); assert(nativeMapViewPtr != 0); assert(width >= 0); assert(height >= 0); assert(width <= UINT16_MAX); assert(height <= UINT16_MAX); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->resizeView(width, height); } void JNICALL nativeFramebufferResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint fbWidth, jint fbHeight) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeFramebufferResize"); assert(nativeMapViewPtr != 0); assert(fbWidth >= 0); assert(fbHeight >= 0); assert(fbWidth <= UINT16_MAX); assert(fbHeight <= UINT16_MAX); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->resizeFramebuffer(fbWidth, fbHeight); } void JNICALL nativeRemoveClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveClass"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().removeClass(std_string_from_jstring(env, clazz)); } jboolean JNICALL nativeHasClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeHasClass"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().hasClass(std_string_from_jstring(env, clazz)); } void JNICALL nativeAddClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddClass"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().addClass(std_string_from_jstring(env, clazz)); } void JNICALL nativeSetClasses(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject classes) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetClasses"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setClasses(std_vector_string_from_jobject(env, classes)); } jobject JNICALL nativeGetClasses(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetClasses"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return std_vector_string_to_jobject(env, nativeMapView->getMap().getClasses()); } void JNICALL nativeSetDefaultTransitionDuration(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDefaultTransitionDuration"); assert(nativeMapViewPtr != 0); assert(duration >= 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setDefaultTransitionDuration(std::chrono::milliseconds(duration)); } jlong JNICALL nativeGetDefaultTransitionDuration(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetDefaultTransitionDuration"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return std::chrono::duration_cast(nativeMapView->getMap().getDefaultTransitionDuration()).count(); } void JNICALL nativeSetStyleURL(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring url) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleURL"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url)); } void JNICALL nativeSetStyleJSON(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring newStyleJson, jstring base) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleJSON"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson), std_string_from_jstring(env, base)); } jstring JNICALL nativeGetStyleJSON(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetStyleJSON"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return std_string_to_jstring(env, nativeMapView->getMap().getStyleJSON()); } void JNICALL nativeSetAccessToken(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring accessToken) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetAccessToken"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getFileSource().setAccessToken(std_string_from_jstring(env, accessToken)); } jstring JNICALL nativeGetAccessToken(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetAccessToken"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return std_string_to_jstring(env, nativeMapView->getFileSource().getAccessToken()); } void JNICALL nativeCancelTransitions(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeCancelTransitions"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().cancelTransitions(); } void JNICALL nativeSetGestureInProgress(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean inProgress) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetGestureInProgress"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setGestureInProgress(inProgress); } void JNICALL nativeMoveBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble dx, jdouble dy, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeMoveBy"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().moveBy(dx, dy, std::chrono::milliseconds(duration)); } void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLatLng"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration)); } jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(); jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; } return ret; } void JNICALL nativeResetPosition(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetPosition"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().resetPosition(); } void JNICALL nativeScaleBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble ds, jdouble cx, jdouble cy, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeScaleBy"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().scaleBy(ds, cx, cy, std::chrono::milliseconds(duration)); } void JNICALL nativeSetScale(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble scale, jdouble cx, jdouble cy, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetScale"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setScale(scale, cx, cy, std::chrono::milliseconds(duration)); } jdouble JNICALL nativeGetScale(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetScale"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getScale(); } void JNICALL nativeSetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble zoom, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setZoom(zoom, std::chrono::milliseconds(duration)); } jdouble JNICALL nativeGetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getZoom(); } void JNICALL nativeSetLatLngZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLngZoom, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLatLngZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); jdouble latitude = env->GetDoubleField(latLngZoom, latLngZoomLatitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } jdouble longitude = env->GetDoubleField(latLngZoom, latLngZoomLongitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } jdouble zoom = env->GetDoubleField(latLngZoom, latLngZoomZoomId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } nativeMapView->getMap().setLatLngZoom(mbgl::LatLng(latitude, longitude), zoom, std::chrono::milliseconds(duration)); } jobject JNICALL nativeGetLatLngZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLngZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(); jdouble zoom = nativeMapView->getMap().getZoom(); jobject ret = env->NewObject(latLngZoomClass, latLngZoomConstructorId, latLng.longitude, latLng.latitude, zoom); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; } return ret; } void JNICALL nativeResetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().resetZoom(); } jdouble JNICALL nativeGetMinZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMinZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getMinZoom(); } jdouble JNICALL nativeGetMaxZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMaxZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getMaxZoom(); } void JNICALL nativeRotateBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble sx, jdouble sy, jdouble ex, jdouble ey, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeRotateBy"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().rotateBy(sx, sy, ex, ey, std::chrono::milliseconds(duration)); } void JNICALL nativeSetBearing(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble degrees, jlong duration) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetBearing"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setBearing(degrees, std::chrono::milliseconds(duration)); } void JNICALL nativeSetBearing(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble degrees, jdouble cx, jdouble cy) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetBearing"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setBearing(degrees, cx, cy); } jdouble JNICALL nativeGetBearing(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetBearing"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getBearing(); } void JNICALL nativeResetNorth(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetNorth"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().resetNorth(); } 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(nativeMapViewPtr); jobject position = env->GetObjectField(marker, markerPositionId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return -1; } jstring jsprite = reinterpret_cast(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 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(nativeMapViewPtr); 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; }*/ 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 = {{ static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f, static_cast(a) / 255.0f }}; lineProperties.width = width; shapeProperties.set(lineProperties); jobject points = env->GetObjectField(polyline, polylinePointsId); mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); std::vector shapes; shapes.emplace_back(mbgl::AnnotationSegments { segment }, shapeProperties); std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); uint32_t id = shapeAnnotationIDs.at(0); return 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::vector shapes; std::pair segment = annotation_std_pair_from_polygon_jobject(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 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 jarray = reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId)); if (env->ExceptionCheck() || (jarray == nullptr)) { env->ExceptionDescribe(); return nullptr; } jsize len = env->GetArrayLength(jarray); if (len < 0) { env->ExceptionDescribe(); return nullptr; } shapes.reserve(len); for (jsize i = 0; i < len; i++) { jobject polygon = reinterpret_cast(env->GetObjectArrayElement(jarray, i)); std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second); env->DeleteLocalRef(polygon); } env->DeleteLocalRef(jarray); 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); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().removeAnnotation(static_cast(annotationId)); } void JNICALL nativeRemoveAnnotations(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlongArray jarray) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotations"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); std::vector ids; if (env->ExceptionCheck() || (jarray == nullptr)) { env->ExceptionDescribe(); return; } jsize len = env->GetArrayLength(jarray); if (len < 0) { env->ExceptionDescribe(); return; } ids.reserve(len); jlong* jids = env->GetLongArrayElements(jarray, nullptr); for (jsize i = 0; i < len; i++) { if(jids[i] == -1L) continue; ids.push_back(static_cast(jids[i])); } env->ReleaseLongArrayElements(jarray, jids, JNI_ABORT); nativeMapView->getMap().removeAnnotations(ids); } jlongArray JNICALL nativeGetAnnotationsInBounds(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject bbox) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetAnnotationsInBounds"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); if (env->ExceptionCheck() || (bbox == nullptr)) { env->ExceptionDescribe(); return nullptr; } jdouble swLat = env->GetDoubleField(bbox, bboxLatSouthId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jdouble swLon = env->GetDoubleField(bbox, bboxLonWestId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jdouble neLat = env->GetDoubleField(bbox, bboxLatNorthId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jdouble neLon = env->GetDoubleField(bbox, bboxLonEastId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } mbgl::LatLngBounds bounds; bounds.sw = { swLat, swLon }; bounds.ne = { neLat, neLon }; // assume only points for now std::vector annotations = nativeMapView->getMap().getAnnotationsInBounds(bounds, mbgl::AnnotationType::Point); return std_vector_uint_to_jobject(env, annotations); } 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(reinterpret_cast(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); } void JNICALL nativeOnLowMemory(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnLowMemory"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().onLowMemory(); } void JNICALL nativeSetDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean debug) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDebug"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setDebug(debug); nativeMapView->enableFps(debug); } void JNICALL nativeToggleDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeToggleDebug"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().toggleDebug(); nativeMapView->enableFps(nativeMapView->getMap().getDebug()); } jboolean JNICALL nativeGetDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetDebug"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getDebug(); } void JNICALL nativeSetCollisionDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean debug) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetCollisionDebug"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().setCollisionDebug(debug); } void JNICALL nativeToggleCollisionDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeToggleCollisionDebug"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); nativeMapView->getMap().toggleCollisionDebug(); } jboolean JNICALL nativeGetCollisionDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetCollisionDebug"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getCollisionDebug(); } jboolean JNICALL nativeIsFullyLoaded(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeIsFullyLoaded"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().isFullyLoaded(); } void JNICALL nativeSetReachability(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean status) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetReachability"); assert(nativeMapViewPtr != 0); if (status) { mbgl::NetworkStatus::Reachable(); } } jdouble JNICALL nativeGetMetersPerPixelAtLatitude(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble lat, jdouble zoom) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMetersPerPixelAtLatitude"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getMetersPerPixelAtLatitude(lat, zoom); } jobject JNICALL nativeProjectedMetersForLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeProjectedMetersForLatLng"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } mbgl::ProjectedMeters projectedMeters = nativeMapView->getMap().projectedMetersForLatLng(mbgl::LatLng(latitude, longitude)); jobject ret = env->NewObject(projectedMetersClass, projectedMetersConstructorId, projectedMeters.northing, projectedMeters.easting); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; } return ret; } jobject JNICALL nativeLatLngForProjectedMeters(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject projectedMeters) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeLatLngForProjectedMeters"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); jdouble northing = env->GetDoubleField(projectedMeters, projectedMetersNorthingId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jdouble easting = env->GetDoubleField(projectedMeters, projectedMetersEastingId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } mbgl::LatLng latLng = nativeMapView->getMap().latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting)); jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; } return ret; } jobject JNICALL nativePixelForLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng) { mbgl::Log::Debug(mbgl::Event::JNI, "nativePixelForLatLng"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } mbgl::vec2 pixel = nativeMapView->getMap().pixelForLatLng(mbgl::LatLng(latitude, longitude)); jobject ret = env->NewObject(pointFClass, pointFConstructorId, static_cast(pixel.x), static_cast(pixel.y)); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; } return ret; } jobject JNICALL nativeLatLngForPixel(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject pixel) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeLatLngForPixel"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); jfloat x = env->GetFloatField(pixel, pointFXId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } jfloat y = env->GetFloatField(pixel, pointFYId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return nullptr; } mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::vec2(x, y)); jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; } return ret; } jdouble JNICALL nativeGetTopOffsetPixelsForAnnotationSymbol(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring symbolName) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetTopOffsetPixelsForAnnotationSymbol"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); return nativeMapView->getMap().getTopOffsetPixelsForAnnotationSymbol(std_string_from_jstring(env, symbolName)); } } extern "C" { extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { mbgl::Log::Debug(mbgl::Event::JNI, "JNI_OnLoad"); theJVM = vm; JNIEnv *env = nullptr; jint ret = vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); if (ret != JNI_OK) { mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret); return JNI_ERR; } latLngClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLng"); if (latLngClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngConstructorId = env->GetMethodID(latLngClass, "", "(DD)V"); if (latLngConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngLatitudeId = env->GetFieldID(latLngClass, "latitude", "D"); if (latLngLatitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngLongitudeId = env->GetFieldID(latLngClass, "longitude", "D"); if (latLngLongitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom"); if (latLngZoomClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngZoomConstructorId = env->GetMethodID(latLngZoomClass, "", "(DDD)V"); if (latLngZoomConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngZoomLatitudeId = env->GetFieldID(latLngZoomClass, "latitude", "D"); if (latLngZoomLatitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngZoomLongitudeId = env->GetFieldID(latLngZoomClass, "longitude", "D"); if (latLngZoomLongitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngZoomZoomId = env->GetFieldID(latLngZoomClass, "zoom", "D"); if (latLngZoomZoomId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } bboxClass = env->FindClass("com/mapbox/mapboxgl/geometry/BoundingBox"); if (bboxClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } bboxConstructorId = env->GetMethodID(bboxClass, "", "(DDDD)V"); if (bboxConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } bboxLatNorthId = env->GetFieldID(bboxClass, "mLatNorth", "D"); if (bboxLatNorthId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } bboxLatSouthId = env->GetFieldID(bboxClass, "mLatSouth", "D"); if (bboxLatSouthId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } bboxLonEastId = env->GetFieldID(bboxClass, "mLonEast", "D"); if (bboxLonEastId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } bboxLonWestId = env->GetFieldID(bboxClass, "mLonWest", "D"); if (bboxLonWestId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } markerClass = env->FindClass("com/mapbox/mapboxgl/annotations/Marker"); if (markerClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } markerConstructorId = env->GetMethodID(markerClass, "", "()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, "", "()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, "", "()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; } jclass nativeMapViewClass = env->FindClass("com/mapbox/mapboxgl/views/NativeMapView"); if (nativeMapViewClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } onInvalidateId = env->GetMethodID(nativeMapViewClass, "onInvalidate", "()V"); if (onInvalidateId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } onMapChangedId = env->GetMethodID(nativeMapViewClass, "onMapChanged", "(I)V"); if (onMapChangedId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } onFpsChangedId = env->GetMethodID(nativeMapViewClass, "onFpsChanged", "(D)V"); if (onFpsChangedId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } runtimeExceptionClass = env->FindClass("java/lang/RuntimeException"); if (runtimeExceptionClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } nullPointerExceptionClass = env->FindClass("java/lang/NullPointerException"); if (nullPointerExceptionClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } jclass listClass = env->FindClass("java/util/List"); if (listClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } listToArrayId = env->GetMethodID(listClass, "toArray", "()[Ljava/lang/Object;"); if (listToArrayId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } arrayListClass = env->FindClass("java/util/ArrayList"); if (arrayListClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } arrayListConstructorId = env->GetMethodID(arrayListClass, "", "()V"); if (arrayListConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } arrayListAddId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); if (arrayListAddId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } projectedMetersClass = env->FindClass("com/mapbox/mapboxgl/geometry/ProjectedMeters"); if (projectedMetersClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } projectedMetersConstructorId = env->GetMethodID(projectedMetersClass, "", "(DD)V"); if (projectedMetersConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } projectedMetersNorthingId = env->GetFieldID(projectedMetersClass, "northing", "D"); if (projectedMetersNorthingId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } projectedMetersEastingId = env->GetFieldID(projectedMetersClass, "easting", "D"); if (projectedMetersEastingId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } pointFClass = env->FindClass("android/graphics/PointF"); if (pointFClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } pointFConstructorId = env->GetMethodID(pointFClass, "", "(FF)V"); if (pointFConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } pointFXId = env->GetFieldID(pointFClass, "x", "F"); if (pointFXId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } pointFYId = env->GetFieldID(pointFClass, "y", "F"); if (pointFYId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } httpContextClass = env->FindClass("com/mapbox/mapboxgl/http/HTTPContext"); if (httpContextClass == nullptr) { env->ExceptionDescribe(); } httpContextGetInstanceId = env->GetStaticMethodID(httpContextClass, "getInstance", "()Lcom/mapbox/mapboxgl/http/HTTPContext;"); if (httpContextGetInstanceId == nullptr) { env->ExceptionDescribe(); } httpContextCreateRequestId = env->GetMethodID(httpContextClass, "createRequest", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/mapbox/mapboxgl/http/HTTPContext$HTTPRequest;"); if (httpContextCreateRequestId == nullptr) { env->ExceptionDescribe(); } httpRequestClass = env->FindClass("com/mapbox/mapboxgl/http/HTTPContext$HTTPRequest"); if (httpRequestClass == nullptr) { env->ExceptionDescribe(); } httpRequestStartId = env->GetMethodID(httpRequestClass, "start", "()V"); if (httpRequestStartId == nullptr) { env->ExceptionDescribe(); } httpRequestCancelId = env->GetMethodID(httpRequestClass, "cancel", "()V"); if (httpRequestCancelId == nullptr) { env->ExceptionDescribe(); } const std::vector methods = { {"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;FIJ)J", reinterpret_cast(&nativeCreate)}, {"nativeDestroy", "(J)V", reinterpret_cast(&nativeDestroy)}, {"nativeInitializeDisplay", "(J)V", reinterpret_cast(&nativeInitializeDisplay)}, {"nativeTerminateDisplay", "(J)V", reinterpret_cast(&nativeTerminateDisplay)}, {"nativeInitializeContext", "(J)V", reinterpret_cast(&nativeInitializeContext)}, {"nativeTerminateContext", "(J)V", reinterpret_cast(&nativeTerminateContext)}, {"nativeCreateSurface", "(JLandroid/view/Surface;)V", reinterpret_cast(&nativeCreateSurface)}, {"nativeDestroySurface", "(J)V", reinterpret_cast(&nativeDestroySurface)}, {"nativePause", "(J)V", reinterpret_cast(&nativePause)}, {"nativeResume", "(J)V", reinterpret_cast(&nativeResume)}, {"nativeUpdate", "(J)V", reinterpret_cast(&nativeUpdate)}, {"nativeRenderSync", "(J)V", reinterpret_cast(&nativeRenderSync)}, {"nativeViewResize", "(JII)V", reinterpret_cast(static_cast(&nativeViewResize))}, {"nativeFramebufferResize", "(JII)V", reinterpret_cast(static_cast(&nativeFramebufferResize))}, {"nativeAddClass", "(JLjava/lang/String;)V", reinterpret_cast(&nativeAddClass)}, {"nativeRemoveClass", "(JLjava/lang/String;)V", reinterpret_cast(&nativeRemoveClass)}, {"nativeHasClass", "(JLjava/lang/String;)Z", reinterpret_cast(&nativeHasClass)}, {"nativeSetClasses", "(JLjava/util/List;)V", reinterpret_cast(&nativeSetClasses)}, {"nativeGetClasses", "(J)Ljava/util/List;", reinterpret_cast(&nativeGetClasses)}, {"nativeSetDefaultTransitionDuration", "(JJ)V", reinterpret_cast(&nativeSetDefaultTransitionDuration)}, {"nativeGetDefaultTransitionDuration", "(J)J", reinterpret_cast(&nativeGetDefaultTransitionDuration)}, {"nativeSetStyleUrl", "(JLjava/lang/String;)V", reinterpret_cast(&nativeSetStyleURL)}, {"nativeSetStyleJson", "(JLjava/lang/String;Ljava/lang/String;)V", reinterpret_cast(&nativeSetStyleJSON)}, {"nativeGetStyleJson", "(J)Ljava/lang/String;", reinterpret_cast(&nativeGetStyleJSON)}, {"nativeSetAccessToken", "(JLjava/lang/String;)V", reinterpret_cast(&nativeSetAccessToken)}, {"nativeGetAccessToken", "(J)Ljava/lang/String;", reinterpret_cast(&nativeGetAccessToken)}, {"nativeCancelTransitions", "(J)V", reinterpret_cast(&nativeCancelTransitions)}, {"nativeSetGestureInProgress", "(JZ)V", reinterpret_cast(&nativeSetGestureInProgress)}, {"nativeMoveBy", "(JDDJ)V", reinterpret_cast(&nativeMoveBy)}, {"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V", reinterpret_cast(&nativeSetLatLng)}, {"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeGetLatLng)}, {"nativeResetPosition", "(J)V", reinterpret_cast(&nativeResetPosition)}, {"nativeScaleBy", "(JDDDJ)V", reinterpret_cast(&nativeScaleBy)}, {"nativeSetScale", "(JDDDJ)V", reinterpret_cast(&nativeSetScale)}, {"nativeGetScale", "(J)D", reinterpret_cast(&nativeGetScale)}, {"nativeSetZoom", "(JDJ)V", reinterpret_cast(&nativeSetZoom)}, {"nativeGetZoom", "(J)D", reinterpret_cast(&nativeGetZoom)}, {"nativeSetLatLngZoom", "(JLcom/mapbox/mapboxgl/geometry/LatLngZoom;J)V", reinterpret_cast(&nativeSetLatLngZoom)}, {"nativeGetLatLngZoom", "(J)Lcom/mapbox/mapboxgl/geometry/LatLngZoom;", reinterpret_cast(&nativeGetLatLngZoom)}, {"nativeResetZoom", "(J)V", reinterpret_cast(&nativeResetZoom)}, {"nativeGetMinZoom", "(J)D", reinterpret_cast(&nativeGetMinZoom)}, {"nativeGetMaxZoom", "(J)D", reinterpret_cast(&nativeGetMaxZoom)}, {"nativeRotateBy", "(JDDDDJ)V", reinterpret_cast(&nativeRotateBy)}, {"nativeSetBearing", "(JDJ)V", reinterpret_cast( static_cast( &nativeSetBearing))}, {"nativeSetBearing", "(JDDD)V", reinterpret_cast( static_cast( &nativeSetBearing))}, {"nativeGetBearing", "(J)D", reinterpret_cast(&nativeGetBearing)}, {"nativeResetNorth", "(J)V", reinterpret_cast(&nativeResetNorth)}, {"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)}, {"nativeGetAnnotationsInBounds", "(JLcom/mapbox/mapboxgl/geometry/BoundingBox;)[J", reinterpret_cast(&nativeGetAnnotationsInBounds)}, {"nativeSetSprite", "(JLjava/lang/String;IIF[B)V", reinterpret_cast(&nativeSetSprite)}, {"nativeOnLowMemory", "(J)V", reinterpret_cast(&nativeOnLowMemory)}, {"nativeSetDebug", "(JZ)V", reinterpret_cast(&nativeSetDebug)}, {"nativeToggleDebug", "(J)V", reinterpret_cast(&nativeToggleDebug)}, {"nativeGetDebug", "(J)Z", reinterpret_cast(&nativeGetDebug)}, {"nativeSetCollisionDebug", "(JZ)V", reinterpret_cast(&nativeSetCollisionDebug)}, {"nativeToggleCollisionDebug", "(J)V", reinterpret_cast(&nativeToggleCollisionDebug)}, {"nativeGetCollisionDebug", "(J)Z", reinterpret_cast(&nativeGetCollisionDebug)}, {"nativeIsFullyLoaded", "(J)Z", reinterpret_cast(&nativeIsFullyLoaded)}, {"nativeSetReachability", "(JZ)V", reinterpret_cast(&nativeSetReachability)}, //{"nativeGetWorldBoundsMeters", "(J)V", reinterpret_cast(&nativeGetWorldBoundsMeters)}, //{"nativeGetWorldBoundsLatLng", "(J)V", reinterpret_cast(&nativeGetWorldBoundsLatLng)}, {"nativeGetMetersPerPixelAtLatitude", "(JDD)D", reinterpret_cast(&nativeGetMetersPerPixelAtLatitude)}, {"nativeProjectedMetersForLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Lcom/mapbox/mapboxgl/geometry/ProjectedMeters;", reinterpret_cast(&nativeProjectedMetersForLatLng)}, {"nativeLatLngForProjectedMeters", "(JLcom/mapbox/mapboxgl/geometry/ProjectedMeters;)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeLatLngForProjectedMeters)}, {"nativePixelForLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Landroid/graphics/PointF;", reinterpret_cast(&nativePixelForLatLng)}, {"nativeLatLngForPixel", "(JLandroid/graphics/PointF;)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeLatLngForPixel)}, {"nativeGetTopOffsetPixelsForAnnotationSymbol", "(JLjava/lang/String;)D", reinterpret_cast(&nativeGetTopOffsetPixelsForAnnotationSymbol)}, }; if (env->RegisterNatives(nativeMapViewClass, methods.data(), methods.size()) < 0) { env->ExceptionDescribe(); return JNI_ERR; } latLngClass = reinterpret_cast(env->NewGlobalRef(latLngClass)); if (latLngClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } latLngZoomClass = reinterpret_cast(env->NewGlobalRef(latLngZoomClass)); if (latLngZoomClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); return JNI_ERR; } bboxClass = reinterpret_cast(env->NewGlobalRef(bboxClass)); if (bboxClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); return JNI_ERR; } markerClass = reinterpret_cast(env->NewGlobalRef(markerClass)); if (markerClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); return JNI_ERR; } polylineClass = reinterpret_cast(env->NewGlobalRef(polylineClass)); if (polylineClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(markerClass); return JNI_ERR; } polygonClass = reinterpret_cast(env->NewGlobalRef(polygonClass)); if (polygonClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(polylineClass); return JNI_ERR; } runtimeExceptionClass = reinterpret_cast(env->NewGlobalRef(runtimeExceptionClass)); if (runtimeExceptionClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); return JNI_ERR; } nullPointerExceptionClass = reinterpret_cast(env->NewGlobalRef(nullPointerExceptionClass)); if (nullPointerExceptionClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); return JNI_ERR; } arrayListClass = reinterpret_cast(env->NewGlobalRef(arrayListClass)); if (arrayListClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); return JNI_ERR; } projectedMetersClass = reinterpret_cast(env->NewGlobalRef(projectedMetersClass)); if (projectedMetersClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); env->DeleteGlobalRef(arrayListClass); return JNI_ERR; } pointFClass = reinterpret_cast(env->NewGlobalRef(pointFClass)); if (pointFClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); env->DeleteGlobalRef(arrayListClass); env->DeleteGlobalRef(projectedMetersClass); return JNI_ERR; } httpContextClass = reinterpret_cast(env->NewGlobalRef(httpContextClass)); if (httpContextClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); env->DeleteGlobalRef(arrayListClass); env->DeleteGlobalRef(projectedMetersClass); env->DeleteGlobalRef(pointFClass); } httpRequestClass = reinterpret_cast(env->NewGlobalRef(httpRequestClass)); if (httpRequestClass == nullptr) { env->ExceptionDescribe(); env->DeleteGlobalRef(latLngClass); env->DeleteGlobalRef(markerClass); env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(bboxClass); env->DeleteGlobalRef(polylineClass); env->DeleteGlobalRef(polygonClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); env->DeleteGlobalRef(arrayListClass); env->DeleteGlobalRef(projectedMetersClass); env->DeleteGlobalRef(pointFClass); env->DeleteGlobalRef(httpContextClass); } char release[PROP_VALUE_MAX] = ""; __system_property_get("ro.build.version.release", release); androidRelease = std::string(release); return JNI_VERSION_1_6; } extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { mbgl::Log::Debug(mbgl::Event::JNI, "JNI_OnUnload"); theJVM = vm; JNIEnv *env = nullptr; jint ret = vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); if (ret != JNI_OK) { mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret); throw new std::runtime_error("GetEnv() failed"); } env->DeleteGlobalRef(latLngClass); latLngClass = nullptr; latLngConstructorId = nullptr; latLngLongitudeId = nullptr; latLngLatitudeId = nullptr; env->DeleteGlobalRef(latLngZoomClass); latLngZoomClass = nullptr; latLngZoomConstructorId = nullptr; latLngZoomLongitudeId = nullptr; latLngZoomLatitudeId = nullptr; latLngZoomZoomId = nullptr; env->DeleteGlobalRef(bboxClass); bboxClass = nullptr; bboxConstructorId = nullptr; bboxLatNorthId = nullptr; bboxLatSouthId = nullptr; bboxLonEastId = nullptr; bboxLonWestId = 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; onInvalidateId = nullptr; onMapChangedId = nullptr; onFpsChangedId = nullptr; env->DeleteGlobalRef(runtimeExceptionClass); runtimeExceptionClass = nullptr; env->DeleteGlobalRef(nullPointerExceptionClass); nullPointerExceptionClass = nullptr; listToArrayId = nullptr; env->DeleteGlobalRef(arrayListClass); arrayListClass = nullptr; arrayListConstructorId = nullptr; arrayListAddId = nullptr; env->DeleteGlobalRef(projectedMetersClass); projectedMetersClass = nullptr; projectedMetersConstructorId = nullptr; projectedMetersNorthingId = nullptr; projectedMetersEastingId = nullptr; env->DeleteGlobalRef(pointFClass); pointFClass = nullptr; pointFConstructorId = nullptr; pointFXId = nullptr; pointFYId = nullptr; env->DeleteGlobalRef(httpContextClass); httpContextGetInstanceId = nullptr; httpContextCreateRequestId = nullptr; env->DeleteGlobalRef(httpRequestClass); httpRequestStartId = nullptr; httpRequestCancelId = nullptr; theJVM = nullptr; } }