1955 lines
93 KiB
C++
Executable File
1955 lines
93 KiB
C++
Executable File
#include <cstdint>
|
|
#include <cinttypes>
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <array>
|
|
#include <vector>
|
|
|
|
#include <android/native_window_jni.h>
|
|
#include <sys/system_properties.h>
|
|
|
|
#include "jni.hpp"
|
|
#include "java_types.hpp"
|
|
#include "native_map_view.hpp"
|
|
#include "connectivity_listener.hpp"
|
|
#include "style/layers/layers.hpp"
|
|
#include "style/sources/sources.hpp"
|
|
|
|
#include "conversion/conversion.hpp"
|
|
#include "conversion/collection.hpp"
|
|
#include "geometry/conversion/feature.hpp"
|
|
|
|
#include <mbgl/map/map.hpp>
|
|
#include <mbgl/map/camera.hpp>
|
|
#include <mbgl/annotation/annotation.hpp>
|
|
#include <mbgl/style/layer.hpp>
|
|
#include <mbgl/style/source.hpp>
|
|
#include <mbgl/sprite/sprite_image.hpp>
|
|
#include <mbgl/platform/event.hpp>
|
|
#include <mbgl/platform/log.hpp>
|
|
#include <mbgl/storage/network_status.hpp>
|
|
#include <mbgl/util/exception.hpp>
|
|
#include <mbgl/util/optional.hpp>
|
|
#include <mbgl/util/string.hpp>
|
|
#include <mbgl/util/run_loop.hpp>
|
|
|
|
#include <mapbox/geometry.hpp>
|
|
|
|
#include <jni/jni.hpp>
|
|
|
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
|
|
|
namespace mbgl {
|
|
namespace android {
|
|
|
|
void RegisterNativeHTTPRequest(JNIEnv&);
|
|
|
|
JavaVM* theJVM;
|
|
|
|
std::string cachePath;
|
|
std::string dataPath;
|
|
std::string apkPath;
|
|
std::string androidRelease;
|
|
|
|
jni::jmethodID* onInvalidateId = nullptr;
|
|
jni::jmethodID* onMapChangedId = nullptr;
|
|
jni::jmethodID* onFpsChangedId = nullptr;
|
|
jni::jmethodID* onSnapshotReadyId = nullptr;
|
|
|
|
jni::jclass* latLngClass = nullptr;
|
|
jni::jmethodID* latLngConstructorId = nullptr;
|
|
jni::jfieldID* latLngLatitudeId = nullptr;
|
|
jni::jfieldID* latLngLongitudeId = nullptr;
|
|
|
|
jni::jclass* latLngBoundsClass = nullptr;
|
|
jni::jmethodID* latLngBoundsConstructorId = nullptr;
|
|
jni::jfieldID* latLngBoundsLatNorthId = nullptr;
|
|
jni::jfieldID* latLngBoundsLatSouthId = nullptr;
|
|
jni::jfieldID* latLngBoundsLonEastId = nullptr;
|
|
jni::jfieldID* latLngBoundsLonWestId = nullptr;
|
|
|
|
jni::jclass* iconClass = nullptr;
|
|
jni::jfieldID* iconIdId = nullptr;
|
|
|
|
jni::jclass* markerClass = nullptr;
|
|
jni::jfieldID* markerPositionId = nullptr;
|
|
jni::jfieldID* markerIconId = nullptr;
|
|
jni::jfieldID* markerIdId = nullptr;
|
|
|
|
jni::jclass* polylineClass = nullptr;
|
|
jni::jfieldID* polylineAlphaId = nullptr;
|
|
jni::jfieldID* polylineColorId = nullptr;
|
|
jni::jfieldID* polylineWidthId = nullptr;
|
|
jni::jfieldID* polylinePointsId = nullptr;
|
|
|
|
jni::jclass* polygonClass = nullptr;
|
|
jni::jfieldID* polygonAlphaId = nullptr;
|
|
jni::jfieldID* polygonFillColorId = nullptr;
|
|
jni::jfieldID* polygonStrokeColorId = nullptr;
|
|
jni::jfieldID* polygonPointsId = nullptr;
|
|
|
|
jni::jmethodID* listToArrayId = nullptr;
|
|
|
|
jni::jclass* arrayListClass = nullptr;
|
|
jni::jmethodID* arrayListConstructorId = nullptr;
|
|
jni::jmethodID* arrayListAddId = nullptr;
|
|
|
|
jni::jclass* projectedMetersClass = nullptr;
|
|
jni::jmethodID* projectedMetersConstructorId = nullptr;
|
|
jni::jfieldID* projectedMetersNorthingId = nullptr;
|
|
jni::jfieldID* projectedMetersEastingId = nullptr;
|
|
|
|
jni::jclass* pointFClass = nullptr;
|
|
jni::jmethodID* pointFConstructorId = nullptr;
|
|
jni::jfieldID* pointFXId = nullptr;
|
|
jni::jfieldID* pointFYId = nullptr;
|
|
|
|
jni::jclass* rectFClass = nullptr;
|
|
jni::jmethodID* rectFConstructorId = nullptr;
|
|
jni::jfieldID* rectFLeftId = nullptr;
|
|
jni::jfieldID* rectFTopId = nullptr;
|
|
jni::jfieldID* rectFRightId = nullptr;
|
|
jni::jfieldID* rectFBottomId = nullptr;
|
|
|
|
// Offline declarations start
|
|
|
|
jni::jfieldID* offlineManagerClassPtrId = nullptr;
|
|
|
|
jni::jmethodID* listOnListMethodId = nullptr;
|
|
jni::jmethodID* listOnErrorMethodId = nullptr;
|
|
|
|
jni::jclass* offlineRegionClass = nullptr;
|
|
jni::jmethodID* offlineRegionConstructorId = nullptr;
|
|
jni::jfieldID* offlineRegionOfflineManagerId = nullptr;
|
|
jni::jfieldID* offlineRegionIdId = nullptr;
|
|
jni::jfieldID* offlineRegionDefinitionId = nullptr;
|
|
jni::jfieldID* offlineRegionMetadataId = nullptr;
|
|
jni::jfieldID* offlineRegionPtrId = nullptr;
|
|
|
|
jni::jclass* offlineRegionDefinitionClass = nullptr;
|
|
jni::jmethodID* offlineRegionDefinitionConstructorId = nullptr;
|
|
jni::jfieldID* offlineRegionDefinitionStyleURLId = nullptr;
|
|
jni::jfieldID* offlineRegionDefinitionBoundsId = nullptr;
|
|
jni::jfieldID* offlineRegionDefinitionMinZoomId = nullptr;
|
|
jni::jfieldID* offlineRegionDefinitionMaxZoomId = nullptr;
|
|
jni::jfieldID* offlineRegionDefinitionPixelRatioId = nullptr;
|
|
|
|
jni::jmethodID* createOnCreateMethodId = nullptr;
|
|
jni::jmethodID* createOnErrorMethodId = nullptr;
|
|
|
|
jni::jmethodID* updateMetadataOnUpdateMethodId = nullptr;
|
|
jni::jmethodID* updateMetadataOnErrorMethodId = nullptr;
|
|
|
|
jni::jmethodID* offlineRegionObserveronStatusChangedId = nullptr;
|
|
jni::jmethodID* offlineRegionObserveronErrorId = nullptr;
|
|
jni::jmethodID* offlineRegionObserveronLimitId = nullptr;
|
|
|
|
jni::jclass* offlineRegionStatusClass = nullptr;
|
|
jni::jmethodID* offlineRegionStatusConstructorId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusDownloadStateId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusCompletedResourceCountId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusCompletedResourceSizeId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusCompletedTileCountId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusCompletedTileSizeId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusRequiredResourceCountId = nullptr;
|
|
jni::jfieldID* offlineRegionStatusRequiredResourceCountIsPreciseId = nullptr;
|
|
|
|
jni::jclass* offlineRegionErrorClass = nullptr;
|
|
jni::jmethodID* offlineRegionErrorConstructorId = nullptr;
|
|
jni::jfieldID* offlineRegionErrorReasonId = nullptr;
|
|
jni::jfieldID* offlineRegionErrorMessageId = nullptr;
|
|
|
|
jni::jmethodID* offlineRegionStatusOnStatusId = nullptr;
|
|
jni::jmethodID* offlineRegionStatusOnErrorId = nullptr;
|
|
|
|
jni::jmethodID* offlineRegionDeleteOnDeleteId = nullptr;
|
|
jni::jmethodID* offlineRegionDeleteOnErrorId = nullptr;
|
|
|
|
// Offline declarations end
|
|
|
|
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<void **>(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 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 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 std::runtime_error("DetachCurrentThread() failed");
|
|
}
|
|
}
|
|
*env = nullptr;
|
|
}
|
|
|
|
std::string std_string_from_jstring(JNIEnv *env, jni::jstring* jstr) {
|
|
return jni::Make<std::string>(*env, jni::String(jstr));
|
|
}
|
|
|
|
jni::jstring* std_string_to_jstring(JNIEnv *env, std::string str) {
|
|
return jni::Make<jni::String>(*env, str).Get();
|
|
}
|
|
|
|
std::vector<std::string> std_vector_string_from_jobject(JNIEnv *env, jni::jobject* jlist) {
|
|
std::vector<std::string> vector;
|
|
|
|
jni::NullCheck(*env, jlist);
|
|
jni::jarray<jni::jobject>* jarray =
|
|
reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
|
|
|
|
jni::NullCheck(*env, jarray);
|
|
std::size_t len = jni::GetArrayLength(*env, *jarray);
|
|
|
|
for (std::size_t i = 0; i < len; i++) {
|
|
jni::jstring* jstr = reinterpret_cast<jni::jstring*>(jni::GetObjectArrayElement(*env, *jarray, i));
|
|
vector.push_back(std_string_from_jstring(env, jstr));
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
|
|
jni::jobject* std_vector_string_to_jobject(JNIEnv *env, std::vector<std::string> vector) {
|
|
jni::jobject* jlist = &jni::NewObject(*env, *arrayListClass, *arrayListConstructorId);
|
|
|
|
for (const auto& str : vector) {
|
|
jni::CallMethod<jboolean>(*env, jlist, *arrayListAddId, std_string_to_jstring(env, str));
|
|
}
|
|
|
|
return jlist;
|
|
}
|
|
|
|
jni::jarray<jlong>* std_vector_uint_to_jobject(JNIEnv *env, const std::vector<uint32_t>& vector) {
|
|
jni::jarray<jlong>& jarray = jni::NewArray<jlong>(*env, vector.size());
|
|
|
|
std::vector<jlong> v;
|
|
v.reserve(vector.size());
|
|
std::move(vector.begin(), vector.end(), std::back_inserter(v));
|
|
|
|
jni::SetArrayRegion(*env, jarray, 0, v);
|
|
|
|
return &jarray;
|
|
}
|
|
|
|
static std::vector<uint8_t> metadata_from_java(JNIEnv* env, jni::jarray<jbyte>& j) {
|
|
std::size_t length = jni::GetArrayLength(*env, j);
|
|
std::vector<uint8_t> c;
|
|
c.resize(length);
|
|
jni::GetArrayRegion(*env, j, 0, length, reinterpret_cast<jbyte*>(c.data()));
|
|
return c;
|
|
}
|
|
|
|
static jni::jarray<jbyte>* metadata_from_native(JNIEnv* env, const std::vector<uint8_t>& c) {
|
|
std::size_t length = static_cast<std::size_t>(c.size());
|
|
jni::jarray<jbyte>& j = jni::NewArray<jbyte>(*env, length);
|
|
jni::SetArrayRegion(*env, j, 0, c.size(), reinterpret_cast<const jbyte*>(c.data()));
|
|
return &j;
|
|
}
|
|
|
|
static mbgl::LatLngBounds latlngbounds_from_java(JNIEnv *env, jni::jobject* latLngBounds) {
|
|
jdouble swLat = jni::GetField<jdouble>(*env, latLngBounds, *latLngBoundsLatSouthId);
|
|
jdouble swLon = jni::GetField<jdouble>(*env, latLngBounds, *latLngBoundsLonWestId);
|
|
jdouble neLat = jni::GetField<jdouble>(*env, latLngBounds, *latLngBoundsLatNorthId);
|
|
jdouble neLon = jni::GetField<jdouble>(*env, latLngBounds, *latLngBoundsLonEastId);
|
|
return mbgl::LatLngBounds::hull({ swLat, swLon }, { neLat, neLon });
|
|
}
|
|
|
|
static jni::jobject* latlngbounds_from_native(JNIEnv *env, mbgl::LatLngBounds bounds) {
|
|
double northLatitude = bounds.north();
|
|
double eastLongitude = bounds.east();
|
|
double southLatitude = bounds.south();
|
|
double westLongitude = bounds.west();
|
|
|
|
jni::jobject* jbounds = &jni::NewObject(*env, *latLngBoundsClass, *latLngBoundsConstructorId,
|
|
northLatitude, eastLongitude, southLatitude, westLongitude);
|
|
|
|
return jbounds;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
|
|
using namespace mbgl::android;
|
|
using DebugOptions = mbgl::MapDebugOptions;
|
|
|
|
jlong nativeCreate(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* dataPath_, jni::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_);
|
|
return reinterpret_cast<jlong>(new NativeMapView(env, jni::Unwrap(obj), pixelRatio, availableProcessors, totalMemory));
|
|
}
|
|
|
|
void nativeDestroy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeDestroy");
|
|
assert(nativeMapViewPtr != 0);
|
|
delete reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
}
|
|
|
|
void nativeInitializeDisplay(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeInitializeDisplay");
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->initializeDisplay();
|
|
}
|
|
|
|
void nativeTerminateDisplay(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminateDisplay");
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->terminateDisplay();
|
|
}
|
|
|
|
void nativeInitializeContext(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeInitializeContext");
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->initializeContext();
|
|
}
|
|
|
|
void nativeTerminateContext(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminateContext");
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->terminateContext();
|
|
}
|
|
|
|
void nativeCreateSurface(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* surface) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeCreateSurface");
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->createSurface(ANativeWindow_fromSurface(env, jni::Unwrap(surface)));
|
|
}
|
|
|
|
void nativeDestroySurface(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "nativeDestroySurface");
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->destroySurface();
|
|
}
|
|
|
|
void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->invalidate();
|
|
}
|
|
|
|
void nativeRender(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->render();
|
|
}
|
|
|
|
void nativeViewResize(JNIEnv *env, jni::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<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->resizeView(width, height);
|
|
}
|
|
|
|
void nativeFramebufferResize(JNIEnv *env, jni::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<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->resizeFramebuffer(fbWidth, fbHeight);
|
|
}
|
|
|
|
void nativeRemoveClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().removeClass(std_string_from_jstring(env, clazz));
|
|
}
|
|
|
|
jboolean nativeHasClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().hasClass(std_string_from_jstring(env, clazz));
|
|
}
|
|
|
|
void nativeAddClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().addClass(std_string_from_jstring(env, clazz));
|
|
}
|
|
|
|
void nativeSetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* classes) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setClasses(std_vector_string_from_jobject(env, classes));
|
|
}
|
|
|
|
jni::jobject* nativeGetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return std_vector_string_to_jobject(env, nativeMapView->getMap().getClasses());
|
|
}
|
|
|
|
void nativeSetAPIBaseURL(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getFileSource().setAPIBaseURL(std_string_from_jstring(env, url));
|
|
}
|
|
|
|
void nativeSetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url));
|
|
}
|
|
|
|
void nativeSetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* newStyleJson) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson));
|
|
}
|
|
|
|
jni::jstring* nativeGetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return std_string_to_jstring(env, nativeMapView->getMap().getStyleJSON());
|
|
}
|
|
|
|
void nativeSetAccessToken(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* accessToken) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getFileSource().setAccessToken(std_string_from_jstring(env, accessToken));
|
|
}
|
|
|
|
jni::jstring* nativeGetAccessToken(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return std_string_to_jstring(env, nativeMapView->getFileSource().getAccessToken());
|
|
}
|
|
|
|
void nativeCancelTransitions(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().cancelTransitions();
|
|
}
|
|
|
|
void nativeSetGestureInProgress(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean inProgress) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setGestureInProgress(inProgress);
|
|
}
|
|
|
|
void nativeMoveBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble dx, jdouble dy,
|
|
jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ScreenCoordinate center(dx, dy);
|
|
nativeMapView->getMap().moveBy(center, mbgl::Milliseconds(duration));
|
|
}
|
|
|
|
void nativeSetLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude, jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), nativeMapView->getInsets(), mbgl::Duration(duration));
|
|
}
|
|
|
|
jni::jobject* nativeGetLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(nativeMapView->getInsets());
|
|
return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude);
|
|
}
|
|
|
|
jdoubleArray nativeGetCameraValues(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(nativeMapView->getInsets());
|
|
jdoubleArray output = env->NewDoubleArray(5);
|
|
jsize start = 0;
|
|
jsize leng = 5;
|
|
jdouble buf[5];
|
|
buf[0] = latLng.latitude;
|
|
buf[1] = latLng.longitude;
|
|
buf[2] = -(nativeMapView->getMap().getBearing()-360);
|
|
buf[3] = nativeMapView->getMap().getPitch();
|
|
buf[4] = nativeMapView->getMap().getZoom();
|
|
env->SetDoubleArrayRegion(output, start, leng, buf);
|
|
|
|
if (output == nullptr) {
|
|
env->ExceptionDescribe();
|
|
return nullptr;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
void nativeResetPosition(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().resetPosition();
|
|
}
|
|
|
|
jdouble nativeGetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getPitch();
|
|
}
|
|
|
|
void nativeSetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble pitch, jlong milliseconds) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::Duration duration((mbgl::Milliseconds(milliseconds)));
|
|
nativeMapView->getMap().setPitch(pitch, duration);
|
|
}
|
|
|
|
void nativeScaleBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble ds, jdouble cx,
|
|
jdouble cy, jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ScreenCoordinate center(cx, cy);
|
|
nativeMapView->getMap().scaleBy(ds, center, mbgl::Milliseconds(duration));
|
|
}
|
|
|
|
void nativeSetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble scale,
|
|
jdouble cx, jdouble cy, jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ScreenCoordinate center(cx, cy);
|
|
nativeMapView->getMap().setScale(scale, center, mbgl::Milliseconds(duration));
|
|
}
|
|
|
|
jdouble nativeGetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getScale();
|
|
}
|
|
|
|
void nativeSetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom, jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setZoom(zoom, mbgl::Milliseconds(duration));
|
|
}
|
|
|
|
jdouble nativeGetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getZoom();
|
|
}
|
|
|
|
void nativeResetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().resetZoom();
|
|
}
|
|
|
|
void nativeSetMinZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setMinZoom(zoom);
|
|
}
|
|
|
|
jdouble nativeGetMinZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getMinZoom();
|
|
}
|
|
|
|
void nativeSetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().setMaxZoom(zoom);
|
|
}
|
|
|
|
jdouble nativeGetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getMaxZoom();
|
|
}
|
|
|
|
void nativeRotateBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble sx,
|
|
jdouble sy, jdouble ex, jdouble ey, jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ScreenCoordinate first(sx, sy);
|
|
mbgl::ScreenCoordinate second(ex, ey);
|
|
nativeMapView->getMap().rotateBy(first, second, mbgl::Milliseconds(duration));
|
|
}
|
|
|
|
void nativeSetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees,
|
|
jlong milliseconds) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::Duration duration((mbgl::Milliseconds(milliseconds)));
|
|
nativeMapView->getMap().setBearing(degrees, duration);
|
|
}
|
|
|
|
void nativeSetBearingXY(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees,
|
|
jdouble cx, jdouble cy) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ScreenCoordinate center(cx, cy);
|
|
nativeMapView->getMap().setBearing(degrees, center);
|
|
}
|
|
|
|
jdouble nativeGetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getBearing();
|
|
}
|
|
|
|
void nativeResetNorth(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().resetNorth();
|
|
}
|
|
|
|
void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong markerId, jdouble lat, jdouble lon, jni::jstring* jid) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
if (markerId == -1) {
|
|
return;
|
|
}
|
|
std::string iconId = std_string_from_jstring(env, jid);
|
|
// Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
|
|
nativeMapView->getMap().updateAnnotation(markerId, mbgl::SymbolAnnotation { mbgl::Point<double>(lon, lat), iconId });
|
|
}
|
|
|
|
jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
NullCheck(*env, jarray);
|
|
std::size_t len = jni::GetArrayLength(*env, *jarray);
|
|
|
|
mbgl::AnnotationIDs ids;
|
|
ids.reserve(len);
|
|
|
|
for (std::size_t i = 0; i < len; i++) {
|
|
jni::jobject* marker = jni::GetObjectArrayElement(*env, *jarray, i);
|
|
jni::jobject* position = jni::GetField<jni::jobject*>(*env, marker, *markerPositionId);
|
|
jni::jobject* icon = jni::GetField<jni::jobject*>(*env, marker, *markerIconId);
|
|
jni::jstring* jid = reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, icon, *iconIdId));
|
|
|
|
jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
|
|
jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
|
|
|
|
ids.push_back(nativeMapView->getMap().addAnnotation(mbgl::SymbolAnnotation {
|
|
mbgl::Point<double>(longitude, latitude),
|
|
std_string_from_jstring(env, jid)
|
|
}));
|
|
|
|
jni::DeleteLocalRef(*env, position);
|
|
jni::DeleteLocalRef(*env, jid);
|
|
jni::DeleteLocalRef(*env, icon);
|
|
jni::DeleteLocalRef(*env, marker);
|
|
}
|
|
|
|
return std_vector_uint_to_jobject(env, ids);
|
|
}
|
|
|
|
static mbgl::Color toColor(jint color) {
|
|
float r = (color >> 16) & 0xFF;
|
|
float g = (color >> 8) & 0xFF;
|
|
float b = (color) & 0xFF;
|
|
float a = (color >> 24) & 0xFF;
|
|
return { r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f };
|
|
}
|
|
|
|
template <class Geometry>
|
|
Geometry toGeometry(JNIEnv *env, jni::jobject* jlist) {
|
|
NullCheck(*env, jlist);
|
|
jni::jarray<jni::jobject>* jarray =
|
|
reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
|
|
NullCheck(*env, jarray);
|
|
|
|
std::size_t size = jni::GetArrayLength(*env, *jarray);
|
|
|
|
Geometry geometry;
|
|
geometry.reserve(size);
|
|
|
|
for (std::size_t i = 0; i < size; i++) {
|
|
jni::jobject* latLng = reinterpret_cast<jni::jobject*>(jni::GetObjectArrayElement(*env, *jarray, i));
|
|
NullCheck(*env, latLng);
|
|
|
|
geometry.push_back(mbgl::Point<double>(
|
|
jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId),
|
|
jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId)));
|
|
|
|
jni::DeleteLocalRef(*env, latLng);
|
|
}
|
|
|
|
jni::DeleteLocalRef(*env, jarray);
|
|
jni::DeleteLocalRef(*env, jlist);
|
|
|
|
return geometry;
|
|
}
|
|
|
|
jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
NullCheck(*env, jarray);
|
|
std::size_t len = jni::GetArrayLength(*env, *jarray);
|
|
|
|
mbgl::AnnotationIDs ids;
|
|
ids.reserve(len);
|
|
|
|
for (std::size_t i = 0; i < len; i++) {
|
|
jni::jobject* polyline = jni::GetObjectArrayElement(*env, *jarray, i);
|
|
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
|
|
|
|
mbgl::LineAnnotation annotation { toGeometry<mbgl::LineString<double>>(env, points) };
|
|
annotation.opacity = { jni::GetField<jfloat>(*env, polyline, *polylineAlphaId) };
|
|
annotation.color = { toColor(jni::GetField<jint>(*env, polyline, *polylineColorId)) };
|
|
annotation.width = { jni::GetField<jfloat>(*env, polyline, *polylineWidthId) };
|
|
ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
|
|
|
|
jni::DeleteLocalRef(*env, polyline);
|
|
}
|
|
|
|
return std_vector_uint_to_jobject(env, ids);
|
|
}
|
|
|
|
jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
NullCheck(*env, jarray);
|
|
std::size_t len = jni::GetArrayLength(*env, *jarray);
|
|
|
|
mbgl::AnnotationIDs ids;
|
|
ids.reserve(len);
|
|
|
|
for (std::size_t i = 0; i < len; i++) {
|
|
jni::jobject* polygon = jni::GetObjectArrayElement(*env, *jarray, i);
|
|
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
|
|
|
|
mbgl::FillAnnotation annotation { mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) } };
|
|
annotation.opacity = { jni::GetField<jfloat>(*env, polygon, *polygonAlphaId) };
|
|
annotation.outlineColor = { toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId)) };
|
|
annotation.color = { toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId)) };
|
|
ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
|
|
|
|
jni::DeleteLocalRef(*env, polygon);
|
|
}
|
|
|
|
return std_vector_uint_to_jobject(env, ids);
|
|
}
|
|
|
|
void nativeUpdatePolygon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong polygonId, jni::jobject* polygon) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
|
|
|
|
mbgl::FillAnnotation annotation { mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) } };
|
|
annotation.opacity = { jni::GetField<jfloat>(*env, polygon, *polygonAlphaId) };
|
|
annotation.outlineColor = { toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId)) };
|
|
annotation.color = { toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId)) };
|
|
nativeMapView->getMap().updateAnnotation(polygonId, annotation);
|
|
}
|
|
|
|
void nativeUpdatePolyline(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong polylineId, jni::jobject* polyline) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
|
|
|
|
mbgl::LineAnnotation annotation { toGeometry<mbgl::LineString<double>>(env, points) };
|
|
annotation.opacity = { jni::GetField<jfloat>(*env, polyline, *polylineAlphaId) };
|
|
annotation.color = { toColor(jni::GetField<jint>(*env, polyline, *polylineColorId)) };
|
|
annotation.width = { jni::GetField<jfloat>(*env, polyline, *polylineWidthId) };
|
|
nativeMapView->getMap().updateAnnotation(polylineId, annotation);
|
|
}
|
|
|
|
void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jlong>* jarray) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
NullCheck(*env, jarray);
|
|
std::size_t len = jni::GetArrayLength(*env, *jarray);
|
|
auto elements = jni::GetArrayElements(*env, *jarray);
|
|
jlong* jids = std::get<0>(elements).get();
|
|
|
|
for (std::size_t i = 0; i < len; i++) {
|
|
if(jids[i] == -1L)
|
|
continue;
|
|
nativeMapView->getMap().removeAnnotation(jids[i]);
|
|
}
|
|
}
|
|
|
|
jni::jarray<jlong>* nativeQueryPointAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* rect) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
// Conversion
|
|
jfloat left = jni::GetField<jfloat>(*env, rect, *rectFLeftId);
|
|
jfloat right = jni::GetField<jfloat>(*env, rect, *rectFRightId);
|
|
jfloat top = jni::GetField<jfloat>(*env, rect, *rectFTopId);
|
|
jfloat bottom = jni::GetField<jfloat>(*env, rect, *rectFBottomId);
|
|
mbgl::ScreenBox box = {
|
|
{ left, top },
|
|
{ right, bottom },
|
|
};
|
|
|
|
// Assume only points for now
|
|
mbgl::AnnotationIDs ids = nativeMapView->getMap().queryPointAnnotations(box);
|
|
|
|
return std_vector_uint_to_jobject(env, ids);
|
|
}
|
|
|
|
void nativeAddAnnotationIcon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
|
|
jni::jstring* symbol, jint width, jint height, jfloat scale, jni::jarray<jbyte>* jpixels) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
const std::string symbolName = std_string_from_jstring(env, symbol);
|
|
|
|
NullCheck(*env, jpixels);
|
|
std::size_t size = jni::GetArrayLength(*env, *jpixels);
|
|
mbgl::PremultipliedImage premultipliedImage(width, height);
|
|
|
|
if (premultipliedImage.size() != uint32_t(size)) {
|
|
throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
|
|
}
|
|
|
|
jni::GetArrayRegion(*env, *jpixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
|
|
|
|
auto iconImage = std::make_shared<mbgl::SpriteImage>(
|
|
std::move(premultipliedImage),
|
|
float(scale));
|
|
|
|
nativeMapView->getMap().addAnnotationIcon(symbolName, iconImage);
|
|
}
|
|
|
|
void nativeSetVisibleCoordinateBounds(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
|
|
jni::jarray<jni::jobject>* coordinates, jni::jobject* padding, jdouble direction, jlong duration) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
jfloat left = jni::GetField<jfloat>(*env, padding, *rectFLeftId);
|
|
jfloat right = jni::GetField<jfloat>(*env, padding, *rectFRightId);
|
|
jfloat top = jni::GetField<jfloat>(*env, padding, *rectFTopId);
|
|
jfloat bottom = jni::GetField<jfloat>(*env, padding, *rectFBottomId);
|
|
|
|
NullCheck(*env, coordinates);
|
|
std::size_t count = jni::GetArrayLength(*env, *coordinates);
|
|
|
|
mbgl::EdgeInsets mbglInsets = {top, left, bottom, right};
|
|
std::vector<mbgl::LatLng> latLngs;
|
|
latLngs.reserve(count);
|
|
|
|
for (std::size_t i = 0; i < count; i++) {
|
|
jni::jobject* latLng = jni::GetObjectArrayElement(*env, *coordinates, i);
|
|
jdouble latitude = jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId);
|
|
jdouble longitude = jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId);
|
|
latLngs.push_back(mbgl::LatLng(latitude, longitude));
|
|
}
|
|
|
|
mbgl::CameraOptions cameraOptions = nativeMapView->getMap().cameraForLatLngs(latLngs, mbglInsets);
|
|
if (direction >= 0) {
|
|
// convert from degrees to radians
|
|
cameraOptions.angle = (-direction * M_PI) / 180;
|
|
}
|
|
mbgl::AnimationOptions animationOptions;
|
|
if (duration > 0) {
|
|
animationOptions.duration.emplace(mbgl::Milliseconds(duration));
|
|
// equivalent to kCAMediaTimingFunctionDefault in iOS
|
|
animationOptions.easing.emplace(mbgl::util::UnitBezier { 0.25, 0.1, 0.25, 0.1 });
|
|
}
|
|
|
|
nativeMapView->getMap().easeTo(cameraOptions, animationOptions);
|
|
}
|
|
|
|
jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForPoint(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jfloat x, jni::jfloat y, jni::jarray<jni::jobject>* layerIds) {
|
|
using namespace mbgl::android::conversion;
|
|
using namespace mapbox::geometry;
|
|
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
mbgl::optional<std::vector<std::string>> layers;
|
|
if (layerIds != nullptr && jni::GetArrayLength(*env, *layerIds) > 0) {
|
|
layers = toVector(*env, *layerIds);
|
|
}
|
|
point<double> point = {x, y};
|
|
|
|
return *convert<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>>(*env, nativeMapView->getMap().queryRenderedFeatures(point, layers));
|
|
}
|
|
|
|
jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForBox(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::jarray<jni::jobject>* layerIds) {
|
|
using namespace mbgl::android::conversion;
|
|
using namespace mapbox::geometry;
|
|
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
mbgl::optional<std::vector<std::string>> layers;
|
|
if (layerIds != nullptr && jni::GetArrayLength(*env, *layerIds) > 0) {
|
|
layers = toVector(*env, *layerIds);
|
|
}
|
|
box<double> box = { point<double>{ left, top}, point<double>{ right, bottom } };
|
|
|
|
return *convert<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>>(*env, nativeMapView->getMap().queryRenderedFeatures(box, layers));
|
|
}
|
|
|
|
void nativeOnLowMemory(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().onLowMemory();
|
|
}
|
|
|
|
void nativeSetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean debug) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
DebugOptions debugOptions = debug ? DebugOptions::TileBorders | DebugOptions::ParseStatus | DebugOptions::Collision
|
|
: DebugOptions::NoDebug;
|
|
nativeMapView->getMap().setDebug(debugOptions);
|
|
nativeMapView->enableFps(debug);
|
|
}
|
|
|
|
void nativeToggleDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().cycleDebugOptions();
|
|
nativeMapView->enableFps(nativeMapView->getMap().getDebug() != DebugOptions::NoDebug);
|
|
}
|
|
|
|
jboolean nativeGetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getDebug() != DebugOptions::NoDebug;
|
|
}
|
|
|
|
jboolean nativeIsFullyLoaded(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().isFullyLoaded();
|
|
}
|
|
|
|
void nativeSetReachability(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean status) {
|
|
assert(nativeMapViewPtr != 0);
|
|
if (status) {
|
|
mbgl::NetworkStatus::Reachable();
|
|
}
|
|
}
|
|
|
|
jdouble nativeGetMetersPerPixelAtLatitude(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble lat, jdouble zoom) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getMetersPerPixelAtLatitude(lat, zoom);
|
|
}
|
|
|
|
jni::jobject* nativeProjectedMetersForLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ProjectedMeters projectedMeters = nativeMapView->getMap().projectedMetersForLatLng(mbgl::LatLng(latitude, longitude));
|
|
return &jni::NewObject(*env, *projectedMetersClass, *projectedMetersConstructorId, projectedMeters.northing, projectedMeters.easting);
|
|
}
|
|
|
|
jni::jobject* nativeLatLngForProjectedMeters(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble northing, jdouble easting) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::LatLng latLng = nativeMapView->getMap().latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting));
|
|
return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude);
|
|
}
|
|
|
|
jni::jobject* nativePixelForLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::ScreenCoordinate pixel = nativeMapView->getMap().pixelForLatLng(mbgl::LatLng(latitude, longitude));
|
|
return &jni::NewObject(*env, *pointFClass, *pointFConstructorId, static_cast<jfloat>(pixel.x), static_cast<jfloat>(pixel.y));
|
|
}
|
|
|
|
jni::jobject* nativeLatLngForPixel(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jfloat x, jfloat y) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::ScreenCoordinate(x, y));
|
|
return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude);
|
|
}
|
|
|
|
jdouble nativeGetTopOffsetPixelsForAnnotationSymbol(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* symbolName) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
return nativeMapView->getMap().getTopOffsetPixelsForAnnotationIcon(std_string_from_jstring(env, symbolName));
|
|
}
|
|
|
|
void nativeJumpTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jdouble latitude, jdouble longitude, jdouble pitch, jdouble zoom) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
mbgl::CameraOptions options;
|
|
if (angle != -1) {
|
|
options.angle = angle * M_PI / 180;
|
|
}
|
|
options.center = mbgl::LatLng(latitude, longitude);
|
|
options.padding = nativeMapView->getInsets();
|
|
if (pitch != -1) {
|
|
options.pitch = pitch * M_PI / 180;
|
|
}
|
|
if (zoom != -1) {
|
|
options.zoom = zoom;
|
|
}
|
|
|
|
nativeMapView->getMap().jumpTo(options);
|
|
}
|
|
|
|
void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jdouble latitude, jdouble longitude, jlong duration, jdouble pitch, jdouble zoom, jboolean easing) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
mbgl::CameraOptions cameraOptions;
|
|
if (angle != -1) {
|
|
cameraOptions.angle = angle * M_PI / 180;
|
|
}
|
|
cameraOptions.center = mbgl::LatLng(latitude, longitude);
|
|
cameraOptions.padding = nativeMapView->getInsets();
|
|
if (pitch != -1) {
|
|
cameraOptions.pitch = pitch * M_PI / 180;
|
|
}
|
|
if (zoom != -1) {
|
|
cameraOptions.zoom = zoom;
|
|
}
|
|
mbgl::AnimationOptions animationOptions;
|
|
animationOptions.duration.emplace(mbgl::Duration(duration));
|
|
|
|
if (!easing) {
|
|
// add a linear interpolator instead of easing
|
|
animationOptions.easing.emplace(mbgl::util::UnitBezier { 0, 0, 1, 1 });
|
|
}
|
|
|
|
nativeMapView->getMap().easeTo(cameraOptions, animationOptions);
|
|
}
|
|
|
|
void nativeSetContentPadding(JNIEnv *env, jni::jobject* obj,long nativeMapViewPtr, double top, double left, double bottom, double right) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->setInsets({top, left, bottom, right});
|
|
}
|
|
|
|
void nativeFlyTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jdouble latitude, jdouble longitude, jlong duration, jdouble pitch, jdouble zoom) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
mbgl::CameraOptions cameraOptions;
|
|
if (angle != -1) {
|
|
cameraOptions.angle = angle * M_PI / 180 ;
|
|
}
|
|
cameraOptions.center = mbgl::LatLng(latitude, longitude);
|
|
cameraOptions.padding = nativeMapView->getInsets();
|
|
if (pitch != -1) {
|
|
cameraOptions.pitch = pitch * M_PI / 180;
|
|
}
|
|
if (zoom != -1) {
|
|
cameraOptions.zoom = zoom;
|
|
}
|
|
mbgl::AnimationOptions animationOptions;
|
|
animationOptions.duration.emplace(mbgl::Duration(duration));
|
|
|
|
nativeMapView->getMap().flyTo(cameraOptions, animationOptions);
|
|
}
|
|
|
|
jni::jobject* nativeGetLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* layerId) {
|
|
assert(env);
|
|
assert(nativeMapViewPtr != 0);
|
|
|
|
//Get the native map peer
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
//Find the layer
|
|
mbgl::style::Layer* coreLayer = nativeMapView->getMap().getLayer(std_string_from_jstring(env, layerId));
|
|
if (!coreLayer) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "No layer found");
|
|
return jni::Object<Layer>();
|
|
}
|
|
|
|
//Create and return the layer's native peer
|
|
return createJavaLayerPeer(*env, nativeMapView->getMap(), *coreLayer);
|
|
}
|
|
|
|
void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong nativeLayerPtr, jni::jstring* before) {
|
|
assert(nativeMapViewPtr != 0);
|
|
assert(nativeLayerPtr != 0);
|
|
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr);
|
|
|
|
nativeMapView->getMap().addLayer(
|
|
layer->releaseCoreLayer(),
|
|
before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>()
|
|
);
|
|
}
|
|
|
|
void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
try {
|
|
nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id));
|
|
} catch (const std::runtime_error& error) {
|
|
jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
|
|
}
|
|
}
|
|
|
|
jni::jobject* nativeGetSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jstring* sourceId) {
|
|
assert(env);
|
|
assert(nativeMapViewPtr != 0);
|
|
|
|
//Get the native map peer
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
//Find the source
|
|
mbgl::style::Source* coreSource = nativeMapView->getMap().getSource(std_string_from_jstring(env, sourceId));
|
|
if (!coreSource) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "No source found");
|
|
return jni::Object<Source>();
|
|
}
|
|
|
|
//Create and return the source's native peer
|
|
return createJavaSourcePeer(*env, nativeMapView->getMap(), *coreSource);
|
|
}
|
|
|
|
void nativeAddSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jlong nativeSourcePtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
assert(nativeSourcePtr != 0);
|
|
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
Source *source = reinterpret_cast<Source *>(nativeSourcePtr);
|
|
|
|
nativeMapView->getMap().addSource(source->releaseCoreSource());
|
|
}
|
|
|
|
void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
try {
|
|
nativeMapView->getMap().removeSource(std_string_from_jstring(env, id));
|
|
} catch (const std::runtime_error& error) {
|
|
jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
|
|
}
|
|
}
|
|
|
|
void nativeAddImage(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* name, jni::jint width, jni::jint height, jni::jfloat pixelRatio, jni::jarray<jbyte>* data) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
|
|
// Create Pre-multiplied image from byte[]
|
|
NullCheck(*env, data);
|
|
std::size_t size = jni::GetArrayLength(*env, *data);
|
|
mbgl::PremultipliedImage premultipliedImage(width, height);
|
|
|
|
if (premultipliedImage.size() != uint32_t(size)) {
|
|
throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
|
|
}
|
|
|
|
jni::GetArrayRegion(*env, *data, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
|
|
|
|
//Wrap in a SpriteImage with the correct pixel ratio
|
|
auto spriteImage = std::make_unique<mbgl::SpriteImage>(std::move(premultipliedImage), float(pixelRatio));
|
|
|
|
nativeMapView->getMap().addImage(std_string_from_jstring(env, name), std::move(spriteImage));
|
|
}
|
|
|
|
void nativeRemoveImage(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* name) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->getMap().removeImage(std_string_from_jstring(env, name));
|
|
}
|
|
|
|
void nativeScheduleTakeSnapshot(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
|
assert(nativeMapViewPtr != 0);
|
|
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
|
nativeMapView->scheduleTakeSnapshot();
|
|
}
|
|
|
|
// Offline calls begin
|
|
|
|
jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* assetRoot_, jlong maximumCacheSize) {
|
|
std::string cachePath = std_string_from_jstring(env, cachePath_);
|
|
std::string assetRoot = std_string_from_jstring(env, assetRoot_);
|
|
mbgl::DefaultFileSource *defaultFileSource = new mbgl::DefaultFileSource(cachePath, assetRoot, maximumCacheSize);
|
|
jlong defaultFileSourcePtr = reinterpret_cast<jlong>(defaultFileSource);
|
|
return defaultFileSourcePtr;
|
|
}
|
|
|
|
void setAccessToken(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jstring* accessToken_) {
|
|
assert(defaultFileSourcePtr != 0);
|
|
std::string accessToken = std_string_from_jstring(env, accessToken_);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
defaultFileSource->setAccessToken(accessToken);
|
|
}
|
|
|
|
jni::jstring* getAccessToken(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr) {
|
|
assert(defaultFileSourcePtr != 0);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
std::string accessToken = defaultFileSource->getAccessToken();
|
|
return std_string_to_jstring(env, accessToken);
|
|
}
|
|
|
|
void listOfflineRegions(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jobject* listCallback) {
|
|
// Checks
|
|
assert(defaultFileSourcePtr != 0);
|
|
NullCheck(*env, listCallback);
|
|
|
|
// Makes sure the objects don't get GC'ed
|
|
obj = jni::NewGlobalRef(*env, obj).release();
|
|
listCallback = jni::NewGlobalRef(*env, listCallback).release();
|
|
|
|
// Launch listCallback
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
defaultFileSource->listOfflineRegions([obj, defaultFileSourcePtr, listCallback](std::exception_ptr error, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) mutable {
|
|
|
|
// Reattach, the callback comes from a different thread
|
|
JNIEnv *env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
if (renderDetach) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "Attached.");
|
|
}
|
|
|
|
if (error) {
|
|
std::string message = mbgl::util::toString(error);
|
|
jni::CallMethod<void>(*env2, listCallback, *listOnErrorMethodId, std_string_to_jstring(env2, message));
|
|
} else if (regions) {
|
|
// Build jni::jarray<jni::jobject>*
|
|
std::size_t index = 0;
|
|
jni::jarray<jni::jobject>* jregions = &jni::NewObjectArray(*env2, regions->size(), *offlineRegionClass, NULL);
|
|
for (auto& region : *regions) {
|
|
// Create a new local reference frame (capacity 2 for the NewObject allocations below)
|
|
// to avoid a local reference table overflow (#5629)
|
|
jni::UniqueLocalFrame frame = jni::PushLocalFrame(*env2, 2);
|
|
|
|
// Build the Region object
|
|
jni::jobject* jregion = &jni::NewObject(*env2, *offlineRegionClass, *offlineRegionConstructorId);
|
|
jni::SetField<jni::jobject*>(*env2, jregion, *offlineRegionOfflineManagerId, obj);
|
|
jni::SetField<jlong>(*env2, jregion, *offlineRegionIdId, region.getID());
|
|
|
|
// Definition object
|
|
mbgl::OfflineTilePyramidRegionDefinition definition = region.getDefinition();
|
|
jni::jobject* jdefinition = &jni::NewObject(*env2, *offlineRegionDefinitionClass, *offlineRegionDefinitionConstructorId);
|
|
jni::SetField<jni::jobject*>(*env2, jdefinition, *offlineRegionDefinitionStyleURLId, std_string_to_jstring(env2, definition.styleURL));
|
|
jni::SetField<jni::jobject*>(*env2, jdefinition, *offlineRegionDefinitionBoundsId, latlngbounds_from_native(env2, definition.bounds));
|
|
jni::SetField<jdouble>(*env2, jdefinition, *offlineRegionDefinitionMinZoomId, definition.minZoom);
|
|
jni::SetField<jdouble>(*env2, jdefinition, *offlineRegionDefinitionMaxZoomId, definition.maxZoom);
|
|
jni::SetField<jfloat>(*env2, jdefinition, *offlineRegionDefinitionPixelRatioId, definition.pixelRatio);
|
|
jni::SetField<jni::jobject*>(*env2, jregion, *offlineRegionDefinitionId, jdefinition);
|
|
|
|
// Metadata object
|
|
jni::jarray<jbyte>* metadata = metadata_from_native(env2, region.getMetadata());
|
|
jni::SetField<jni::jobject*>(*env2, jregion, *offlineRegionMetadataId, metadata);
|
|
|
|
// Moves the region on the stack into a heap-allocated one
|
|
jni::SetField<jlong>(*env2, jregion, *offlineRegionPtrId,
|
|
reinterpret_cast<jlong>(new mbgl::OfflineRegion(std::move(region))));
|
|
|
|
jni::SetObjectArrayElement(*env2, *jregions, index, jregion);
|
|
index++;
|
|
}
|
|
|
|
// Trigger callback
|
|
jni::CallMethod<void>(*env2, listCallback, *listOnListMethodId, jregions);
|
|
}
|
|
|
|
// Delete global refs and detach when we're done
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(obj));
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(listCallback));
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
});
|
|
}
|
|
|
|
void createOfflineRegion(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jobject* definition_, jni::jarray<jbyte>* metadata_, jni::jobject* createCallback) {
|
|
// Checks
|
|
assert(defaultFileSourcePtr != 0);
|
|
NullCheck(*env, createCallback);
|
|
|
|
// Definition fields
|
|
jni::jstring* jStyleURL = reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, definition_, *offlineRegionDefinitionStyleURLId));
|
|
std::string styleURL = std_string_from_jstring(env, jStyleURL);
|
|
jni::jobject* jBounds = jni::GetField<jni::jobject*>(*env, definition_, *offlineRegionDefinitionBoundsId);
|
|
jdouble jMinZoom = jni::GetField<jdouble>(*env, definition_, *offlineRegionDefinitionMinZoomId);
|
|
jdouble jMaxZoom = jni::GetField<jdouble>(*env, definition_, *offlineRegionDefinitionMaxZoomId);
|
|
jfloat jPixelRatio = jni::GetField<jfloat>(*env, definition_, *offlineRegionDefinitionPixelRatioId);
|
|
|
|
// Convert bounds fields to native
|
|
mbgl::LatLngBounds bounds = latlngbounds_from_java(env, jBounds);
|
|
|
|
// Definition
|
|
mbgl::OfflineTilePyramidRegionDefinition definition(styleURL, bounds, jMinZoom, jMaxZoom, jPixelRatio);
|
|
|
|
// Metadata
|
|
mbgl::OfflineRegionMetadata metadata;
|
|
if (metadata_ != nullptr) {
|
|
metadata = metadata_from_java(env, *metadata_);
|
|
}
|
|
|
|
// Makes sure the objects don't get GC'ed
|
|
obj = jni::NewGlobalRef(*env, obj).release();
|
|
createCallback = jni::NewGlobalRef(*env, createCallback).release();
|
|
|
|
// Launch createCallback
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
defaultFileSource->createOfflineRegion(definition, metadata, [obj, defaultFileSourcePtr, createCallback] (std::exception_ptr error, mbgl::optional<mbgl::OfflineRegion> region) mutable {
|
|
|
|
// Reattach, the callback comes from a different thread
|
|
JNIEnv *env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
if (renderDetach) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "Attached.");
|
|
}
|
|
|
|
if (error) {
|
|
std::string message = mbgl::util::toString(error);
|
|
jni::CallMethod<void>(*env2, createCallback, *createOnErrorMethodId, std_string_to_jstring(env2, message));
|
|
} else if (region) {
|
|
// Build the Region object
|
|
jni::jobject* jregion = &jni::NewObject(*env2, *offlineRegionClass, *offlineRegionConstructorId);
|
|
jni::SetField<jni::jobject*>(*env2, jregion, *offlineRegionOfflineManagerId, obj);
|
|
jni::SetField<jlong>(*env2, jregion, *offlineRegionIdId, region->getID());
|
|
|
|
// Metadata object
|
|
jni::jarray<jbyte>* jmetadata = metadata_from_native(env2, region->getMetadata());
|
|
jni::SetField<jni::jobject*>(*env2, jregion, *offlineRegionMetadataId, jmetadata);
|
|
|
|
// Moves the region on the stack into a heap-allocated one
|
|
jni::SetField<jlong>(*env2, jregion, *offlineRegionPtrId,
|
|
reinterpret_cast<jlong>(new mbgl::OfflineRegion(std::move(*region))));
|
|
|
|
// Invoke Java callback
|
|
jni::CallMethod<void>(*env2, createCallback, *createOnCreateMethodId, jregion);
|
|
}
|
|
|
|
// Delete global refs and detach when we're done
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(obj));
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(createCallback));
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
});
|
|
}
|
|
|
|
void setOfflineMapboxTileCountLimit(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jlong limit) {
|
|
// Checks
|
|
assert(defaultFileSourcePtr != 0);
|
|
assert(limit > 0);
|
|
|
|
// Set limit
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
defaultFileSource->setOfflineMapboxTileCountLimit(limit);
|
|
}
|
|
|
|
mbgl::OfflineRegion* getOfflineRegionPeer(JNIEnv *env, jni::jobject* offlineRegion_) {
|
|
jlong offlineRegionPtr = jni::GetField<jlong>(*env, offlineRegion_, *offlineRegionPtrId);
|
|
if (!offlineRegionPtr) {
|
|
jni::ThrowNew(*env, jni::FindClass(*env, "java/lang/IllegalStateException"),
|
|
"Use of OfflineRegion after OfflineRegion.delete");
|
|
}
|
|
return reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr);
|
|
}
|
|
|
|
void destroyOfflineRegion(JNIEnv *env, jni::jobject* offlineRegion_) {
|
|
// Offline region
|
|
jlong offlineRegionPtr = jni::GetField<jlong>(*env, offlineRegion_, *offlineRegionPtrId);
|
|
if (!offlineRegionPtr) {
|
|
return; // Already deleted
|
|
}
|
|
|
|
// File source
|
|
jni::jobject* jmanager = jni::GetField<jni::jobject*>(*env, offlineRegion_, *offlineRegionOfflineManagerId);
|
|
jlong defaultFileSourcePtr = jni::GetField<jlong>(*env, jmanager, *offlineManagerClassPtrId);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
|
|
// Release the observer and delete the region
|
|
mbgl::OfflineRegion *offlineRegion = reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr);
|
|
defaultFileSource->setOfflineRegionObserver(*offlineRegion, nullptr);
|
|
jni::SetField<jlong>(*env, offlineRegion_, *offlineRegionPtrId, 0);
|
|
delete offlineRegion;
|
|
}
|
|
|
|
void setOfflineRegionObserver(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject* observerCallback) {
|
|
// Offline region
|
|
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
|
|
|
|
// File source
|
|
jni::jobject* jmanager = jni::GetField<jni::jobject*>(*env, offlineRegion_, *offlineRegionOfflineManagerId);
|
|
jlong defaultFileSourcePtr = jni::GetField<jlong>(*env, jmanager, *offlineManagerClassPtrId);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
|
|
// Define the observer
|
|
class Observer : public mbgl::OfflineRegionObserver {
|
|
public:
|
|
Observer(jni::UniqueGlobalRef<jni::jobject>&& observerCallback_)
|
|
: observerCallback(std::move(observerCallback_)) {
|
|
}
|
|
|
|
~Observer() override {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "~Observer()");
|
|
// Env
|
|
JNIEnv* env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
jni::DeleteGlobalRef(*env2, std::move(observerCallback));
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
}
|
|
|
|
void statusChanged(mbgl::OfflineRegionStatus status) override {
|
|
// Env
|
|
JNIEnv* env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
|
|
// Conver to jint
|
|
jint downloadState;
|
|
switch(status.downloadState) {
|
|
case mbgl::OfflineRegionDownloadState::Inactive:
|
|
downloadState = 0;
|
|
break;
|
|
case mbgl::OfflineRegionDownloadState::Active:
|
|
downloadState = 1;
|
|
break;
|
|
}
|
|
|
|
// Create a new local reference frame (capacity 1 for the NewObject allocation below)
|
|
// to avoid a local reference table overflow (#4706)
|
|
jni::UniqueLocalFrame frame = jni::PushLocalFrame(*env2, 1);
|
|
|
|
// Stats object
|
|
jni::jobject* jstatus = &jni::NewObject(*env2, *offlineRegionStatusClass, *offlineRegionStatusConstructorId);
|
|
jni::SetField<jint>(*env2, jstatus, *offlineRegionStatusDownloadStateId, downloadState);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedResourceCountId, status.completedResourceCount);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedResourceSizeId, status.completedResourceSize);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedTileCountId, status.completedTileCount);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedTileSizeId, status.completedTileSize);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusRequiredResourceCountId, status.requiredResourceCount);
|
|
jni::SetField<jboolean>(*env2, jstatus, *offlineRegionStatusRequiredResourceCountIsPreciseId, status.requiredResourceCountIsPrecise);
|
|
jni::CallMethod<void>(*env2, observerCallback.get(), *offlineRegionObserveronStatusChangedId, jstatus);
|
|
|
|
// Detach when we're done
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
}
|
|
|
|
void responseError(mbgl::Response::Error error) override {
|
|
// Env
|
|
JNIEnv* env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
|
|
// Handle the value of reason independently of the underlying int value
|
|
std::string errorReason;
|
|
switch(error.reason) {
|
|
case mbgl::Response::Error::Reason::Success:
|
|
errorReason = "REASON_SUCCESS";
|
|
break;
|
|
case mbgl::Response::Error::Reason::NotFound:
|
|
errorReason = "REASON_NOT_FOUND";
|
|
break;
|
|
case mbgl::Response::Error::Reason::Server:
|
|
errorReason = "REASON_SERVER";
|
|
break;
|
|
case mbgl::Response::Error::Reason::Connection:
|
|
errorReason = "REASON_CONNECTION";
|
|
break;
|
|
case mbgl::Response::Error::Reason::RateLimit:
|
|
errorReason = "REASON_RATE_LIMIT";
|
|
break;
|
|
case mbgl::Response::Error::Reason::Other:
|
|
errorReason = "REASON_OTHER";
|
|
break;
|
|
}
|
|
|
|
// Error object
|
|
jni::UniqueLocalFrame frame = jni::PushLocalFrame(*env2, 3);
|
|
jni::jobject* jerror = &jni::NewObject(*env2, *offlineRegionErrorClass, *offlineRegionErrorConstructorId);
|
|
jni::SetField<jni::jobject*>(*env2, jerror, *offlineRegionErrorReasonId, std_string_to_jstring(env2, errorReason));
|
|
jni::SetField<jni::jobject*>(*env2, jerror, *offlineRegionErrorMessageId, std_string_to_jstring(env2, error.message));
|
|
jni::CallMethod<void>(*env2, observerCallback.get(), *offlineRegionObserveronErrorId, jerror);
|
|
|
|
// Detach when we're done
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
}
|
|
|
|
void mapboxTileCountLimitExceeded(uint64_t limit) override {
|
|
// Env
|
|
JNIEnv* env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
|
|
// Send limit
|
|
jni::CallMethod<void>(*env2, observerCallback.get(), *offlineRegionObserveronLimitId, jlong(limit));
|
|
|
|
// Detach when we're done
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
}
|
|
|
|
jni::UniqueGlobalRef<jni::jobject> observerCallback;
|
|
};
|
|
|
|
// Set the observer
|
|
defaultFileSource->setOfflineRegionObserver(*offlineRegion,
|
|
std::make_unique<Observer>(jni::NewGlobalRef(*env, observerCallback)));
|
|
}
|
|
|
|
void setOfflineRegionDownloadState(JNIEnv *env, jni::jobject* offlineRegion_, jint offlineRegionDownloadState) {
|
|
// State
|
|
mbgl::OfflineRegionDownloadState state;
|
|
if (offlineRegionDownloadState == 0) {
|
|
state = mbgl::OfflineRegionDownloadState::Inactive;
|
|
} else if (offlineRegionDownloadState == 1) {
|
|
state = mbgl::OfflineRegionDownloadState::Active;
|
|
} else {
|
|
mbgl::Log::Error(mbgl::Event::JNI, "State can only be 0 (inactive) or 1 (active).");
|
|
return;
|
|
}
|
|
|
|
// Offline region
|
|
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
|
|
|
|
// File source
|
|
jni::jobject* jmanager = jni::GetField<jni::jobject*>(*env, offlineRegion_, *offlineRegionOfflineManagerId);
|
|
jlong defaultFileSourcePtr = jni::GetField<jlong>(*env, jmanager, *offlineManagerClassPtrId);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
|
|
// Set new state
|
|
defaultFileSource->setOfflineRegionDownloadState(*offlineRegion, state);
|
|
}
|
|
|
|
void getOfflineRegionStatus(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject* statusCallback) {
|
|
// Offline region
|
|
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
|
|
|
|
// File source
|
|
jni::jobject* jmanager = jni::GetField<jni::jobject*>(*env, offlineRegion_, *offlineRegionOfflineManagerId);
|
|
jlong defaultFileSourcePtr = jni::GetField<jlong>(*env, jmanager, *offlineManagerClassPtrId);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
|
|
// Makes sure the callback doesn't get GC'ed
|
|
statusCallback = jni::NewGlobalRef(*env, statusCallback).release();
|
|
|
|
// Set new state
|
|
defaultFileSource->getOfflineRegionStatus(*offlineRegion, [statusCallback](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionStatus> status) mutable {
|
|
|
|
// Reattach, the callback comes from a different thread
|
|
JNIEnv *env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
if (renderDetach) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "Attached.");
|
|
}
|
|
|
|
if (error) {
|
|
std::string message = mbgl::util::toString(error);
|
|
jni::CallMethod<void>(*env2, statusCallback, *offlineRegionStatusOnErrorId, std_string_to_jstring(env2, message));
|
|
} else if (status) {
|
|
// Conver to jint
|
|
jint downloadState = -1;
|
|
if (status->downloadState == mbgl::OfflineRegionDownloadState::Inactive) {
|
|
downloadState = 0;
|
|
} else if (status->downloadState == mbgl::OfflineRegionDownloadState::Active) {
|
|
downloadState = 1;
|
|
} else {
|
|
mbgl::Log::Error(mbgl::Event::JNI, "Unsupported OfflineRegionDownloadState value.");
|
|
return;
|
|
}
|
|
|
|
// Stats object
|
|
jni::jobject* jstatus = &jni::NewObject(*env2, *offlineRegionStatusClass, *offlineRegionStatusConstructorId);
|
|
jni::SetField<jint>(*env2, jstatus, *offlineRegionStatusDownloadStateId, downloadState);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedResourceCountId, status->completedResourceCount);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedResourceSizeId, status->completedResourceSize);
|
|
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusRequiredResourceCountId, status->requiredResourceCount);
|
|
jni::SetField<jboolean>(*env2, jstatus, *offlineRegionStatusRequiredResourceCountIsPreciseId, status->requiredResourceCountIsPrecise);
|
|
jni::CallMethod<void>(*env2, statusCallback, *offlineRegionStatusOnStatusId, jstatus);
|
|
}
|
|
|
|
// Delete global refs and detach when we're done
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(statusCallback));
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
});
|
|
}
|
|
|
|
void deleteOfflineRegion(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject* deleteCallback) {
|
|
// Offline region
|
|
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
|
|
|
|
// File source
|
|
jni::jobject* jmanager = jni::GetField<jni::jobject*>(*env, offlineRegion_, *offlineRegionOfflineManagerId);
|
|
jlong defaultFileSourcePtr = jni::GetField<jlong>(*env, jmanager, *offlineManagerClassPtrId);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
|
|
// Makes sure the callback doesn't get GC'ed
|
|
deleteCallback = jni::NewGlobalRef(*env, deleteCallback).release();
|
|
|
|
// Set new state
|
|
jni::SetField<jlong>(*env, offlineRegion_, *offlineRegionPtrId, 0);
|
|
defaultFileSource->deleteOfflineRegion(std::move(*offlineRegion), [deleteCallback](std::exception_ptr error) mutable {
|
|
|
|
// Reattach, the callback comes from a different thread
|
|
JNIEnv *env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
if (renderDetach) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "Attached.");
|
|
}
|
|
|
|
if (error) {
|
|
std::string message = mbgl::util::toString(error);
|
|
jni::CallMethod<void>(*env2, deleteCallback, *offlineRegionDeleteOnErrorId, std_string_to_jstring(env2, message));
|
|
} else {
|
|
jni::CallMethod<void>(*env2, deleteCallback, *offlineRegionDeleteOnDeleteId);
|
|
}
|
|
|
|
// Delete global refs and detach when we're done
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(deleteCallback));
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
});
|
|
}
|
|
|
|
void updateOfflineRegionMetadata(JNIEnv *env, jni::jobject* offlineRegion_, jni::jarray<jbyte>* metadata_, jni::jobject* updateCallback) {
|
|
// Offline region
|
|
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
|
|
|
|
// File source
|
|
jni::jobject* jmanager = jni::GetField<jni::jobject*>(*env, offlineRegion_, *offlineRegionOfflineManagerId);
|
|
jlong defaultFileSourcePtr = jni::GetField<jlong>(*env, jmanager, *offlineManagerClassPtrId);
|
|
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
|
|
|
|
// Id conversion
|
|
int64_t id = offlineRegion->getID();
|
|
|
|
// Metadata
|
|
mbgl::OfflineRegionMetadata metadata;
|
|
if (metadata_ != nullptr) {
|
|
metadata = metadata_from_java(env, *metadata_);
|
|
}
|
|
|
|
// Makes sure the objects don't get GC'ed
|
|
updateCallback = jni::NewGlobalRef(*env, updateCallback).release();
|
|
|
|
// Launch updateCallback
|
|
defaultFileSource->updateOfflineMetadata(id, metadata, [updateCallback] (std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionMetadata> data) mutable {
|
|
// Reattach, the callback comes from a different thread
|
|
JNIEnv *env2;
|
|
jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread");
|
|
if (renderDetach) {
|
|
mbgl::Log::Debug(mbgl::Event::JNI, "Attached.");
|
|
}
|
|
|
|
if (error) {
|
|
std::string message = mbgl::util::toString(error);
|
|
jni::CallMethod<void>(*env2, updateCallback, *updateMetadataOnErrorMethodId, std_string_to_jstring(env2, message));
|
|
} else if (data) {
|
|
jni::jarray<jbyte>* jmetadata = metadata_from_native(env2, *data);
|
|
jni::CallMethod<void>(*env2, updateCallback, *updateMetadataOnUpdateMethodId, jmetadata);
|
|
}
|
|
|
|
// Delete global refs and detach when we're done
|
|
jni::DeleteGlobalRef(*env2, jni::UniqueGlobalRef<jni::jobject>(updateCallback));
|
|
detach_jni_thread(theJVM, &env2, renderDetach);
|
|
});
|
|
}
|
|
|
|
// Offline calls end
|
|
|
|
}
|
|
|
|
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
|
theJVM = vm;
|
|
|
|
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
|
|
|
|
static mbgl::util::RunLoop mainRunLoop;
|
|
|
|
mbgl::android::RegisterNativeHTTPRequest(env);
|
|
|
|
java::registerNatives(env);
|
|
registerNativeLayers(env);
|
|
registerNativeSources(env);
|
|
ConnectivityListener::registerNative(env);
|
|
|
|
latLngClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLng");
|
|
latLngClass = jni::NewGlobalRef(env, latLngClass).release();
|
|
latLngConstructorId = &jni::GetMethodID(env, *latLngClass, "<init>", "(DD)V");
|
|
latLngLatitudeId = &jni::GetFieldID(env, *latLngClass, "latitude", "D");
|
|
latLngLongitudeId = &jni::GetFieldID(env, *latLngClass, "longitude", "D");
|
|
|
|
latLngBoundsClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLngBounds");
|
|
latLngBoundsClass = jni::NewGlobalRef(env, latLngBoundsClass).release();
|
|
latLngBoundsConstructorId = &jni::GetMethodID(env, *latLngBoundsClass, "<init>", "(DDDD)V");
|
|
latLngBoundsLatNorthId = &jni::GetFieldID(env, *latLngBoundsClass, "mLatNorth", "D");
|
|
latLngBoundsLatSouthId = &jni::GetFieldID(env, *latLngBoundsClass, "mLatSouth", "D");
|
|
latLngBoundsLonEastId = &jni::GetFieldID(env, *latLngBoundsClass, "mLonEast", "D");
|
|
latLngBoundsLonWestId = &jni::GetFieldID(env, *latLngBoundsClass, "mLonWest", "D");
|
|
|
|
iconClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Icon");
|
|
iconClass = jni::NewGlobalRef(env, iconClass).release();
|
|
iconIdId = &jni::GetFieldID(env, *iconClass, "mId", "Ljava/lang/String;");
|
|
|
|
markerClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Marker");
|
|
markerClass = jni::NewGlobalRef(env, markerClass).release();
|
|
markerPositionId = &jni::GetFieldID(env, *markerClass, "position", "Lcom/mapbox/mapboxsdk/geometry/LatLng;");
|
|
markerIconId = &jni::GetFieldID(env, *markerClass, "icon", "Lcom/mapbox/mapboxsdk/annotations/Icon;");
|
|
markerIdId = &jni::GetFieldID(env, *markerClass, "id", "J");
|
|
|
|
polylineClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Polyline");
|
|
polylineClass = jni::NewGlobalRef(env, polylineClass).release();
|
|
polylineAlphaId = &jni::GetFieldID(env, *polylineClass, "alpha", "F");
|
|
polylineColorId = &jni::GetFieldID(env, *polylineClass, "color", "I");
|
|
polylineWidthId = &jni::GetFieldID(env, *polylineClass, "width", "F");
|
|
polylinePointsId = &jni::GetFieldID(env, *polylineClass, "points", "Ljava/util/List;");
|
|
|
|
polygonClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Polygon");
|
|
polygonClass = jni::NewGlobalRef(env, polygonClass).release();
|
|
polygonAlphaId = &jni::GetFieldID(env, *polygonClass, "alpha", "F");
|
|
polygonFillColorId = &jni::GetFieldID(env, *polygonClass, "fillColor", "I");
|
|
polygonStrokeColorId = &jni::GetFieldID(env, *polygonClass, "strokeColor", "I");
|
|
polygonPointsId = &jni::GetFieldID(env, *polygonClass, "points", "Ljava/util/List;");
|
|
|
|
jni::jclass* listClass = &jni::FindClass(env, "java/util/List");
|
|
listToArrayId = &jni::GetMethodID(env, *listClass, "toArray", "()[Ljava/lang/Object;");
|
|
|
|
arrayListClass = &jni::FindClass(env, "java/util/ArrayList");
|
|
arrayListClass = jni::NewGlobalRef(env, arrayListClass).release();
|
|
arrayListConstructorId = &jni::GetMethodID(env, *arrayListClass, "<init>", "()V");
|
|
arrayListAddId = &jni::GetMethodID(env, *arrayListClass, "add", "(Ljava/lang/Object;)Z");
|
|
|
|
projectedMetersClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/ProjectedMeters");
|
|
projectedMetersClass = jni::NewGlobalRef(env, projectedMetersClass).release();
|
|
projectedMetersConstructorId = &jni::GetMethodID(env, *projectedMetersClass, "<init>", "(DD)V");
|
|
projectedMetersNorthingId = &jni::GetFieldID(env, *projectedMetersClass, "northing", "D");
|
|
projectedMetersEastingId = &jni::GetFieldID(env, *projectedMetersClass, "easting", "D");
|
|
|
|
pointFClass = &jni::FindClass(env, "android/graphics/PointF");
|
|
pointFClass = jni::NewGlobalRef(env, pointFClass).release();
|
|
pointFConstructorId = &jni::GetMethodID(env, *pointFClass, "<init>", "(FF)V");
|
|
pointFXId = &jni::GetFieldID(env, *pointFClass, "x", "F");
|
|
pointFYId = &jni::GetFieldID(env, *pointFClass, "y", "F");
|
|
|
|
rectFClass = &jni::FindClass(env, "android/graphics/RectF");
|
|
rectFClass = jni::NewGlobalRef(env, rectFClass).release();
|
|
rectFConstructorId = &jni::GetMethodID(env, *rectFClass, "<init>", "()V");
|
|
rectFLeftId = &jni::GetFieldID(env, *rectFClass, "left", "F");
|
|
rectFRightId = &jni::GetFieldID(env, *rectFClass, "right", "F");
|
|
rectFTopId = &jni::GetFieldID(env, *rectFClass, "top", "F");
|
|
rectFBottomId = &jni::GetFieldID(env, *rectFClass, "bottom", "F");
|
|
|
|
jni::jclass& nativeMapViewClass = jni::FindClass(env, "com/mapbox/mapboxsdk/maps/NativeMapView");
|
|
|
|
onInvalidateId = &jni::GetMethodID(env, nativeMapViewClass, "onInvalidate", "()V");
|
|
onMapChangedId = &jni::GetMethodID(env, nativeMapViewClass, "onMapChanged", "(I)V");
|
|
onFpsChangedId = &jni::GetMethodID(env, nativeMapViewClass, "onFpsChanged", "(D)V");
|
|
onSnapshotReadyId = &jni::GetMethodID(env, nativeMapViewClass, "onSnapshotReady","([B)V");
|
|
|
|
#define MAKE_NATIVE_METHOD(name, sig) jni::MakeNativeMethod<decltype(name), name>( #name, sig )
|
|
|
|
jni::RegisterNatives(env, nativeMapViewClass,
|
|
MAKE_NATIVE_METHOD(nativeCreate, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;FIJ)J"),
|
|
MAKE_NATIVE_METHOD(nativeDestroy, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeInitializeDisplay, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeTerminateDisplay, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeInitializeContext, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeTerminateContext, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeCreateSurface, "(JLandroid/view/Surface;)V"),
|
|
MAKE_NATIVE_METHOD(nativeDestroySurface, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeUpdate, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeRender, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeViewResize, "(JII)V"),
|
|
MAKE_NATIVE_METHOD(nativeFramebufferResize, "(JII)V"),
|
|
MAKE_NATIVE_METHOD(nativeAddClass, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeRemoveClass, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeHasClass, "(JLjava/lang/String;)Z"),
|
|
MAKE_NATIVE_METHOD(nativeSetClasses, "(JLjava/util/List;)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetClasses, "(J)Ljava/util/List;"),
|
|
MAKE_NATIVE_METHOD(nativeSetStyleUrl, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetStyleJson, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetStyleJson, "(J)Ljava/lang/String;"),
|
|
MAKE_NATIVE_METHOD(nativeSetAccessToken, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetAccessToken, "(J)Ljava/lang/String;"),
|
|
MAKE_NATIVE_METHOD(nativeCancelTransitions, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetGestureInProgress, "(JZ)V"),
|
|
MAKE_NATIVE_METHOD(nativeMoveBy, "(JDDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetLatLng, "(JDDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetLatLng, "(J)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
|
|
MAKE_NATIVE_METHOD(nativeResetPosition, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetCameraValues, "(J)[D"),
|
|
MAKE_NATIVE_METHOD(nativeGetPitch, "(J)D"),
|
|
MAKE_NATIVE_METHOD(nativeSetPitch, "(JDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeScaleBy, "(JDDDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetScale, "(JDDDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetScale, "(J)D"),
|
|
MAKE_NATIVE_METHOD(nativeSetZoom, "(JDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetZoom, "(J)D"),
|
|
MAKE_NATIVE_METHOD(nativeResetZoom, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetMinZoom, "(J)D"),
|
|
MAKE_NATIVE_METHOD(nativeSetMinZoom, "(JD)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetMaxZoom, "(J)D"),
|
|
MAKE_NATIVE_METHOD(nativeSetMaxZoom, "(JD)V"),
|
|
MAKE_NATIVE_METHOD(nativeRotateBy, "(JDDDDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetBearing, "(JDJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetBearingXY, "(JDDD)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetBearing, "(J)D"),
|
|
MAKE_NATIVE_METHOD(nativeResetNorth, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeAddMarkers, "(J[Lcom/mapbox/mapboxsdk/annotations/Marker;)[J"),
|
|
MAKE_NATIVE_METHOD(nativeAddPolylines, "(J[Lcom/mapbox/mapboxsdk/annotations/Polyline;)[J"),
|
|
MAKE_NATIVE_METHOD(nativeAddPolygons, "(J[Lcom/mapbox/mapboxsdk/annotations/Polygon;)[J"),
|
|
MAKE_NATIVE_METHOD(nativeUpdateMarker, "(JJDDLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeUpdatePolygon, "(JJLcom/mapbox/mapboxsdk/annotations/Polygon;)V"),
|
|
MAKE_NATIVE_METHOD(nativeUpdatePolyline, "(JJLcom/mapbox/mapboxsdk/annotations/Polyline;)V"),
|
|
MAKE_NATIVE_METHOD(nativeRemoveAnnotations, "(J[J)V"),
|
|
MAKE_NATIVE_METHOD(nativeQueryPointAnnotations, "(JLandroid/graphics/RectF;)[J"),
|
|
MAKE_NATIVE_METHOD(nativeAddAnnotationIcon, "(JLjava/lang/String;IIF[B)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetVisibleCoordinateBounds, "(J[Lcom/mapbox/mapboxsdk/geometry/LatLng;Landroid/graphics/RectF;DJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeOnLowMemory, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetDebug, "(JZ)V"),
|
|
MAKE_NATIVE_METHOD(nativeToggleDebug, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetDebug, "(J)Z"),
|
|
MAKE_NATIVE_METHOD(nativeIsFullyLoaded, "(J)Z"),
|
|
MAKE_NATIVE_METHOD(nativeSetReachability, "(JZ)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetMetersPerPixelAtLatitude, "(JDD)D"),
|
|
MAKE_NATIVE_METHOD(nativeProjectedMetersForLatLng, "(JDD)Lcom/mapbox/mapboxsdk/geometry/ProjectedMeters;"),
|
|
MAKE_NATIVE_METHOD(nativeLatLngForProjectedMeters, "(JDD)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
|
|
MAKE_NATIVE_METHOD(nativePixelForLatLng, "(JDD)Landroid/graphics/PointF;"),
|
|
MAKE_NATIVE_METHOD(nativeLatLngForPixel, "(JFF)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
|
|
MAKE_NATIVE_METHOD(nativeGetTopOffsetPixelsForAnnotationSymbol, "(JLjava/lang/String;)D"),
|
|
MAKE_NATIVE_METHOD(nativeJumpTo, "(JDDDDD)V"),
|
|
MAKE_NATIVE_METHOD(nativeEaseTo, "(JDDDJDDZ)V"),
|
|
MAKE_NATIVE_METHOD(nativeFlyTo, "(JDDDJDD)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetLayer, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/layers/Layer;"),
|
|
MAKE_NATIVE_METHOD(nativeAddLayer, "(JJLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeGetSource, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/sources/Source;"),
|
|
MAKE_NATIVE_METHOD(nativeAddSource, "(JJ)V"),
|
|
MAKE_NATIVE_METHOD(nativeRemoveSource, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeAddImage, "(JLjava/lang/String;IIF[B)V"),
|
|
MAKE_NATIVE_METHOD(nativeRemoveImage, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V"),
|
|
MAKE_NATIVE_METHOD(nativeScheduleTakeSnapshot, "(J)V"),
|
|
MAKE_NATIVE_METHOD(nativeQueryRenderedFeaturesForPoint, "(JFF[Ljava/lang/String;)[Lcom/mapbox/services/commons/geojson/Feature;"),
|
|
MAKE_NATIVE_METHOD(nativeQueryRenderedFeaturesForBox, "(JFFFF[Ljava/lang/String;)[Lcom/mapbox/services/commons/geojson/Feature;"),
|
|
MAKE_NATIVE_METHOD(nativeSetAPIBaseURL, "(JLjava/lang/String;)V")
|
|
);
|
|
|
|
// Offline begin
|
|
|
|
struct OfflineManager {
|
|
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; }
|
|
|
|
struct ListOfflineRegionsCallback {
|
|
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback"; }
|
|
};
|
|
|
|
struct CreateOfflineRegionsCallback {
|
|
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback"; }
|
|
};
|
|
};
|
|
|
|
struct OfflineRegion {
|
|
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; }
|
|
};
|
|
|
|
jni::Class<OfflineManager> offlineManagerClass = jni::Class<OfflineManager>::Find(env);
|
|
offlineManagerClassPtrId = &jni::GetFieldID(env, offlineManagerClass, "mDefaultFileSourcePtr", "J");
|
|
|
|
jni::RegisterNatives(env, offlineManagerClass,
|
|
MAKE_NATIVE_METHOD(createDefaultFileSource, "(Ljava/lang/String;Ljava/lang/String;J)J"),
|
|
MAKE_NATIVE_METHOD(setAccessToken, "(JLjava/lang/String;)V"),
|
|
MAKE_NATIVE_METHOD(getAccessToken, "(J)Ljava/lang/String;"),
|
|
MAKE_NATIVE_METHOD(listOfflineRegions, "(JLcom/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback;)V"),
|
|
MAKE_NATIVE_METHOD(createOfflineRegion, "(JLcom/mapbox/mapboxsdk/offline/OfflineRegionDefinition;[BLcom/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback;)V"),
|
|
MAKE_NATIVE_METHOD(setOfflineMapboxTileCountLimit, "(JJ)V")
|
|
);
|
|
|
|
jni::Class<OfflineManager::ListOfflineRegionsCallback> listOfflineRegionsCallbackClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Find(env);
|
|
listOnListMethodId = &jni::GetMethodID(env, listOfflineRegionsCallbackClass, "onList", "([Lcom/mapbox/mapboxsdk/offline/OfflineRegion;)V");
|
|
listOnErrorMethodId = &jni::GetMethodID(env, listOfflineRegionsCallbackClass, "onError", "(Ljava/lang/String;)V");
|
|
|
|
jni::Class<OfflineManager::CreateOfflineRegionsCallback> createOfflineRegionCallbackClass = jni::Class<OfflineManager::CreateOfflineRegionsCallback>::Find(env);
|
|
createOnCreateMethodId = &jni::GetMethodID(env, createOfflineRegionCallbackClass, "onCreate", "(Lcom/mapbox/mapboxsdk/offline/OfflineRegion;)V");
|
|
createOnErrorMethodId = &jni::GetMethodID(env, createOfflineRegionCallbackClass, "onError", "(Ljava/lang/String;)V");
|
|
|
|
offlineRegionClass = &jni::FindClass(env, OfflineRegion::Name());
|
|
offlineRegionClass = jni::NewGlobalRef(env, offlineRegionClass).release();
|
|
offlineRegionConstructorId = &jni::GetMethodID(env, *offlineRegionClass, "<init>", "()V");
|
|
offlineRegionOfflineManagerId = &jni::GetFieldID(env, *offlineRegionClass, "offlineManager", "Lcom/mapbox/mapboxsdk/offline/OfflineManager;");
|
|
offlineRegionIdId = &jni::GetFieldID(env, *offlineRegionClass, "mId", "J");
|
|
offlineRegionDefinitionId = &jni::GetFieldID(env, *offlineRegionClass, "mDefinition", "Lcom/mapbox/mapboxsdk/offline/OfflineRegionDefinition;");
|
|
offlineRegionMetadataId = &jni::GetFieldID(env, *offlineRegionClass, "mMetadata", "[B");
|
|
offlineRegionPtrId = &jni::GetFieldID(env, *offlineRegionClass, "mOfflineRegionPtr", "J");
|
|
|
|
jni::RegisterNatives(env, *offlineRegionClass,
|
|
MAKE_NATIVE_METHOD(destroyOfflineRegion, "()V"),
|
|
MAKE_NATIVE_METHOD(setOfflineRegionObserver, "(Lcom/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver;)V"),
|
|
MAKE_NATIVE_METHOD(setOfflineRegionDownloadState, "(I)V"),
|
|
MAKE_NATIVE_METHOD(getOfflineRegionStatus, "(Lcom/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionStatusCallback;)V"),
|
|
MAKE_NATIVE_METHOD(deleteOfflineRegion, "(Lcom/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionDeleteCallback;)V"),
|
|
MAKE_NATIVE_METHOD(updateOfflineRegionMetadata, "([BLcom/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionUpdateMetadataCallback;)V")
|
|
);
|
|
|
|
// This needs to be updated once we support more than one type of region definition
|
|
offlineRegionDefinitionClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition");
|
|
offlineRegionDefinitionClass = jni::NewGlobalRef(env, offlineRegionDefinitionClass).release();
|
|
offlineRegionDefinitionConstructorId = &jni::GetMethodID(env, *offlineRegionDefinitionClass, "<init>", "()V");
|
|
offlineRegionDefinitionStyleURLId = &jni::GetFieldID(env, *offlineRegionDefinitionClass, "styleURL", "Ljava/lang/String;");
|
|
offlineRegionDefinitionBoundsId = &jni::GetFieldID(env, *offlineRegionDefinitionClass, "bounds", "Lcom/mapbox/mapboxsdk/geometry/LatLngBounds;");
|
|
offlineRegionDefinitionMinZoomId = &jni::GetFieldID(env, *offlineRegionDefinitionClass, "minZoom", "D");
|
|
offlineRegionDefinitionMaxZoomId = &jni::GetFieldID(env, *offlineRegionDefinitionClass, "maxZoom", "D");
|
|
offlineRegionDefinitionPixelRatioId = &jni::GetFieldID(env, *offlineRegionDefinitionClass, "pixelRatio", "F");
|
|
|
|
jni::jclass* offlineRegionObserverClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver");
|
|
offlineRegionObserveronStatusChangedId = &jni::GetMethodID(env, *offlineRegionObserverClass, "onStatusChanged", "(Lcom/mapbox/mapboxsdk/offline/OfflineRegionStatus;)V");
|
|
offlineRegionObserveronErrorId = &jni::GetMethodID(env, *offlineRegionObserverClass, "onError", "(Lcom/mapbox/mapboxsdk/offline/OfflineRegionError;)V");
|
|
offlineRegionObserveronLimitId = &jni::GetMethodID(env, *offlineRegionObserverClass, "mapboxTileCountLimitExceeded", "(J)V");
|
|
|
|
offlineRegionStatusClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineRegionStatus");
|
|
offlineRegionStatusClass = jni::NewGlobalRef(env, offlineRegionStatusClass).release();
|
|
offlineRegionStatusConstructorId = &jni::GetMethodID(env, *offlineRegionStatusClass, "<init>", "()V");
|
|
offlineRegionStatusDownloadStateId = &jni::GetFieldID(env, *offlineRegionStatusClass, "downloadState", "I");
|
|
offlineRegionStatusCompletedResourceCountId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedResourceCount", "J");
|
|
offlineRegionStatusCompletedResourceSizeId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedResourceSize", "J");
|
|
offlineRegionStatusCompletedTileCountId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedTileCount", "J");
|
|
offlineRegionStatusCompletedTileSizeId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedTileSize", "J");
|
|
offlineRegionStatusRequiredResourceCountId = &jni::GetFieldID(env, *offlineRegionStatusClass, "requiredResourceCount", "J");
|
|
offlineRegionStatusRequiredResourceCountIsPreciseId = &jni::GetFieldID(env, *offlineRegionStatusClass, "requiredResourceCountIsPrecise", "Z");
|
|
|
|
offlineRegionErrorClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineRegionError");
|
|
offlineRegionErrorClass = jni::NewGlobalRef(env, offlineRegionErrorClass).release();
|
|
offlineRegionErrorConstructorId = &jni::GetMethodID(env, *offlineRegionErrorClass, "<init>", "()V");
|
|
offlineRegionErrorReasonId = &jni::GetFieldID(env, *offlineRegionErrorClass, "reason", "Ljava/lang/String;");
|
|
offlineRegionErrorMessageId = &jni::GetFieldID(env, *offlineRegionErrorClass, "message", "Ljava/lang/String;");
|
|
|
|
jni::jclass* offlineRegionStatusCallbackClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionStatusCallback");
|
|
offlineRegionStatusOnStatusId = &jni::GetMethodID(env, *offlineRegionStatusCallbackClass, "onStatus", "(Lcom/mapbox/mapboxsdk/offline/OfflineRegionStatus;)V");
|
|
offlineRegionStatusOnErrorId = &jni::GetMethodID(env, *offlineRegionStatusCallbackClass, "onError", "(Ljava/lang/String;)V");
|
|
|
|
jni::jclass* offlineRegionDeleteCallbackClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionDeleteCallback");
|
|
offlineRegionDeleteOnDeleteId = &jni::GetMethodID(env, *offlineRegionDeleteCallbackClass, "onDelete", "()V");
|
|
offlineRegionDeleteOnErrorId = &jni::GetMethodID(env, *offlineRegionDeleteCallbackClass, "onError", "(Ljava/lang/String;)V");
|
|
|
|
jni::jclass* offlineRegionUpdateMetadataCallbackClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionUpdateMetadataCallback");
|
|
updateMetadataOnUpdateMethodId = &jni::GetMethodID(env, *offlineRegionUpdateMetadataCallbackClass, "onUpdate", "([B)V");
|
|
updateMetadataOnErrorMethodId = &jni::GetMethodID(env, *offlineRegionUpdateMetadataCallbackClass, "onError", "(Ljava/lang/String;)V");
|
|
|
|
// Offline end
|
|
|
|
char release[PROP_VALUE_MAX] = "";
|
|
__system_property_get("ro.build.version.release", release);
|
|
androidRelease = std::string(release);
|
|
|
|
return JNI_VERSION_1_6;
|
|
}
|