diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp index b1bfefe2803..37c790a4261 100644 --- a/android/cpp/jni.cpp +++ b/android/cpp/jni.cpp @@ -33,16 +33,16 @@ std::string androidRelease; jmethodID onMapChangedId = nullptr; jmethodID onFpsChangedId = nullptr; -jclass lonLatClass = nullptr; -jmethodID lonLatConstructorId = nullptr; -jfieldID lonLatLonId = nullptr; -jfieldID lonLatLatId = nullptr; +jclass latLngClass = nullptr; +jmethodID latLngConstructorId = nullptr; +jfieldID latLngLatitudeId = nullptr; +jfieldID latLngLongitudeId = nullptr; -jclass lonLatZoomClass = nullptr; -jmethodID lonLatZoomConstructorId = nullptr; -jfieldID lonLatZoomLonId = nullptr; -jfieldID lonLatZoomLatId = nullptr; -jfieldID lonLatZoomZoomId = nullptr; +jclass latLngZoomClass = nullptr; +jmethodID latLngZoomConstructorId = nullptr; +jfieldID latLngZoomLatitudeId = nullptr; +jfieldID latLngZoomLongitudeId = nullptr; +jfieldID latLngZoomZoomId = nullptr; jclass runtimeExceptionClass = nullptr; jclass nullPointerExceptionClass = nullptr; @@ -53,6 +53,16 @@ jclass arrayListClass = nullptr; jmethodID arrayListConstructorId = nullptr; jmethodID arrayListAddId = nullptr; +jclass projectedMetersClass = nullptr; +jmethodID projectedMetersConstructorId = nullptr; +jfieldID projectedMetersNorthingId = nullptr; +jfieldID projectedMetersEastingId = nullptr; + +jclass pointFClass = nullptr; +jmethodID pointFConstructorId = nullptr; +jfieldID pointFXId = nullptr; +jfieldID pointFYId = nullptr; + bool throw_error(JNIEnv *env, const char *msg) { if (env->ThrowNew(runtimeExceptionClass, msg) < 0) { env->ExceptionDescribe(); @@ -449,34 +459,34 @@ void JNICALL nativeMoveBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdou nativeMapView->getMap().moveBy(dx, dy, std::chrono::milliseconds(duration)); } -void JNICALL nativeSetLonLat(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject lonLat, +void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng, jlong duration) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLonLat"); + mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLatLng"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - double lon = env->GetDoubleField(lonLat, lonLatLonId); + jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } - double lat = env->GetDoubleField(lonLat, lonLatLatId); + jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } - nativeMapView->getMap().setLatLng(mbgl::LatLng(lat, lon), std::chrono::milliseconds(duration)); + nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration)); } -jobject JNICALL nativeGetLonLat(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLonLat"); +jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(); - jobject ret = env->NewObject(lonLatClass, lonLatConstructorId, latLng.longitude, latLng.latitude); + jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; @@ -544,41 +554,41 @@ jdouble JNICALL nativeGetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) return nativeMapView->getMap().getZoom(); } -void JNICALL nativeSetLonLatZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, - jobject lonLatZoom, jlong duration) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLonLatZoom"); +void JNICALL nativeSetLatLngZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, + jobject latLngZoom, jlong duration) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLatLngZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - double lon = env->GetDoubleField(lonLatZoom, lonLatZoomLonId); + jdouble latitude = env->GetDoubleField(latLngZoom, latLngZoomLatitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } - double lat = env->GetDoubleField(lonLatZoom, lonLatZoomLatId); + jdouble longitude = env->GetDoubleField(latLngZoom, latLngZoomLongitudeId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } - double zoom = env->GetDoubleField(lonLatZoom, lonLatZoomZoomId); + jdouble zoom = env->GetDoubleField(latLngZoom, latLngZoomZoomId); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return; } - nativeMapView->getMap().setLatLngZoom(mbgl::LatLng(lat, lon), zoom, std::chrono::milliseconds(duration)); + nativeMapView->getMap().setLatLngZoom(mbgl::LatLng(latitude, longitude), zoom, std::chrono::milliseconds(duration)); } -jobject JNICALL nativeGetLonLatZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLonLatZoom"); +jobject JNICALL nativeGetLatLngZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLngZoom"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(); - double zoom = nativeMapView->getMap().getZoom(); + jdouble zoom = nativeMapView->getMap().getZoom(); - jobject ret = env->NewObject(lonLatZoomClass, lonLatZoomConstructorId, latLng.longitude, latLng.latitude, zoom); + jobject ret = env->NewObject(latLngZoomClass, latLngZoomConstructorId, latLng.longitude, latLng.latitude, zoom); if (ret == nullptr) { env->ExceptionDescribe(); return nullptr; @@ -705,6 +715,125 @@ nativeSetReachability(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean mbgl::NetworkStatus::Reachable(); } } + +jdouble JNICALL nativeGetMetersPerPixelAtLatitude(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble lat, jdouble zoom) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMetersPerPixelAtLatitude"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + return nativeMapView->getMap().getMetersPerPixelAtLatitude(lat, zoom); +} + +jobject JNICALL nativeProjectedMetersForLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeProjectedMetersForLatLng"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + mbgl::ProjectedMeters projectedMeters = nativeMapView->getMap().projectedMetersForLatLng(mbgl::LatLng(latitude, longitude)); + + jobject ret = env->NewObject(projectedMetersClass, projectedMetersConstructorId, projectedMeters.northing, projectedMeters.easting); + if (ret == nullptr) { + env->ExceptionDescribe(); + return nullptr; + } + + return ret; +} + +jobject JNICALL nativeLatLngForProjectedMeters(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject projectedMeters) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeLatLngForProjectedMeters"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + jdouble northing = env->GetDoubleField(projectedMeters, projectedMetersNorthingId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble easting = env->GetDoubleField(projectedMeters, projectedMetersEastingId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + mbgl::LatLng latLng = nativeMapView->getMap().latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting)); + + jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude); + if (ret == nullptr) { + env->ExceptionDescribe(); + return nullptr; + } + + return ret; +} + +jobject JNICALL nativePixelForLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativePixelForLatLng"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + mbgl::vec2 pixel = nativeMapView->getMap().pixelForLatLng(mbgl::LatLng(latitude, longitude)); + + jobject ret = env->NewObject(pointFClass, pointFConstructorId, static_cast(pixel.x), static_cast(pixel.y)); + if (ret == nullptr) { + env->ExceptionDescribe(); + return nullptr; + } + + return ret; +} + +jobject JNICALL nativeLatLngForPixel(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject pixel) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeLatLngForPixel"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); + + jfloat x = env->GetDoubleField(pixel, pointFXId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + jfloat y = env->GetDoubleField(pixel, pointFYId); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return nullptr; + } + + mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::vec2(x, y)); + + jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude); + if (ret == nullptr) { + env->ExceptionDescribe(); + return nullptr; + } + + return ret; +} } extern "C" { @@ -721,61 +850,61 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } - lonLatClass = env->FindClass("com/mapbox/mapboxgl/lib/geometry/LatLng"); - if (lonLatClass == nullptr) { + latLngClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLng"); + if (latLngClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatConstructorId = env->GetMethodID(lonLatClass, "", "(DD)V"); - if (lonLatConstructorId == nullptr) { + latLngConstructorId = env->GetMethodID(latLngClass, "", "(DD)V"); + if (latLngConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatLonId = env->GetFieldID(lonLatClass, "longitude", "D"); - if (lonLatLonId == nullptr) { + latLngLatitudeId = env->GetFieldID(latLngClass, "latitude", "D"); + if (latLngLatitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatLatId = env->GetFieldID(lonLatClass, "latitude", "D"); - if (lonLatLatId == nullptr) { + latLngLongitudeId = env->GetFieldID(latLngClass, "longitude", "D"); + if (latLngLongitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatZoomClass = env->FindClass("com/mapbox/mapboxgl/lib/LatLngZoom"); - if (lonLatClass == nullptr) { + latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom"); + if (latLngZoomClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatZoomConstructorId = env->GetMethodID(lonLatZoomClass, "", "(DDD)V"); - if (lonLatZoomConstructorId == nullptr) { + latLngZoomConstructorId = env->GetMethodID(latLngZoomClass, "", "(DDD)V"); + if (latLngZoomConstructorId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatZoomLonId = env->GetFieldID(lonLatZoomClass, "longitude", "D"); - if (lonLatZoomLonId == nullptr) { + latLngZoomLatitudeId = env->GetFieldID(latLngZoomClass, "latitude", "D"); + if (latLngZoomLatitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatZoomLatId = env->GetFieldID(lonLatZoomClass, "latitude", "D"); - if (lonLatZoomLatId == nullptr) { + latLngZoomLongitudeId = env->GetFieldID(latLngZoomClass, "longitude", "D"); + if (latLngZoomLongitudeId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatZoomZoomId = env->GetFieldID(lonLatZoomClass, "zoom", "D"); - if (lonLatZoomZoomId == nullptr) { + latLngZoomZoomId = env->GetFieldID(latLngZoomClass, "zoom", "D"); + if (latLngZoomZoomId == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - jclass nativeMapViewClass = env->FindClass("com/mapbox/mapboxgl/lib/NativeMapView"); + jclass nativeMapViewClass = env->FindClass("com/mapbox/mapboxgl/views/NativeMapView"); if (nativeMapViewClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; @@ -835,9 +964,57 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } + projectedMetersClass = env->FindClass("com/mapbox/mapboxgl/geometry/ProjectedMeters"); + if (projectedMetersClass == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + projectedMetersConstructorId = env->GetMethodID(projectedMetersClass, "", "(DD)V"); + if (projectedMetersConstructorId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + projectedMetersNorthingId = env->GetFieldID(projectedMetersClass, "northing", "D"); + if (projectedMetersNorthingId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + projectedMetersEastingId = env->GetFieldID(projectedMetersClass, "easting", "D"); + if (projectedMetersEastingId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + pointFClass = env->FindClass("android/graphics/PointF"); + if (pointFClass == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + pointFConstructorId = env->GetMethodID(pointFClass, "", "(FF)V"); + if (pointFConstructorId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + pointFXId = env->GetFieldID(pointFClass, "x", "F"); + if (pointFXId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + pointFYId = env->GetFieldID(pointFClass, "y", "F"); + if (pointFYId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + // NOTE: if you get java.lang.UnsatisfiedLinkError you likely forgot to set the size of the // array correctly (too large) - std::array methods = {{ // Can remove the extra brace in C++14 + std::array methods = {{ // Can remove the extra brace in C++14 {"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J", reinterpret_cast(&nativeCreate)}, {"nativeDestroy", "(J)V", reinterpret_cast(&nativeDestroy)}, @@ -891,10 +1068,10 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { reinterpret_cast(&nativeGetAccessToken)}, {"nativeCancelTransitions", "(J)V", reinterpret_cast(&nativeCancelTransitions)}, {"nativeMoveBy", "(JDDJ)V", reinterpret_cast(&nativeMoveBy)}, - {"nativeSetLonLat", "(JLcom/mapbox/mapboxgl/lib/geometry/LatLng;J)V", - reinterpret_cast(&nativeSetLonLat)}, - {"nativeGetLonLat", "(J)Lcom/mapbox/mapboxgl/lib/geometry/LatLng;", - reinterpret_cast(&nativeGetLonLat)}, + {"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V", + reinterpret_cast(&nativeSetLatLng)}, + {"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;", + reinterpret_cast(&nativeGetLatLng)}, {"nativeStartPanning", "(J)V", reinterpret_cast(&nativeStartPanning)}, {"nativeStopPanning", "(J)V", reinterpret_cast(&nativeStopPanning)}, {"nativeResetPosition", "(J)V", reinterpret_cast(&nativeResetPosition)}, @@ -903,10 +1080,10 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { {"nativeGetScale", "(J)D", reinterpret_cast(&nativeGetScale)}, {"nativeSetZoom", "(JDJ)V", reinterpret_cast(&nativeSetZoom)}, {"nativeGetZoom", "(J)D", reinterpret_cast(&nativeGetZoom)}, - {"nativeSetLonLatZoom", "(JLcom/mapbox/mapboxgl/lib/LatLngZoom;J)V", - reinterpret_cast(&nativeSetLonLatZoom)}, - {"nativeGetLonLatZoom", "(J)Lcom/mapbox/mapboxgl/lib/LatLngZoom;", - reinterpret_cast(&nativeGetLonLatZoom)}, + {"nativeSetLatLngZoom", "(JLcom/mapbox/mapboxgl/geometry/LatLngZoom;J)V", + reinterpret_cast(&nativeSetLatLngZoom)}, + {"nativeGetLatLngZoom", "(J)Lcom/mapbox/mapboxgl/geometry/LatLngZoom;", + reinterpret_cast(&nativeGetLatLngZoom)}, {"nativeResetZoom", "(J)V", reinterpret_cast(&nativeResetZoom)}, {"nativeStartPanning", "(J)V", reinterpret_cast(&nativeStartScaling)}, {"nativeStopPanning", "(J)V", reinterpret_cast(&nativeStopScaling)}, @@ -928,31 +1105,39 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { {"nativeSetDebug", "(JZ)V", reinterpret_cast(&nativeSetDebug)}, {"nativeToggleDebug", "(J)V", reinterpret_cast(&nativeToggleDebug)}, {"nativeGetDebug", "(J)Z", reinterpret_cast(&nativeGetDebug)}, - {"nativeSetReachability", "(JZ)V", reinterpret_cast(&nativeSetReachability)}}}; + {"nativeSetReachability", "(JZ)V", reinterpret_cast(&nativeSetReachability)}, + //{"nativeGetWorldBoundsMeters", "(J)V", reinterpret_cast(&nativeGetWorldBoundsMeters)}, + //{"nativeGetWorldBoundsLatLng", "(J)V", reinterpret_cast(&nativeGetWorldBoundsLatLng)}, + {"nativeGetMetersPerPixelAtLatitude", "(JDD)D", reinterpret_cast(&nativeGetMetersPerPixelAtLatitude)}, + {"nativeProjectedMetersForLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Lcom/mapbox/mapboxgl/geometry/ProjectedMeters;", reinterpret_cast(&nativeProjectedMetersForLatLng)}, + {"nativeLatLngForProjectedMeters", "(JLcom/mapbox/mapboxgl/geometry/ProjectedMeters;)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeLatLngForProjectedMeters)}, + {"nativePixelForLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Landroid/graphics/PointF;", reinterpret_cast(&nativePixelForLatLng)}, + {"nativeLatLngForPixel", "(JLandroid/graphics/PointF;)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast(&nativeLatLngForPixel)}, + }}; if (env->RegisterNatives(nativeMapViewClass, methods.data(), methods.size()) < 0) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatClass = reinterpret_cast(env->NewGlobalRef(lonLatClass)); - if (lonLatClass == nullptr) { + latLngClass = reinterpret_cast(env->NewGlobalRef(latLngClass)); + if (latLngClass == nullptr) { env->ExceptionDescribe(); return JNI_ERR; } - lonLatZoomClass = reinterpret_cast(env->NewGlobalRef(lonLatZoomClass)); - if (lonLatZoomClass == nullptr) { + latLngZoomClass = reinterpret_cast(env->NewGlobalRef(latLngZoomClass)); + if (latLngZoomClass == nullptr) { env->ExceptionDescribe(); - env->DeleteGlobalRef(lonLatClass); + env->DeleteGlobalRef(latLngClass); return JNI_ERR; } runtimeExceptionClass = reinterpret_cast(env->NewGlobalRef(runtimeExceptionClass)); if (runtimeExceptionClass == nullptr) { env->ExceptionDescribe(); - env->DeleteGlobalRef(lonLatClass); - env->DeleteGlobalRef(lonLatZoomClass); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); return JNI_ERR; } @@ -960,8 +1145,8 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { reinterpret_cast(env->NewGlobalRef(nullPointerExceptionClass)); if (nullPointerExceptionClass == nullptr) { env->ExceptionDescribe(); - env->DeleteGlobalRef(lonLatClass); - env->DeleteGlobalRef(lonLatZoomClass); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(runtimeExceptionClass); return JNI_ERR; } @@ -969,13 +1154,38 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { arrayListClass = reinterpret_cast(env->NewGlobalRef(arrayListClass)); if (arrayListClass == nullptr) { env->ExceptionDescribe(); - env->DeleteGlobalRef(lonLatClass); - env->DeleteGlobalRef(lonLatZoomClass); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); env->DeleteGlobalRef(runtimeExceptionClass); env->DeleteGlobalRef(nullPointerExceptionClass); return JNI_ERR; } + projectedMetersClass = reinterpret_cast(env->NewGlobalRef(projectedMetersClass)); + if (projectedMetersClass == nullptr) { + env->ExceptionDescribe(); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(runtimeExceptionClass); + env->DeleteGlobalRef(nullPointerExceptionClass); + env->DeleteGlobalRef(arrayListClass); + return JNI_ERR; + } + + + pointFClass = reinterpret_cast(env->NewGlobalRef(pointFClass)); + if (pointFClass == nullptr) { + env->ExceptionDescribe(); + env->DeleteGlobalRef(latLngClass); + env->DeleteGlobalRef(latLngZoomClass); + env->DeleteGlobalRef(runtimeExceptionClass); + env->DeleteGlobalRef(nullPointerExceptionClass); + env->DeleteGlobalRef(arrayListClass); + env->DeleteGlobalRef(projectedMetersClass); + return JNI_ERR; + } + + char release[PROP_VALUE_MAX] = ""; __system_property_get("ro.build.version.release", release); androidRelease = std::string(release); @@ -993,18 +1203,18 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { throw new std::runtime_error("GetEnv() failed"); } - env->DeleteGlobalRef(lonLatClass); - lonLatClass = nullptr; - lonLatConstructorId = nullptr; - lonLatLonId = nullptr; - lonLatLatId = nullptr; + env->DeleteGlobalRef(latLngClass); + latLngClass = nullptr; + latLngConstructorId = nullptr; + latLngLongitudeId = nullptr; + latLngLatitudeId = nullptr; - env->DeleteGlobalRef(lonLatZoomClass); - lonLatZoomClass = nullptr; - lonLatZoomConstructorId = nullptr; - lonLatZoomLonId = nullptr; - lonLatZoomLatId = nullptr; - lonLatZoomZoomId = nullptr; + env->DeleteGlobalRef(latLngZoomClass); + latLngZoomClass = nullptr; + latLngZoomConstructorId = nullptr; + latLngZoomLongitudeId = nullptr; + latLngZoomLatitudeId = nullptr; + latLngZoomZoomId = nullptr; onMapChangedId = nullptr; onFpsChangedId = nullptr; @@ -1021,5 +1231,17 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { arrayListClass = nullptr; arrayListConstructorId = nullptr; arrayListAddId = nullptr; + + env->DeleteGlobalRef(projectedMetersClass); + projectedMetersClass = nullptr; + projectedMetersConstructorId = nullptr; + projectedMetersNorthingId = nullptr; + projectedMetersEastingId = nullptr; + + env->DeleteGlobalRef(pointFClass); + pointFClass = nullptr; + pointFConstructorId = nullptr; + pointFXId = nullptr; + pointFYId = nullptr; } } diff --git a/android/java/MapboxGLAndroidSDK/build.gradle b/android/java/MapboxGLAndroidSDK/build.gradle index ebfe98cd837..192bc2bd7a3 100644 --- a/android/java/MapboxGLAndroidSDK/build.gradle +++ b/android/java/MapboxGLAndroidSDK/build.gradle @@ -54,7 +54,8 @@ android { lintOptions { checkAllWarnings true - disable 'IconMissingDensityFolder' + warningsAsErrors true + disable 'InvalidPackage' } buildTypes { @@ -83,8 +84,7 @@ android.libraryVariants.all { variant -> failOnError = false destinationDir = new File(destinationDir, variant.baseName) source = files(variant.javaCompile.source) - ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar" - classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar) + classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath) options.links("http://docs.oracle.com/javase/7/docs/api/") options.links("http://d.android.com/reference/") exclude '**/R.html', '**/R.*.html' @@ -234,9 +234,8 @@ afterEvaluate { project -> } task androidJavadocs(type: Javadoc) { - failOnError false source = android.sourceSets.main.java.sourceFiles - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + classpath = files(android.bootClasspath) } task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { diff --git a/android/java/MapboxGLAndroidSDK/lint.xml b/android/java/MapboxGLAndroidSDK/lint.xml index 309f4e478b1..3a244199a77 100644 --- a/android/java/MapboxGLAndroidSDK/lint.xml +++ b/android/java/MapboxGLAndroidSDK/lint.xml @@ -1,3 +1,7 @@ + + + + diff --git a/android/java/MapboxGLAndroidSDK/src/main/AndroidManifest.xml b/android/java/MapboxGLAndroidSDK/src/main/AndroidManifest.xml index 7c7dac9a011..dea0f1e7632 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/AndroidManifest.xml +++ b/android/java/MapboxGLAndroidSDK/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.mapbox.mapboxgl.views"> diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/constants/GeoConstants.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/constants/GeoConstants.java similarity index 82% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/constants/GeoConstants.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/constants/GeoConstants.java index d7f674d7b19..4c899d2d8b5 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/constants/GeoConstants.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/constants/GeoConstants.java @@ -1,6 +1,6 @@ -package com.mapbox.mapboxgl.lib.constants; +package com.mapbox.mapboxgl.constants; -public interface GeoConstants { +public class GeoConstants { // http://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius public static final int RADIUS_EARTH_METERS = 6378137; public static final double MIN_LATITUDE = -85.05112878; diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/constants/MathConstants.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/constants/MathConstants.java new file mode 100644 index 00000000000..71e235c9183 --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/constants/MathConstants.java @@ -0,0 +1,8 @@ +package com.mapbox.mapboxgl.constants; + +public class MathConstants { + public static final double DEG2RAD = (Math.PI / 180.0); + public static final double RAD2DEG = (180.0 / Math.PI); + + public static final double PI = Math.PI; +} diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/BoundingBox.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/BoundingBox.java similarity index 99% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/BoundingBox.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/BoundingBox.java index 3a8141e3c33..cb0409d3e9a 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/BoundingBox.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/BoundingBox.java @@ -1,7 +1,8 @@ -package com.mapbox.mapboxgl.lib.geometry; +package com.mapbox.mapboxgl.geometry; import android.os.Parcel; import android.os.Parcelable; + import java.io.Serializable; import java.util.List; @@ -10,8 +11,6 @@ */ public final class BoundingBox implements Parcelable, Serializable { - static final long serialVersionUID = 2L; - private final double mLatNorth; private final double mLatSouth; private final double mLonEast; diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/CoordinateRegion.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/CoordinateRegion.java similarity index 65% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/CoordinateRegion.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/CoordinateRegion.java index 1d2409b464e..c7f63e7902e 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/CoordinateRegion.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/CoordinateRegion.java @@ -1,4 +1,4 @@ -package com.mapbox.mapboxgl.lib.geometry; +package com.mapbox.mapboxgl.geometry; /** * Implementation of iOS MKCoordinateRegion @@ -7,7 +7,7 @@ public class CoordinateRegion { private LatLng center; private CoordinateSpan span; - public CoordinateRegion(LatLng center, CoordinateSpan span) { + public CoordinateRegion(final LatLng center, final CoordinateSpan span) { this.center = center; this.span = span; } @@ -16,7 +16,7 @@ public LatLng getCenter() { return center; } - public void setCenter(LatLng center) { + public void setCenter(final LatLng center) { this.center = center; } @@ -24,7 +24,7 @@ public CoordinateSpan getSpan() { return span; } - public void setSpan(CoordinateSpan span) { + public void setSpan(final CoordinateSpan span) { this.span = span; } } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/CoordinateSpan.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/CoordinateSpan.java similarity index 62% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/CoordinateSpan.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/CoordinateSpan.java index 4fa239f664d..b673f83f724 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/CoordinateSpan.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/CoordinateSpan.java @@ -1,14 +1,14 @@ -package com.mapbox.mapboxgl.lib.geometry; +package com.mapbox.mapboxgl.geometry; /** * Implementation of iOS MKCoordinateSpan */ -public final class CoordinateSpan { +public class CoordinateSpan { private double latitudeSpan; private double longitudeSpan; - public CoordinateSpan(double latitudeSpan, double longitudeSpan) { + public CoordinateSpan(final double latitudeSpan, final double longitudeSpan) { this.latitudeSpan = latitudeSpan; this.longitudeSpan = longitudeSpan; } @@ -17,7 +17,7 @@ public double getLatitudeSpan() { return latitudeSpan; } - public void setLatitudeSpan(double latitudeSpan) { + public void setLatitudeSpan(final double latitudeSpan) { this.latitudeSpan = latitudeSpan; } @@ -25,7 +25,7 @@ public double getLongitudeSpan() { return longitudeSpan; } - public void setLongitudeSpan(double longitudeSpan) { + public void setLongitudeSpan(final double longitudeSpan) { this.longitudeSpan = longitudeSpan; } } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/ILatLng.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/ILatLng.java similarity index 78% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/ILatLng.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/ILatLng.java index c22a8ae3969..620676d83be 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/ILatLng.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/ILatLng.java @@ -1,4 +1,4 @@ -package com.mapbox.mapboxgl.lib.geometry; +package com.mapbox.mapboxgl.geometry; /** * A Latitude, Longitude point. diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/IProjectedMeters.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/IProjectedMeters.java new file mode 100644 index 00000000000..99f4fdec3ba --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/IProjectedMeters.java @@ -0,0 +1,7 @@ +package com.mapbox.mapboxgl.geometry; + +public interface IProjectedMeters { + double getNorthing(); + + double getEasting(); +} diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/LatLng.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/LatLng.java similarity index 63% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/LatLng.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/LatLng.java index 89c51f2da39..9b0991b0820 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/geometry/LatLng.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/LatLng.java @@ -1,13 +1,15 @@ -package com.mapbox.mapboxgl.lib.geometry; +package com.mapbox.mapboxgl.geometry; import android.location.Location; import android.os.Parcel; import android.os.Parcelable; -import com.mapbox.mapboxgl.lib.constants.GeoConstants; -import com.mapbox.mapboxgl.lib.constants.MathConstants; + +import com.mapbox.mapboxgl.constants.GeoConstants; +import com.mapbox.mapboxgl.constants.MathConstants; + import java.io.Serializable; -public class LatLng implements ILatLng, GeoConstants, MathConstants, Parcelable, Serializable { +public class LatLng implements ILatLng, Parcelable, Serializable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public LatLng createFromParcel(Parcel in) { @@ -19,14 +21,14 @@ public LatLng[] newArray(int size) { } }; - private double longitude; private double latitude; - private double altitude = 0f; + private double longitude; + private double altitude = 0.0; /** * Construct a new latitude, longitude point given float arguments * @param latitude Latitude in degrees - * @param longitude Longitude in degress + * @param longitude Longitude in degrees */ public LatLng(double latitude, double longitude) { this.latitude = latitude; @@ -39,7 +41,7 @@ public LatLng(double latitude, double longitude) { * @param longitude Longitude in degress * @param altitude Altitude in meters */ - public LatLng(final double latitude, final double longitude, final double altitude) { + public LatLng(double latitude, double longitude, double altitude) { this.latitude = latitude; this.longitude = longitude; this.altitude = altitude; @@ -49,7 +51,7 @@ public LatLng(final double latitude, final double longitude, final double altitu * Transform a Location into a LatLng point * @param location Android Location */ - public LatLng(final Location location) { + public LatLng(Location location) { this(location.getLatitude(), location.getLongitude(), location.getAltitude()); } @@ -57,15 +59,15 @@ public LatLng(final Location location) { * Clone an existing latitude longitude point * @param aLatLng LatLng */ - public LatLng(final LatLng aLatLng) { + public LatLng(LatLng aLatLng) { this.latitude = aLatLng.latitude; this.longitude = aLatLng.longitude; this.altitude = aLatLng.altitude; } protected LatLng(Parcel in) { - longitude = in.readDouble(); latitude = in.readDouble(); + longitude = in.readDouble(); altitude = in.readDouble(); } @@ -85,30 +87,46 @@ public double getAltitude() { } @Override - public boolean equals(final Object obj) { - if (obj == null) { + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { return false; } - if (obj == this) { - return true; + + LatLng latLng = (LatLng) o; + + if (Double.compare(latLng.altitude, altitude) != 0) { + return false; } - if (!obj.getClass().equals(this.getClass())) { + + if (Double.compare(latLng.latitude, latitude) != 0) { return false; } - final LatLng rhs = (LatLng) obj; - return rhs.latitude == this.latitude - && rhs.longitude == this.longitude - && rhs.altitude == this.altitude; + if (Double.compare(latLng.longitude, longitude) != 0) { + return false; + } + + return true; } @Override public int hashCode() { - return (int) (37.0 * (17.0 * latitude * 1E6d + longitude * 1E6d) + altitude); + int result; + long temp; + temp = Double.doubleToLongBits(latitude); + result = (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(longitude); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(altitude); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; } @Override public String toString() { - return "LatLng [longitude=" + longitude + ", latitude=" + latitude + "]"; + return "LatLng [longitude=" + longitude + ", latitude=" + latitude + ", altitude=" + altitude + "]"; } @Override @@ -118,8 +136,8 @@ public int describeContents() { @Override public void writeToParcel(Parcel out, int flags) { - out.writeDouble(longitude); out.writeDouble(latitude); + out.writeDouble(longitude); out.writeDouble(altitude); } @@ -128,12 +146,12 @@ public void writeToParcel(Parcel out, int flags) { * @param other Other LatLng to compare to * @return distance in meters */ - public int distanceTo(final LatLng other) { + public double distanceTo(LatLng other) { - final double a1 = DEG2RAD * this.latitude; - final double a2 = DEG2RAD * this.longitude; - final double b1 = DEG2RAD * other.getLatitude(); - final double b2 = DEG2RAD * other.getLongitude(); + final double a1 = MathConstants.DEG2RAD * this.latitude; + final double a2 = MathConstants.DEG2RAD * this.longitude; + final double b1 = MathConstants.DEG2RAD * other.getLatitude(); + final double b2 = MathConstants.DEG2RAD * other.getLongitude(); final double cosa1 = Math.cos(a1); final double cosb1 = Math.cos(b1); @@ -143,6 +161,6 @@ public int distanceTo(final LatLng other) { final double t3 = Math.sin(a1) * Math.sin(b1); final double tt = Math.acos(t1 + t2 + t3); - return (int) (RADIUS_EARTH_METERS * tt); + return GeoConstants.RADIUS_EARTH_METERS * tt; } } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/LatLngZoom.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/LatLngZoom.java similarity index 59% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/LatLngZoom.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/LatLngZoom.java index 5cbb48d366c..f1d2862b24a 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/LatLngZoom.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/LatLngZoom.java @@ -1,10 +1,11 @@ -package com.mapbox.mapboxgl.lib; +package com.mapbox.mapboxgl.geometry; import android.os.Parcel; import android.os.Parcelable; -import com.mapbox.mapboxgl.lib.geometry.LatLng; -public class LatLngZoom extends LatLng implements Parcelable { +import java.io.Serializable; + +public class LatLngZoom extends LatLng implements Parcelable, Serializable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public LatLngZoom createFromParcel(Parcel in) { @@ -18,8 +19,8 @@ public LatLngZoom[] newArray(int size) { private double zoom; - public LatLngZoom(double lat, double lon, double zoom) { - super(lat, lon); + public LatLngZoom(double latitude, double longitude, double zoom) { + super(latitude, longitude); this.zoom = zoom; } @@ -42,33 +43,38 @@ public void setZoom(double zoom) { } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = super.hashCode(); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { + public boolean equals(Object o) { + if (this == o) { return true; } - if (obj == null) { + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { return false; } - if (getClass() != obj.getClass()) { + + LatLngZoom that = (LatLngZoom) o; + + if (Double.compare(that.zoom, zoom) != 0) { return false; } - LatLngZoom other = (LatLngZoom) obj; - return super.equals(obj) && Double.doubleToLongBits(zoom) == Double.doubleToLongBits(other.zoom); + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + long temp; + temp = Double.doubleToLongBits(zoom); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; } @Override public String toString() { - return "LatLngZoom [lat=" + super.getLatitude() + ", lon=" + super.getLongitude() + ", zoom=" + zoom + "]"; + return "LatLngZoom [latitude=" + super.getLatitude() + ", longitude=" + super.getLongitude() + ", altitude=" + super.getAltitude() + ", zoom=" + zoom + "]"; } @Override diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/ProjectedMeters.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/ProjectedMeters.java new file mode 100644 index 00000000000..d28d8688761 --- /dev/null +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/geometry/ProjectedMeters.java @@ -0,0 +1,95 @@ +package com.mapbox.mapboxgl.geometry; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.Serializable; + +public class ProjectedMeters implements IProjectedMeters, Parcelable, Serializable { + + public static final Creator CREATOR = new Creator() { + public ProjectedMeters createFromParcel(Parcel in) { + return new ProjectedMeters(in); + } + + public ProjectedMeters[] newArray(int size) { + return new ProjectedMeters[size]; + } + }; + + private double northing; + private double easting; + + public ProjectedMeters(double northing, double easting) { + this.northing = northing; + this.easting = easting; + } + + public ProjectedMeters(ProjectedMeters aProjectedMeters) { + this.northing = aProjectedMeters.northing; + this.easting = aProjectedMeters.easting; + } + + protected ProjectedMeters(Parcel in) { + northing = in.readDouble(); + easting = in.readDouble(); + } + + @Override + public double getNorthing() { + return northing; + } + + @Override + public double getEasting() { + return easting; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ProjectedMeters projectedMeters = (ProjectedMeters) o; + + if (Double.compare(projectedMeters.easting, easting) != 0) { + return false; + } + if (Double.compare(projectedMeters.northing, northing) != 0) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result; + long temp; + temp = Double.doubleToLongBits(easting); + result = (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(northing); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public String toString() { + return "ProjectedMeters [northing=" + northing + ", easting=" + easting + "]"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeDouble(northing); + out.writeDouble(easting); + } +} diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/constants/MathConstants.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/constants/MathConstants.java deleted file mode 100644 index 3e4a3dea550..00000000000 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/constants/MathConstants.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.mapbox.mapboxgl.lib.constants; - -public interface MathConstants { - public static final float DEG2RAD = (float) (Math.PI / 180.0); - public static final float RAD2DEG = (float) (180.0 / Math.PI); - - public static final float PI = (float) Math.PI; -} diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java similarity index 96% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/MapView.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index 4eeda79e802..f865f9144a8 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -1,4 +1,4 @@ -package com.mapbox.mapboxgl.lib; +package com.mapbox.mapboxgl.views; import android.annotation.TargetApi; import android.content.BroadcastReceiver; @@ -18,7 +18,6 @@ import android.view.GestureDetector; import android.view.ScaleGestureDetector; import android.util.AttributeSet; -import android.util.Log; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; @@ -30,7 +29,8 @@ import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector; import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector; -import com.mapbox.mapboxgl.lib.geometry.LatLng; +import com.mapbox.mapboxgl.geometry.LatLng; +import com.mapbox.mapboxgl.geometry.LatLngZoom; import org.apache.commons.validator.routines.UrlValidator; @@ -45,9 +45,6 @@ public class MapView extends SurfaceView { // Static members // - // Tag used for logging - private static final String TAG = "MapView"; - // Used for animation private static final long ANIMATION_DURATION = 300; @@ -129,14 +126,12 @@ public MapView(Context context, AttributeSet attrs, int defStyle) { // Common initialization code goes here private void initialize(Context context, AttributeSet attrs) { - Log.v(TAG, "initialize"); // Save the context mContext = context; // Check if we are in Eclipse UI editor if (isInEditMode()) { - // TODO editor does not load properly because we don't implement this return; } @@ -352,10 +347,6 @@ public String getAccessToken() { return mNativeMapView.getAccessToken(); } - // - // Style methods - // - public List getClasses() { return mNativeMapView.getClasses(); } @@ -387,10 +378,18 @@ public void removeAllClasses() { public void removeAllClasses(long transitionDuration) { mNativeMapView.setDefaultTransitionDuration(transitionDuration); - ArrayList classes = new ArrayList(0); + ArrayList classes = new ArrayList<>(0); setClasses(classes); } + public LatLng fromScreenLocation(PointF point) { + return mNativeMapView.latLngForPixel(point); + } + + public PointF toScreenLocation(LatLng location) { + return mNativeMapView.pixelForLatLng(location); + } + // // Lifecycle events // @@ -398,7 +397,6 @@ public void removeAllClasses(long transitionDuration) { // Called when we need to restore instance state // Must be called from Activity onCreate public void onCreate(Bundle savedInstanceState) { - Log.v(TAG, "onCreate"); if (savedInstanceState != null) { setCenterCoordinate((LatLng) savedInstanceState.getParcelable(STATE_CENTER_COORDINATE)); setZoomLevel(savedInstanceState.getDouble(STATE_ZOOM_LEVEL)); // need to set zoom level first because of limitation on rotating when zoomed out @@ -427,7 +425,6 @@ public void onCreate(Bundle savedInstanceState) { // Called when we need to save instance state // Must be called from Activity onSaveInstanceState public void onSaveInstanceState(Bundle outState) { - Log.v(TAG, "onSaveInstanceState"); outState.putParcelable(STATE_CENTER_COORDINATE, getCenterCoordinate()); outState.putDouble(STATE_ZOOM_LEVEL, getZoomLevel()); // need to set zoom level first because of limitation on rotating when zoomed out outState.putDouble(STATE_CENTER_DIRECTION, getDirection()); @@ -437,14 +434,13 @@ public void onSaveInstanceState(Bundle outState) { outState.putBoolean(STATE_DEBUG_ACTIVE, isDebugActive()); outState.putString(STATE_STYLE_URL, mStyleUrl); outState.putString(STATE_ACCESS_TOKEN, getAccessToken()); - outState.putStringArrayList(STATE_CLASSES, new ArrayList(getClasses())); + outState.putStringArrayList(STATE_CLASSES, new ArrayList<>(getClasses())); outState.putLong(STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration()); } // Called when we need to clean up // Must be called from Activity onDestroy public void onDestroy() { - Log.v(TAG, "onDestroy"); mNativeMapView.stop(); mNativeMapView.terminateContext(); mNativeMapView.terminateDisplay(); @@ -453,21 +449,17 @@ public void onDestroy() { // Called when we need to create the GL context // Must be called from Activity onStart public void onStart() { - Log.v(TAG, "onStart"); + // Do nothing } // Called when we need to terminate the GL context // Must be called from Activity onPause public void onStop() { - Log.v(TAG, "onStop"); - //mNativeMapView.stop(); } // Called when we need to stop the render thread // Must be called from Activity onPause public void onPause() { - Log.v(TAG, "onPause"); - // Register for connectivity changes getContext().unregisterReceiver(mConnectivityReceiver); mConnectivityReceiver = null; @@ -479,8 +471,6 @@ public void onPause() { // Must be called from Activity onResume public void onResume() { - Log.v(TAG, "onResume"); - // Register for connectivity changes mConnectivityReceiver = new ConnectivityReceiver(); mContext.registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); @@ -495,7 +485,6 @@ private class Callbacks implements SurfaceHolder.Callback { // Must do all EGL/GL ES initialization here @Override public void surfaceCreated(SurfaceHolder holder) { - Log.v(TAG, "surfaceCreated"); mNativeMapView.createSurface(holder.getSurface()); } @@ -503,7 +492,6 @@ public void surfaceCreated(SurfaceHolder holder) { // Must do all EGL/GL ES destruction here @Override public void surfaceDestroyed(SurfaceHolder holder) { - Log.v(TAG, "surfaceDestroyed"); mNativeMapView.destroySurface(); } @@ -513,8 +501,6 @@ public void surfaceDestroyed(SurfaceHolder holder) { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - Log.v(TAG, "surfaceChanged"); - Log.i(TAG, "resize " + format + " " + width + " " + height); mNativeMapView.resize((int) (width / mScreenDensity), (int) (height / mScreenDensity), mScreenDensity, width, height); } } @@ -527,13 +513,10 @@ private class Callbacks2 extends Callbacks implements SurfaceHolder.Callback2 { // flicker (see Android SDK documentation) @Override public void surfaceRedrawNeeded(SurfaceHolder holder) { - Log.v(TAG, "surfaceRedrawNeeded"); mNativeMapView.update(); } } - // TODO examine how GLSurvaceView hadles attach/detach from window - // Called when view is no longer connected @Override protected void onDetachedFromWindow() { @@ -561,10 +544,6 @@ protected void onVisibilityChanged(@NonNull View changedView, int visibility) { // Draw events // - // TODO: onDraw for UI editor mockup? - // By default it just shows a gray screen with "MapView" - // Not too important but perhaps we could put a static demo map image there - // // Input events // @@ -590,7 +569,7 @@ private void zoom(boolean zoomIn, float x, float y) { @Override @TargetApi(14) public boolean onTouchEvent(@NonNull MotionEvent event) { // Check and ignore non touch or left clicks - if ((android.os.Build.VERSION.SDK_INT >= 14) && (event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) { + if ((android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) && (event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) { return false; } @@ -783,7 +762,7 @@ public boolean onScale(ScaleGestureDetector detector) { return false; } - // TODO complex decision between roate or scale or both (see Google + // TODO complex decision between rotate or scale or both (see Google // Maps app) // Cancel any animation @@ -1012,7 +991,6 @@ public boolean onKeyUp(int keyCode, KeyEvent event) { // Called for trackball events, all motions are relative in device specific // units - // TODO: test trackball click and long click @Override public boolean onTrackballEvent(MotionEvent event) { // Choose the action @@ -1106,8 +1084,6 @@ public void run() { @Override @TargetApi(12) public boolean onGenericMotionEvent(MotionEvent event) { // Mouse events - // TODO: SOURCE_TOUCH_NAVIGATION? - // TODO: source device resolution? //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) { // Choose the action @@ -1174,7 +1150,6 @@ public class ConnectivityReceiver extends BroadcastReceiver { // Called when an action we are listening to in the manifest has been sent @Override public void onReceive(Context context, Intent intent) { - Log.v(TAG, "ConnectivityReceiver.onReceive: action = " + intent.getAction()); if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); onConnectivityChanged(!noConnectivity); @@ -1184,7 +1159,6 @@ public void onReceive(Context context, Intent intent) { // Called when our Internet connectivity has changed private void onConnectivityChanged(boolean isConnected) { - Log.v(TAG, "onConnectivityChanged: " + isConnected); mNativeMapView.setReachability(isConnected); } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/NativeMapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java similarity index 86% rename from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/NativeMapView.java rename to android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java index 17a95fa3247..ffb439737e2 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/lib/NativeMapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java @@ -1,8 +1,11 @@ -package com.mapbox.mapboxgl.lib; +package com.mapbox.mapboxgl.views; +import android.graphics.PointF; import android.view.Surface; -import com.mapbox.mapboxgl.lib.geometry.LatLng; +import com.mapbox.mapboxgl.geometry.LatLng; +import com.mapbox.mapboxgl.geometry.LatLngZoom; +import com.mapbox.mapboxgl.geometry.ProjectedMeters; import java.util.List; @@ -13,9 +16,6 @@ class NativeMapView { // Static members // - // Tag used for logging - private static final String TAG = "NativeMapView"; - // // Instance members // @@ -248,11 +248,11 @@ public void setLatLng(LatLng latLng) { } public void setLatLng(LatLng latLng, long duration) { - nativeSetLonLat(mNativeMapViewPtr, latLng, duration); + nativeSetLatLng(mNativeMapViewPtr, latLng, duration); } public LatLng getLatLng() { - return nativeGetLonLat(mNativeMapViewPtr); + return nativeGetLatLng(mNativeMapViewPtr); } public void startPanning() { @@ -307,16 +307,16 @@ public double getZoom() { return nativeGetZoom(mNativeMapViewPtr); } - public void setLatLngZoom(LatLngZoom lonLatZoom) { - setLatLngZoom(lonLatZoom, 0); + public void setLatLngZoom(LatLngZoom latLngZoom) { + setLatLngZoom(latLngZoom, 0); } - public void setLatLngZoom(LatLngZoom lonLatZoom, long duration) { - nativeSetLonLatZoom(mNativeMapViewPtr, lonLatZoom, duration); + public void setLatLngZoom(LatLngZoom latLngZoom, long duration) { + nativeSetLatLngZoom(mNativeMapViewPtr, latLngZoom, duration); } public LatLngZoom getLatLngZoom() { - return nativeGetLonLatZoom(mNativeMapViewPtr); + return nativeGetLatLngZoom(mNativeMapViewPtr); } public void resetZoom() { @@ -392,6 +392,30 @@ public void setReachability(boolean status) { nativeSetReachability(mNativeMapViewPtr, status); } + //public void getWorldBoundsMeters(); + + //public void getWorldBoundsLatLng(); + + public double getMetersPerPixelAtLatitude(double lat, double zoom) { + return nativeGetMetersPerPixelAtLatitude(mNativeMapViewPtr, lat, zoom); + } + + public ProjectedMeters projectedMetersForLatLng(LatLng latLng) { + return nativeProjectedMetersForLatLng(mNativeMapViewPtr, latLng); + } + + public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) { + return nativeLatLngForProjectedMeters(mNativeMapViewPtr, projectedMeters); + } + + public PointF pixelForLatLng(LatLng latLng) { + return nativePixelForLatLng(mNativeMapViewPtr, latLng); + } + + public LatLng latLngForPixel(PointF pixel) { + return nativeLatLngForPixel(mNativeMapViewPtr, pixel); + } + // // Callbacks // @@ -490,10 +514,10 @@ private native void nativeSetStyleJson(long nativeMapViewPtr, private native void nativeMoveBy(long nativeMapViewPtr, double dx, double dy, long duration); - private native void nativeSetLonLat(long nativeMapViewPtr, LatLng latLng, + private native void nativeSetLatLng(long nativeMapViewPtr, LatLng latLng, long duration); - private native LatLng nativeGetLonLat(long nativeMapViewPtr); + private native LatLng nativeGetLatLng(long nativeMapViewPtr); private native void nativeStartPanning(long nativeMapViewPtr); @@ -514,10 +538,10 @@ private native void nativeSetZoom(long nativeMapViewPtr, double zoom, private native double nativeGetZoom(long nativeMapViewPtr); - private native void nativeSetLonLatZoom(long nativeMapViewPtr, + private native void nativeSetLatLngZoom(long nativeMapViewPtr, LatLngZoom lonLatZoom, long duration); - private native LatLngZoom nativeGetLonLatZoom(long nativeMapViewPtr); + private native LatLngZoom nativeGetLatLngZoom(long nativeMapViewPtr); private native void nativeResetZoom(long nativeMapViewPtr); @@ -553,4 +577,18 @@ private native void nativeSetBearing(long nativeMapViewPtr, double degrees, private native boolean nativeGetDebug(long nativeMapViewPtr); private native void nativeSetReachability(long nativeMapViewPtr, boolean status); + + //private native void nativeGetWorldBoundsMeters(long nativeMapViewPtr); + + //private native void nativeGetWorldBoundsLatLng(long nativeMapViewPtr); + + private native double nativeGetMetersPerPixelAtLatitude(long nativeMapViewPtr, double lat, double zoom); + + private native ProjectedMeters nativeProjectedMetersForLatLng(long nativeMapViewPtr, LatLng latLng); + + private native LatLng nativeLatLngForProjectedMeters(long nativeMapViewPtr, ProjectedMeters projectedMeters); + + private native PointF nativePixelForLatLng(long nativeMapViewPtr, LatLng latLng); + + private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, PointF pixel); } diff --git a/android/java/MapboxGLAndroidSDKTestApp/build.gradle b/android/java/MapboxGLAndroidSDKTestApp/build.gradle index 9a1f323ef1d..1aac4988701 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/build.gradle +++ b/android/java/MapboxGLAndroidSDKTestApp/build.gradle @@ -38,8 +38,8 @@ android { } defaultConfig { - applicationId "com.mapbox.mapboxgl.app" - minSdkVersion 14 + applicationId "com.mapbox.mapboxgl.testapp" + minSdkVersion 8 targetSdkVersion 21 versionCode 4 versionName "0.1.3" @@ -57,9 +57,9 @@ android { lintOptions { checkAllWarnings true - disable 'UnusedAttribute' - abortOnError false - //disable 'IconDensities' + warningsAsErrors true + disable 'IconDensities' + disable 'InvalidPackage' } buildTypes { @@ -77,7 +77,7 @@ dependencies { compile 'com.android.support:support-annotations:21.0.0' compile 'com.android.support:support-v4:21.0.3' compile 'com.android.support:appcompat-v7:21.0.3' - compile 'com.mapzen.android:lost:0.2' + compile 'com.mapzen.android:lost:1.0.0' } checkstyle { diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index deee959d770..901a63f5720 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ - + @@ -10,9 +10,10 @@ android:icon="@drawable/icon_burned" android:label="@string/app_name" android:theme="@style/AppTheme" + tools:ignore="UnusedAttribute" android:supportsRtl="true"> diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/app/MainActivity.java b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java similarity index 51% rename from android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/app/MainActivity.java rename to android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java index a933d5cd139..bd7100d98d8 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/app/MainActivity.java +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MainActivity.java @@ -1,24 +1,35 @@ -package com.mapbox.mapboxgl.app; - +package com.mapbox.mapboxgl.testapp; + +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.PointF; +import android.hardware.GeomagneticField; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; import android.location.Location; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; -import com.mapbox.mapboxgl.lib.LatLngZoom; -import com.mapbox.mapboxgl.lib.MapView; -import com.mapzen.android.lost.LocationClient; -import com.mapzen.android.lost.LocationListener; -import com.mapzen.android.lost.LocationRequest; + +import com.mapbox.mapboxgl.geometry.LatLng; +import com.mapbox.mapboxgl.views.MapView; +import com.mapzen.android.lost.api.LocationListener; +import com.mapzen.android.lost.api.LocationRequest; +import com.mapzen.android.lost.api.LocationServices; +import com.mapzen.android.lost.api.LostApiClient; + import java.util.ArrayList; public class MainActivity extends ActionBarActivity { @@ -27,36 +38,44 @@ public class MainActivity extends ActionBarActivity { // Static members // - // Tag used for logging - private static final String TAG = "MainActivity"; - - // Rotation State - private static final String IS_GPS_ON = "isGPSOn"; + // Used for saving instance state + private static final String STATE_IS_GPS_ON = "isGpsOn"; // // Instance members // - // Holds the MapFragment + // Used for the UI private MapFragment mMapFragment; - - // The FPS label private TextView mFpsTextView; - - // The compass private ImageView mCompassView; + private FrameLayout mMapFrameLayout; + private float mDensity; + private Spinner mClassSpinner; + private ArrayAdapter mOutdoorsClassAdapter; + private ArrayAdapter mSatelliteClassAdapter; // Used for GPS private boolean mIsGpsOn = false; - private LocationClient mLocationClient; - private LocationListener mLocationListener; + private LostApiClient mLocationClient; + private GpsListener mGpsListener; private LocationRequest mLocationRequest; - private MenuItem gpsMenuItem = null; - - // Used for the class spinner - Spinner mClassSpinner; - ArrayAdapter mOutdoorsClassAdapter; - ArrayAdapter mSatelliteClassAdapter; + private ImageView mGpsMarker; + private Location mGpsLocation; + private MenuItem mGpsMenuItem; + + // Used for compass + private SensorManager mSensorManager; + private Sensor mSensorAccelerometer; + private Sensor mSensorMagneticField; + private CompassListener mCompassListener; + private float[] mValuesAccelerometer = new float[3]; + private float[] mValuesMagneticField = new float[3]; + private float[] mMatrixR = new float[9]; + private float[] mMatrixI = new float[9]; + private float[] mMatrixValues = new float[3]; + private float mCompassBearing; + private boolean mCompassValid = false; // // Lifecycle events @@ -66,7 +85,12 @@ public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Log.v(TAG, "onCreate"); + + if (savedInstanceState != null) { + mIsGpsOn = savedInstanceState.getBoolean(STATE_IS_GPS_ON, false); + } + + mDensity = getResources().getDisplayMetrics().density; // Load the layout setContentView(R.layout.activity_main); @@ -80,6 +104,14 @@ protected void onCreate(Bundle savedInstanceState) { mCompassView = (ImageView) findViewById(R.id.view_compass); mCompassView.setOnClickListener(new CompassOnClickListener()); + mGpsMarker = new ImageView(getApplicationContext()); + mGpsMarker.setVisibility(View.INVISIBLE); + mGpsMarker.setImageResource(R.drawable.location_marker); + mGpsMarker.setLayoutParams(new FrameLayout.LayoutParams((int) (27.0f * mDensity), (int) (27.0f * mDensity))); + mGpsMarker.requestLayout(); + + mMapFrameLayout = (FrameLayout) findViewById(R.id.layout_map); + mMapFrameLayout.addView(mGpsMarker); // Add a toolbar as the action bar Toolbar mainToolbar = (Toolbar) findViewById(R.id.toolbar_main); setSupportActionBar(mainToolbar); @@ -100,72 +132,45 @@ protected void onCreate(Bundle savedInstanceState) { R.array.satellite_class_list, android.R.layout.simple_spinner_dropdown_item); // Prepare for GPS - mLocationRequest = LocationRequest.create(); - mLocationRequest.setInterval(0); - mLocationRequest.setSmallestDisplacement(0); - - mLocationClient = new LocationClient(getApplicationContext(), new LocationClient.ConnectionCallbacks() { - @Override - public void onConnected(Bundle connectionHint) { - updateLocation(mLocationClient.getLastLocation()); - - mLocationListener = new LocationListener() { - @Override - public void onLocationChanged(Location location) { - //Toast.makeText(getApplicationContext(), "Location: " + location.toString(), Toast.LENGTH_SHORT).show(); - updateLocation(location); - } - }; - - mLocationClient.requestLocationUpdates(mLocationRequest, mLocationListener); - } - - @Override - public void onDisconnected() { - mLocationListener = null; - } - }); - - if (savedInstanceState != null) { - // Restore any state that the app saved - mIsGpsOn = savedInstanceState.getBoolean(IS_GPS_ON); - } + mLocationClient = new LostApiClient.Builder(this).build(); + mLocationRequest = LocationRequest.create() + .setInterval(1000) + .setSmallestDisplacement(1) + .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); + mGpsListener = new GpsListener(); + + mSensorManager = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE); + mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + mCompassListener = new CompassListener(); } // Called when our app goes into the background @Override public void onPause() { super.onPause(); - Log.v(TAG, "onPause"); // Cancel GPS - if (mIsGpsOn) { - mLocationClient.disconnect(); - } + toggleGps(false); } // Called when our app comes into the foreground @Override public void onResume() { super.onResume(); - Log.v(TAG, "onResume"); - // Restart GPS - // Cancel any outstanding GPS - if (mIsGpsOn) { - mLocationClient.connect(); - } + toggleGps(true); } + // Called when we need to save instance state @Override protected void onSaveInstanceState(Bundle outState) { - - // Persist any state the app needs to retain - outState.putBoolean(IS_GPS_ON, mIsGpsOn); - super.onSaveInstanceState(outState); + + outState.putBoolean(STATE_IS_GPS_ON, mIsGpsOn); } + // // Other events // @@ -175,10 +180,12 @@ protected void onSaveInstanceState(Bundle outState) { public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_main, menu); - gpsMenuItem = menu.findItem(R.id.action_gps); - - // Set Menu UI to match state (ie, from restore) - toggleGPS(mIsGpsOn); + mGpsMenuItem = menu.findItem(R.id.action_gps); + if (mIsGpsOn) { + mGpsMenuItem.setIcon(R.drawable.ic_action_location_found); + } else { + mGpsMenuItem.setIcon(R.drawable.ic_action_location_searching); + } return super.onCreateOptionsMenu(menu); } @@ -187,7 +194,9 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_gps: - toggleGPS(!mIsGpsOn); + // Toggle GPS position updates + toggleGps(!mIsGpsOn); + updateMap(); return true; case R.id.action_debug: @@ -209,29 +218,98 @@ public boolean onOptionsItemSelected(MenuItem item) { } /** - * Enabled / Disable GPS along with updating the UI - * @param enableGPS true if GPS is to be enabled, false if GPS is to be disabled + * Enabled / Disable GPS location updates along with updating the UI + * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled */ - private void toggleGPS(boolean enableGPS) { - - if (enableGPS) { - mIsGpsOn = true; - gpsMenuItem.setIcon(R.drawable.ic_action_location_found); - mLocationClient.connect(); - } else { - mIsGpsOn = false; - gpsMenuItem.setIcon(R.drawable.ic_action_location_searching); - mLocationClient.disconnect(); - } + private void toggleGps(boolean enableGps) { + + if (enableGps) { + if (!mIsGpsOn) { + mIsGpsOn = true; + if (mGpsMenuItem != null) { + mGpsMenuItem.setIcon(R.drawable.ic_action_location_found); + } + mGpsLocation = null; + mLocationClient.connect(); + updateLocation(LocationServices.FusedLocationApi.getLastLocation()); + LocationServices.FusedLocationApi.requestLocationUpdates(mLocationRequest, new GpsListener()); + mSensorManager.registerListener(mCompassListener, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI); + mSensorManager.registerListener(mCompassListener, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI); + } + } else { + if (mIsGpsOn) { + mIsGpsOn = false; + if (mGpsMenuItem != null) { + mGpsMenuItem.setIcon(R.drawable.ic_action_location_searching); + } + LocationServices.FusedLocationApi.removeLocationUpdates(mGpsListener); + mLocationClient.disconnect(); + mSensorManager.unregisterListener(mCompassListener, mSensorAccelerometer); + mSensorManager.unregisterListener(mCompassListener, mSensorMagneticField); + mGpsLocation = null; + } + } + } + + // This class forwards location updates to updateLocation() + private class GpsListener implements LocationListener { + + @Override + public void onLocationChanged(Location location) { + updateLocation(location); + } } + // This class handles sensor updates to calculate compass bearing + private class CompassListener implements SensorEventListener { + + @Override + public void onSensorChanged(SensorEvent event) { + switch (event.sensor.getType()) { + case Sensor.TYPE_ACCELEROMETER: + System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3); + break; + case Sensor.TYPE_MAGNETIC_FIELD: + System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3); + break; + } + + boolean valid = SensorManager.getRotationMatrix(mMatrixR, mMatrixI, + mValuesAccelerometer, + mValuesMagneticField); + + if (valid) { + SensorManager.getOrientation(mMatrixR, mMatrixValues); + //mAzimuthRadians.putValue(mMatrixValues[0]); + //mAzimuth = Math.toDegrees(mAzimuthRadians.getAverage()); + + if (mGpsLocation != null) { + GeomagneticField geomagneticField = new GeomagneticField( + (float) mGpsLocation.getLatitude(), + (float) mGpsLocation.getLongitude(), + (float) mGpsLocation.getAltitude(), + System.currentTimeMillis()); + mCompassBearing = (float) Math.toDegrees(mMatrixValues[0]) + geomagneticField.getDeclination(); + mCompassValid = true; + } + } + + updateMap(); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // TODO: ignore unreliable stuff + } + } // Handles location updates from GPS private void updateLocation(Location location) { if (location != null) { - LatLngZoom coordinate = new LatLngZoom(location.getLatitude(), location.getLongitude(), 16); - mMapFragment.getMap().setCenterCoordinate(coordinate, true); + mGpsLocation = location; } + + updateMap(); } // This class handles style change events @@ -311,7 +389,7 @@ private class OutdoorClassSpinnerListener implements AdapterView.OnItemSelectedL @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - ArrayList classes = new ArrayList(1); + ArrayList classes = new ArrayList<>(1); switch (position) { // Day @@ -343,7 +421,7 @@ private class SatelliteClassSpinnerListener implements AdapterView.OnItemSelecte @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - ArrayList classes = new ArrayList(2); + ArrayList classes = new ArrayList<>(2); switch (position) { // Labels + Contours @@ -377,7 +455,7 @@ public void onNothingSelected(AdapterView parent) { } // Called when FPS changes - public class MyOnFpsChangedListener implements MapView.OnFpsChangedListener { + private class MyOnFpsChangedListener implements MapView.OnFpsChangedListener { @Override public void onFpsChanged(double fps) { @@ -385,17 +463,58 @@ public void onFpsChanged(double fps) { } } + // Rotates an ImageView - does not work if the ImageView has padding, use margins + private void rotateImageView(ImageView imageView, float angle) { + Matrix matrix = new Matrix(); + matrix.setScale((float) imageView.getWidth() / (float) imageView.getDrawable().getIntrinsicWidth(), (float) imageView.getHeight() / (float) imageView.getDrawable().getIntrinsicHeight()); + matrix.postRotate(angle, (float) imageView.getWidth() / 2.0f, (float) imageView.getHeight() / 2.0f); + imageView.setImageMatrix(matrix); + imageView.setScaleType(ImageView.ScaleType.MATRIX); + } + + // Updates the UI to match the current map's position + private void updateMap() { + rotateImageView(mCompassView, (float) mMapFragment.getMap().getDirection()); + + if (mGpsLocation != null) { + mGpsMarker.setVisibility(View.VISIBLE); + LatLng coordinate = new LatLng(mGpsLocation); + PointF screenLocation = mMapFragment.getMap().toScreenLocation(coordinate); + + if (mGpsLocation.hasBearing() || mCompassValid) { + mGpsMarker.setImageResource(R.drawable.direction_arrow); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) (54.0f * mDensity), (int) (54.0f * mDensity)); + lp.leftMargin = (int) ((screenLocation.x - 54.0f / 2.0f) * mDensity); + lp.topMargin = mMapFrameLayout.getHeight() - (int) ((screenLocation.y + 54.0f / 2.0f) * mDensity); + mGpsMarker.setLayoutParams(lp); + float bearing = mGpsLocation.hasBearing() ? mGpsLocation.getBearing() : mCompassBearing; + rotateImageView(mGpsMarker, bearing); + mGpsMarker.requestLayout(); + } else { + mGpsMarker.setImageResource(R.drawable.location_marker); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) (27.0f * mDensity), (int) (27.0f * mDensity)); + lp.leftMargin = (int) ((screenLocation.x - 27.0f / 2.0f) * mDensity); + lp.topMargin = mMapFrameLayout.getHeight() - (int) ((screenLocation.y + 27.0f / 2.0f) * mDensity); + mGpsMarker.setLayoutParams(lp); + rotateImageView(mGpsMarker, 0.0f); + mGpsMarker.requestLayout(); + } + } else { + mGpsMarker.setVisibility(View.INVISIBLE); + } + } + // Called when map state changes - public class MyOnMapChangedListener implements MapView.OnMapChangedListener { + private class MyOnMapChangedListener implements MapView.OnMapChangedListener { @Override public void onMapChanged() { - mCompassView.setRotation((float) mMapFragment.getMap().getDirection()); + updateMap(); } } // Called when someone presses the compass - public class CompassOnClickListener implements View.OnClickListener { + private class CompassOnClickListener implements View.OnClickListener { @Override public void onClick(View view) { diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/app/MapFragment.java b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java similarity index 97% rename from android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/app/MapFragment.java rename to android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java index 0249dab293b..b78926b9e19 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/app/MapFragment.java +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxgl/testapp/MapFragment.java @@ -1,4 +1,4 @@ -package com.mapbox.mapboxgl.app; +package com.mapbox.mapboxgl.testapp; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -7,7 +7,7 @@ import android.view.View; import android.view.ViewGroup; -import com.mapbox.mapboxgl.lib.MapView; +import com.mapbox.mapboxgl.views.MapView; import java.io.BufferedReader; import java.io.IOException; diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/direction_arrow.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/direction_arrow.png new file mode 100644 index 00000000000..379ac4fb160 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/direction_arrow.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/location_marker.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/location_marker.png new file mode 100644 index 00000000000..f3a57845b74 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/location_marker.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-ldpi/direction_arrow.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-ldpi/direction_arrow.png new file mode 100644 index 00000000000..292d2c5dfad Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-ldpi/direction_arrow.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-ldpi/location_marker.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-ldpi/location_marker.png new file mode 100644 index 00000000000..94a78378178 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-ldpi/location_marker.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/direction_arrow.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/direction_arrow.png new file mode 100644 index 00000000000..c0101b8a69f Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/direction_arrow.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/location_marker.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/location_marker.png new file mode 100644 index 00000000000..d8c15638806 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/location_marker.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/direction_arrow.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/direction_arrow.png new file mode 100644 index 00000000000..5227caf44b2 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/direction_arrow.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/location_marker.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/location_marker.png new file mode 100644 index 00000000000..157c48adeaa Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/location_marker.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/direction_arrow.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/direction_arrow.png new file mode 100644 index 00000000000..760edd43904 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/direction_arrow.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/location_marker.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/location_marker.png new file mode 100644 index 00000000000..ccc56f66019 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/location_marker.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/direction_arrow.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/direction_arrow.png new file mode 100644 index 00000000000..8e3c598195e Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/direction_arrow.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/location_marker.png b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/location_marker.png new file mode 100644 index 00000000000..2318f1b7cc0 Binary files /dev/null and b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/location_marker.png differ diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml index 5376ee2d24d..6a9bf8266a7 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml @@ -24,12 +24,13 @@ + android:id="@+id/view_fps" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceLarge" + android:text="@string/label_fps" + android:layout_margin="10dp" /> diff --git a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_main.xml b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_main.xml index 311242472a0..f303a02f503 100644 --- a/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_main.xml +++ b/android/java/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_main.xml @@ -1,4 +1,4 @@ - diff --git a/android/java/build.gradle b/android/java/build.gradle index e51332720c4..9090070982c 100644 --- a/android/java/build.gradle +++ b/android/java/build.gradle @@ -2,4 +2,3 @@ task wrapper(type: Wrapper) { gradleVersion = '2.2.1' } - diff --git a/include/mbgl/android/jni.hpp b/include/mbgl/android/jni.hpp index 698c0247313..721104897d9 100644 --- a/include/mbgl/android/jni.hpp +++ b/include/mbgl/android/jni.hpp @@ -19,16 +19,16 @@ extern std::string androidRelease; extern jmethodID onMapChangedId; extern jmethodID onFpsChangedId; -extern jclass lonLatClass; -extern jmethodID lonLatConstructorId; -extern jfieldID lonLatLonId; -extern jfieldID lonLatLatId; +extern jclass latLngClass; +extern jmethodID latLngConstructorId; +extern jfieldID latLngLatitudeId; +extern jfieldID latLngLongitudeId; -extern jclass lonLatZoomClass; -extern jmethodID lonLatZoomConstructorId; -extern jfieldID lonLatZoomLonId; -extern jfieldID lonLatZoomLatId; -extern jfieldID lonLatZoomZoomId; +extern jclass latLngZoomClass; +extern jmethodID latLngZoomConstructorId; +extern jfieldID latLngZoomLatitudeId; +extern jfieldID latLngZoomLongitudeId; +extern jfieldID latLngZoomZoomId; extern jclass runtimeExceptionClass; extern jclass nullPointerExceptionClass; @@ -39,6 +39,16 @@ extern jclass arrayListClass; extern jmethodID arrayListConstructorId; extern jmethodID arrayListAddId; +extern jclass projectedMetersClass; +extern jmethodID projectedMetersConstructorId; +extern jfieldID projectedMetersNorthingId; +extern jfieldID projectedMetersEastingId; + +extern jclass pointFClass; +extern jmethodID pointFConstructorId; +extern jfieldID pointFXId; +extern jfieldID pointFYId; + } } diff --git a/styles b/styles index c1303933798..25b1b7dff37 160000 --- a/styles +++ b/styles @@ -1 +1 @@ -Subproject commit c1303933798e1bb48649d8a64b71038b4d3ed0a4 +Subproject commit 25b1b7dff37a18151e3286144bc8013b432a8860