Merge pull request #542 from ljbade/android-mason
Android mason: Get android building
This commit is contained in:
2
.mason
2
.mason
Submodule .mason updated: 4c53b0a3a6...a3ebabd0c6
@@ -23,12 +23,16 @@ env:
|
||||
- secure: "Cbvap9ubVKgjPe3hUhI6JGeDZzBXHpOG9RaYKh+SdoIPhKnlJiNOYm1egomi+e4uqJInlFKuVHTw7Ng9Cun6Zm0jIxpkSchv1GpsR7hmB3UGnGed19Dw8121FwuUaktN+4YnbVlsyd+u8EHD3+h58t4eELrLrZolM4rS7DL6caA="
|
||||
- secure: "RiBIBfVhhaMjU5ksuwJO3shdvG9FpinBjdSv4co9jg9171SR8edNriedHjVKSIeBhSGNmZmX+twS3dJS/By6tl/LKh9sTynA+ZAYYljkE7jn881B/gMrlYvdAA6og5KvkhV1/0iJWlhuZrMTkhpDR200iLgg3EWBhWjltzmDW/I="
|
||||
- LD_LIBRARY_PATH: '/usr/local/lib'
|
||||
- TERM=dumb
|
||||
|
||||
before_install:
|
||||
- source ./scripts/local_mason.sh
|
||||
- source ./scripts/travis_helper.sh
|
||||
- source ./scripts/flags.sh
|
||||
- export ANDROID_NDK_PATH="$(pwd)/android-ndk-r10c"
|
||||
- export NDK_HOME="$(pwd)/android-ndk-r10c"
|
||||
- export JAVA_HOME="$(pwd)/jdk1.7.0_71"
|
||||
- export ANDROID_HOME="$(pwd)/android-sdk-linux"
|
||||
- ./scripts/travis_before_install.sh
|
||||
- if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then export LD_LIBRARY_PATH=`mason prefix mesa 10.3.1`/lib; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then glxinfo; fi
|
||||
|
||||
11
Makefile
11
Makefile
@@ -74,6 +74,7 @@ android:
|
||||
export CXX="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env CXX`" && \
|
||||
export CC="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env CC`" && \
|
||||
export LD="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env LD`" && \
|
||||
export LINK="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env CXX`" && \
|
||||
export AR="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env AR`" && \
|
||||
export RANLIB="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env RANLIB`" && \
|
||||
export LDFLAGS="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env LDFLAGS` ${LDFLAGS}" && \
|
||||
@@ -81,8 +82,12 @@ android:
|
||||
export CPPFLAGS="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env CPPFLAGS` ${CPPFLAGS}" && \
|
||||
export PATH="`MASON_DIR=./.mason MASON_PLATFORM=android ./.mason/mason env PATH`:${PATH}" && \
|
||||
MASON_PLATFORM=android ./configure config-android.gypi && \
|
||||
deps/run_gyp mapboxgl.gyp -Iconfig-android.gypi -Dplatform=android --depth=. --generator-output=./build/android -f make-android && \
|
||||
$(MAKE) -C ./build/android BUILDTYPE=$(BUILDTYPE) V=$(V) mbgl-core
|
||||
deps/run_gyp android/mapboxgl-app.gyp -Iconfig-android.gypi -Dplatform=android --depth=. --generator-output=./build/android -f make-android && \
|
||||
$(MAKE) -C build/android BUILDTYPE=$(BUILDTYPE) V=$(V) androidapp && \
|
||||
mkdir -p android/java/lib/src/main/jniLibs/armeabi-v7a && \
|
||||
cp build/android/out/$(BUILDTYPE)/lib.target/libmapbox-gl.so android/java/lib/src/main/jniLibs/armeabi-v7a/libmapbox-gl.so && \
|
||||
cd android/java && \
|
||||
./gradlew build
|
||||
|
||||
##### Test cases ###############################################################
|
||||
|
||||
@@ -147,6 +152,8 @@ clean: clear_xcode_cache
|
||||
-rm -rf ./build/
|
||||
-rm -rf ./macosx/build/
|
||||
-rm -rf ./config.gypi ./config-ios.gypi ./config-android.gypi
|
||||
-rm -rf ./android/java/build ./android/java/app/build ./android/java/lib/build
|
||||
-rm -rf ./android/java/lib/src/main/jniLibs
|
||||
|
||||
distclean: clean
|
||||
-rm -rf ./mason_packages
|
||||
|
||||
812
android/cpp/JNI.cpp
Normal file
812
android/cpp/JNI.cpp
Normal file
@@ -0,0 +1,812 @@
|
||||
#include <cstdint>
|
||||
#include <cinttypes>
|
||||
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "NativeMapView.hpp"
|
||||
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jmethodID on_map_changed_id = nullptr;
|
||||
|
||||
jclass lon_lat_class = nullptr;
|
||||
jmethodID lon_lat_constructor_id = nullptr;
|
||||
jfieldID lon_lat_lon_id = nullptr;
|
||||
jfieldID lon_lat_lat_id = nullptr;
|
||||
|
||||
jclass lon_lat_zoom_class = nullptr;
|
||||
jmethodID lon_lat_zoom_constructor_id = nullptr;
|
||||
jfieldID lon_lat_zoom_lon_id = nullptr;
|
||||
jfieldID lon_lat_zoom_lat_id = nullptr;
|
||||
jfieldID lon_lat_zoom_zoom_id = nullptr;
|
||||
|
||||
jclass runtime_exception_class = nullptr;
|
||||
|
||||
jmethodID set_to_array_id = nullptr;
|
||||
|
||||
jclass tree_set_class = nullptr;
|
||||
jmethodID tree_set_constructor_id = nullptr;
|
||||
jmethodID tree_set_add_id = nullptr;
|
||||
|
||||
bool throw_error(JNIEnv* env, const char* msg) {
|
||||
if (env->ThrowNew(runtime_exception_class, msg) < 0) {
|
||||
env->ExceptionDescribe();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string std_string_from_jstring(JNIEnv* env, jstring jstr) {
|
||||
std::string str;
|
||||
jsize len = env->GetStringLength(jstr);
|
||||
if (len < 0) {
|
||||
env->ExceptionDescribe();
|
||||
return str;
|
||||
}
|
||||
const jchar* chars = env->GetStringChars(jstr, nullptr);
|
||||
if (chars == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return str;
|
||||
}
|
||||
std::u16string ustr(reinterpret_cast<const char16_t*>(chars), len);
|
||||
env->ReleaseStringChars(jstr, chars);
|
||||
chars = nullptr;
|
||||
str = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t>().to_bytes(ustr);
|
||||
return str;
|
||||
}
|
||||
|
||||
jstring std_string_to_jstring(JNIEnv* env, std::string str) {
|
||||
std::u16string ustr = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t>().from_bytes(str);
|
||||
|
||||
jstring jstr = env->NewString(reinterpret_cast<const jchar*>(ustr.c_str()), ustr.size());
|
||||
if (jstr == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return jstr;
|
||||
}
|
||||
|
||||
|
||||
// TODO: change from Java TreeSet to ArrayList
|
||||
std::vector<std::string> std_vector_string_from_jobject(JNIEnv* env, jobject jset) {
|
||||
std::vector<std::string> vector;
|
||||
|
||||
jobjectArray array = reinterpret_cast<jobjectArray>(env->CallObjectMethod(jset, set_to_array_id));
|
||||
if (env->ExceptionCheck() || (array == nullptr)) {
|
||||
env->ExceptionDescribe();
|
||||
return vector;
|
||||
}
|
||||
|
||||
jsize len = env->GetArrayLength(array);
|
||||
if (len < 0) {
|
||||
env->ExceptionDescribe();
|
||||
return vector;
|
||||
}
|
||||
|
||||
for (jsize i = 0; i < len; i++) {
|
||||
jstring jstr = reinterpret_cast<jstring>(env->GetObjectArrayElement(array, i));
|
||||
if (jstr == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return vector;
|
||||
}
|
||||
|
||||
vector.push_back(std_string_from_jstring(env, jstr));
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
// TODO: change from Java TreeSet to ArrayList
|
||||
jobject std_vector_string_to_jobject(JNIEnv* env, std::vector<std::string> vector) {
|
||||
jobject jset = env->NewObject(tree_set_class, tree_set_constructor_id);
|
||||
if (jset == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (std::string str : vector) {
|
||||
env->CallBooleanMethod(jset, tree_set_add_id, std_string_to_jstring(env, str));
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return jset;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace mbgl::android;
|
||||
|
||||
// TODO: wrap C++ exceptions?
|
||||
// TODO: wrap other sorts of exceptions? eg coffee catch
|
||||
|
||||
jlong JNICALL nativeCreate(JNIEnv* env, jobject obj, jstring default_style_json) {
|
||||
VERBOSE("nativeCreate");
|
||||
NativeMapView* native_map_view = new NativeMapView(env, obj, std_string_from_jstring(env, default_style_json));
|
||||
if (native_map_view == nullptr) {
|
||||
throw_error(env, "Unable to create NativeMapView.");
|
||||
return 0;
|
||||
}
|
||||
jlong map_view_ptr = reinterpret_cast<jlong>(native_map_view);
|
||||
return map_view_ptr;
|
||||
}
|
||||
|
||||
void JNICALL nativeDestroy(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeDestroy");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
delete native_map_view;
|
||||
native_map_view = nullptr;
|
||||
}
|
||||
|
||||
void JNICALL nativeInitializeDisplay(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeInitializeDisplay");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
if (!native_map_view->initializeDisplay()) {
|
||||
throw_error(env, "Unable to initialize GL display.");
|
||||
}
|
||||
}
|
||||
|
||||
void JNICALL nativeTerminateDisplay(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeTerminateDisplay");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->terminateDisplay();
|
||||
}
|
||||
|
||||
void JNICALL nativeInitializeContext(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeInitializeContext");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
if (!native_map_view->initializeContext()) {
|
||||
throw_error(env, "Unable to initialize GL context.");
|
||||
}
|
||||
}
|
||||
|
||||
void JNICALL nativeTerminateContext(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeTerminateContext");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->terminateContext();
|
||||
}
|
||||
|
||||
void JNICALL nativeCreateSurface(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jobject surface) {
|
||||
VERBOSE("nativeCreateSurface");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
if (!native_map_view->createSurface(ANativeWindow_fromSurface(env, surface))) {
|
||||
throw_error(env, "Unable to create GL surface.");
|
||||
}
|
||||
}
|
||||
|
||||
void JNICALL nativeDestroySurface(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeDestroySurface");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->destroySurface();
|
||||
}
|
||||
|
||||
void JNICALL nativeStart(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStart");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->start();
|
||||
}
|
||||
|
||||
void JNICALL nativeStop(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStop");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->stop();
|
||||
}
|
||||
|
||||
void JNICALL nativeRerender(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeRerender");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->rerender();
|
||||
}
|
||||
|
||||
void JNICALL nativeUpdate(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeUpdate");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->update();
|
||||
}
|
||||
|
||||
void JNICALL nativeCleanup(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeCleanup");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->cleanup();
|
||||
}
|
||||
|
||||
void JNICALL nativeResize(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jint width, jint height, jfloat ratio) {
|
||||
VERBOSE("nativeResize");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
ASSERT(width >= 0);
|
||||
ASSERT(height >= 0);
|
||||
ASSERT(width <= UINT16_MAX);
|
||||
ASSERT(height <= UINT16_MAX);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->resize(width, height, ratio);
|
||||
}
|
||||
|
||||
void JNICALL nativeResize(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jint width, jint height, jfloat ratio, jint fb_width, jint fb_height) {
|
||||
VERBOSE("nativeResize");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
ASSERT(width >= 0);
|
||||
ASSERT(height >= 0);
|
||||
ASSERT(width <= UINT16_MAX);
|
||||
ASSERT(height <= UINT16_MAX);
|
||||
ASSERT(fb_width >= 0);
|
||||
ASSERT(fb_height >= 0);
|
||||
ASSERT(fb_width <= UINT16_MAX);
|
||||
ASSERT(fb_height <= UINT16_MAX);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->resize(width, height, ratio, fb_width, fb_height);
|
||||
}
|
||||
|
||||
void JNICALL nativeSetAppliedClasses(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jobject applied_classes) {
|
||||
VERBOSE("nativeSetAppliedClasses");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setAppliedClasses(std_vector_string_from_jobject(env, applied_classes));
|
||||
}
|
||||
|
||||
jobject JNICALL nativeGetAppliedClasses(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetAppliedClasses");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return std_vector_string_to_jobject(env, native_map_view->getMap()->getAppliedClasses());
|
||||
}
|
||||
|
||||
void JNICALL nativeSetDefaultTransitionDuration(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jlong duration_milliseconds) {
|
||||
VERBOSE("nativeSetDefaultTransitionDuration");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
ASSERT(duration_milliseconds >= 0);
|
||||
//ASSERT(duration_milliseconds <= UINT64_MAX);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setDefaultTransitionDuration(duration_milliseconds);
|
||||
}
|
||||
|
||||
void JNICALL nativeSetStyleJSON(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jstring new_style_json) {
|
||||
VERBOSE("nativeSetStyleJSON");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setStyleJSON(std_string_from_jstring(env, new_style_json));
|
||||
}
|
||||
|
||||
jstring JNICALL nativeGetStyleJSON(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetStyleJSON");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return std_string_to_jstring(env, native_map_view->getMap()->getStyleJSON());
|
||||
}
|
||||
|
||||
void JNICALL nativeCancelTransitions(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeCancelTransitions");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->cancelTransitions();
|
||||
}
|
||||
|
||||
void JNICALL nativeMoveBy(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble dx, jdouble dy, jdouble duration) {
|
||||
VERBOSE("nativeMoveBy");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->moveBy(dx, dy, duration);
|
||||
}
|
||||
|
||||
void JNICALL nativeSetLonLat(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jobject lon_lat, jdouble duration) {
|
||||
VERBOSE("nativeSetLonLat");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
|
||||
double lon = env->GetDoubleField(lon_lat, lon_lat_lon_id);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
double lat = env->GetDoubleField(lon_lat, lon_lat_lat_id);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO remove when fixed
|
||||
DEBUG("lon lat %f %f", lon, lat);
|
||||
native_map_view->getMap()->setLonLat(lon, lat, duration);
|
||||
}
|
||||
|
||||
jobject JNICALL nativeGetLonLat(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetLonLat");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
double lon, lat;
|
||||
native_map_view->getMap()->getLonLat(lon, lat);
|
||||
|
||||
jobject ret = env->NewObject(lon_lat_class, lon_lat_constructor_id, lon, lat);
|
||||
if (ret == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JNICALL nativeStartPanning(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStartPanning");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->startPanning();
|
||||
}
|
||||
|
||||
void JNICALL nativeStopPanning(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStopPanning");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->stopPanning();
|
||||
}
|
||||
|
||||
void JNICALL nativeResetPosition(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeResetPosition");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->resetPosition();
|
||||
}
|
||||
|
||||
void JNICALL nativeScaleBy(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble ds, jdouble cx, jdouble cy, jdouble duration) {
|
||||
VERBOSE("nativeScaleBy");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->scaleBy(ds, cx, cy, duration);
|
||||
}
|
||||
|
||||
void JNICALL nativeSetScale(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble scale, jdouble cx, jdouble cy, jdouble duration) {
|
||||
VERBOSE("nativeSetScale");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setScale(scale, cx, cy, duration);
|
||||
}
|
||||
|
||||
jdouble JNICALL nativeGetScale(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetScale");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->getScale();
|
||||
}
|
||||
|
||||
void JNICALL nativeSetZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble zoom, jdouble duration) {
|
||||
VERBOSE("nativeSetZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setZoom(zoom, duration);
|
||||
}
|
||||
|
||||
jdouble JNICALL nativeGetZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->getZoom();
|
||||
}
|
||||
|
||||
void JNICALL nativeSetLonLatZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jobject lon_lat_zoom, jdouble duration) {
|
||||
VERBOSE("nativeSetLonLatZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
|
||||
double lon = env->GetDoubleField(lon_lat_zoom, lon_lat_zoom_lon_id);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
double lat = env->GetDoubleField(lon_lat_zoom, lon_lat_zoom_lat_id);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
double zoom = env->GetDoubleField(lon_lat_zoom, lon_lat_zoom_zoom_id);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
native_map_view->getMap()->setLonLatZoom(lon, lat, zoom, duration);
|
||||
}
|
||||
|
||||
jobject JNICALL nativeGetLonLatZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetLonLatZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
double lon, lat, zoom;
|
||||
native_map_view->getMap()->getLonLatZoom(lon, lat, zoom);
|
||||
|
||||
jobject ret = env->NewObject(lon_lat_zoom_class, lon_lat_zoom_constructor_id, lon, lat, zoom);
|
||||
if (ret == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JNICALL nativeResetZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeResetZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->resetZoom();
|
||||
}
|
||||
|
||||
void JNICALL nativeStartScaling(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStartScaling");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->startScaling();
|
||||
}
|
||||
|
||||
void JNICALL nativeStopScaling(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStopScaling");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->stopScaling();
|
||||
}
|
||||
|
||||
jdouble JNICALL nativeGetMinZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetMinZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->getMinZoom();
|
||||
}
|
||||
|
||||
jdouble JNICALL nativeGetMaxZoom(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetMaxZoom");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->getMaxZoom();
|
||||
}
|
||||
|
||||
void JNICALL nativeRotateBy(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble sx, jdouble sy, jdouble ex, jdouble ey, jdouble duration) {
|
||||
VERBOSE("nativeRotateBy");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->rotateBy(sx, sy, ex, ey, duration);
|
||||
}
|
||||
|
||||
void JNICALL nativeSetBearing(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble degrees, jdouble duration) {
|
||||
VERBOSE("nativeSetBearing");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setBearing(degrees, duration);
|
||||
}
|
||||
|
||||
void JNICALL nativeSetBearing(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jdouble degrees, jdouble cx, jdouble cy) {
|
||||
VERBOSE("nativeSetBearing");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setBearing(degrees, cx, cy);
|
||||
}
|
||||
|
||||
jdouble JNICALL nativeGetBearing(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetBearing");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->getBearing();
|
||||
}
|
||||
|
||||
void JNICALL nativeResetNorth(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeResetNorth");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->resetNorth();
|
||||
}
|
||||
|
||||
void JNICALL nativeStartRotating(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStartRotating");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->startRotating();
|
||||
}
|
||||
|
||||
void JNICALL nativeStopRotating(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeStopRotating");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->stopRotating();
|
||||
}
|
||||
|
||||
jboolean JNICALL nativeCanRotate(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeCanRotate");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->canRotate();
|
||||
}
|
||||
|
||||
void JNICALL nativeSetDebug(JNIEnv* env, jobject obj, jlong native_map_view_ptr, jboolean debug) {
|
||||
VERBOSE("nativeSetDebug");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->setDebug(debug);
|
||||
}
|
||||
|
||||
void JNICALL nativeToggleDebug(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeToggleDebug");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
native_map_view->getMap()->toggleDebug();
|
||||
}
|
||||
|
||||
jboolean JNICALL nativeGetDebug(JNIEnv* env, jobject obj, jlong native_map_view_ptr) {
|
||||
VERBOSE("nativeGetDebug");
|
||||
ASSERT(native_map_view_ptr != 0);
|
||||
NativeMapView* native_map_view = reinterpret_cast<NativeMapView*>(native_map_view_ptr);
|
||||
return native_map_view->getMap()->getDebug();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
VERBOSE("JNI_OnLoad");
|
||||
|
||||
JNIEnv* env = nullptr;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
ERROR("GetEnv() failed");
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_class = env->FindClass("com/mapbox/mapboxgl/lib/LonLat");
|
||||
if (lon_lat_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_constructor_id = env->GetMethodID(lon_lat_class, "<init>", "(DD)V");
|
||||
if (lon_lat_constructor_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_lon_id = env->GetFieldID(lon_lat_class, "lon", "D");
|
||||
if (lon_lat_lon_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_lat_id = env->GetFieldID(lon_lat_class, "lat", "D");
|
||||
if (lon_lat_lat_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_zoom_class = env->FindClass("com/mapbox/mapboxgl/lib/LonLatZoom");
|
||||
if (lon_lat_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_zoom_constructor_id = env->GetMethodID(lon_lat_zoom_class, "<init>", "(DDD)V");
|
||||
if (lon_lat_zoom_constructor_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_zoom_lon_id = env->GetFieldID(lon_lat_zoom_class, "lon", "D");
|
||||
if (lon_lat_zoom_lon_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_zoom_lat_id = env->GetFieldID(lon_lat_zoom_class, "lat", "D");
|
||||
if (lon_lat_zoom_lat_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_zoom_zoom_id = env->GetFieldID(lon_lat_zoom_class, "zoom", "D");
|
||||
if (lon_lat_zoom_zoom_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
jclass native_map_view_class = env->FindClass("com/mapbox/mapboxgl/lib/NativeMapView");
|
||||
if (native_map_view_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
on_map_changed_id = env->GetMethodID(native_map_view_class, "onMapChanged", "()V");
|
||||
if (on_map_changed_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
runtime_exception_class = env->FindClass("java/lang/RuntimeException");
|
||||
if (runtime_exception_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
jclass set_class = env->FindClass("java/util/Set");
|
||||
if (set_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
set_to_array_id = env->GetMethodID(set_class, "toArray", "()[Ljava/lang/Object;");
|
||||
if (set_to_array_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
tree_set_class = env->FindClass("java/util/TreeSet");
|
||||
if (tree_set_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
tree_set_constructor_id = env->GetMethodID(tree_set_class, "<init>", "()V");
|
||||
if (tree_set_constructor_id == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
tree_set_add_id = env->GetMethodID(tree_set_class, "add", "(Ljava/lang/Object;)Z");
|
||||
if (tree_set_add_id == 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<JNINativeMethod, 50> methods = {{ // Can remove the extra brace in C++14
|
||||
{ "nativeCreate", "(Ljava/lang/String;)J", reinterpret_cast<void*>(&nativeCreate) },
|
||||
{ "nativeDestroy", "(J)V", reinterpret_cast<void*>(&nativeDestroy) },
|
||||
{ "nativeInitializeDisplay", "(J)V", reinterpret_cast<void*>(&nativeInitializeDisplay) },
|
||||
{ "nativeTerminateDisplay", "(J)V", reinterpret_cast<void*>(&nativeTerminateDisplay) },
|
||||
{ "nativeInitializeContext", "(J)V", reinterpret_cast<void*>(&nativeInitializeContext) },
|
||||
{ "nativeTerminateContext", "(J)V", reinterpret_cast<void*>(&nativeTerminateContext) },
|
||||
{ "nativeCreateSurface", "(JLandroid/view/Surface;)V", reinterpret_cast<void*>(&nativeCreateSurface) },
|
||||
{ "nativeDestroySurface", "(J)V", reinterpret_cast<void*>(&nativeDestroySurface) },
|
||||
{ "nativeStart", "(J)V", reinterpret_cast<void*>(&nativeStart) },
|
||||
{ "nativeStop", "(J)V", reinterpret_cast<void*>(&nativeStop) },
|
||||
{ "nativeRerender", "(J)V", reinterpret_cast<void*>(&nativeRerender) },
|
||||
{ "nativeUpdate", "(J)V", reinterpret_cast<void*>(&nativeUpdate) },
|
||||
{ "nativeCleanup", "(J)V", reinterpret_cast<void*>(&nativeCleanup) },
|
||||
{ "nativeResize", "(JIIF)V", reinterpret_cast<void*>(static_cast<void JNICALL(*)(JNIEnv*,jobject,jlong,jint,jint,jfloat)>(&nativeResize)) },
|
||||
{ "nativeResize", "(JIIFII)V", reinterpret_cast<void*>(static_cast<void JNICALL(*)(JNIEnv*,jobject,jlong,jint,jint,jfloat,jint,jint)>(&nativeResize)) },
|
||||
{ "nativeSetAppliedClasses", "(JLjava/util/Set;)V", reinterpret_cast<void*>(&nativeSetAppliedClasses) },
|
||||
{ "nativeGetAppliedClasses", "(J)Ljava/util/Set;", reinterpret_cast<void*>(&nativeGetAppliedClasses) },
|
||||
{ "nativeSetDefaultTransitionDuration", "(JJ)V", reinterpret_cast<void*>(&nativeSetDefaultTransitionDuration) },
|
||||
{ "nativeSetStyleJSON", "(JLjava/lang/String;)V", reinterpret_cast<void*>(&nativeSetStyleJSON) },
|
||||
{ "nativeGetStyleJSON", "(J)Ljava/lang/String;", reinterpret_cast<void*>(&nativeGetStyleJSON) },
|
||||
{ "nativeCancelTransitions", "(J)V", reinterpret_cast<void*>(&nativeCancelTransitions) },
|
||||
{ "nativeMoveBy", "(JDDD)V", reinterpret_cast<void*>(&nativeMoveBy) },
|
||||
{ "nativeSetLonLat", "(JLcom/mapbox/mapboxgl/lib/LonLat;D)V", reinterpret_cast<void*>(&nativeSetLonLat) },
|
||||
{ "nativeGetLonLat", "(J)Lcom/mapbox/mapboxgl/lib/LonLat;", reinterpret_cast<void*>(&nativeGetLonLat) },
|
||||
{ "nativeStartPanning", "(J)V", reinterpret_cast<void*>(&nativeStartPanning) },
|
||||
{ "nativeStopPanning", "(J)V", reinterpret_cast<void*>(&nativeStopPanning) },
|
||||
{ "nativeResetPosition", "(J)V", reinterpret_cast<void*>(&nativeResetPosition) },
|
||||
{ "nativeScaleBy", "(JDDDD)V", reinterpret_cast<void*>(&nativeScaleBy) },
|
||||
{ "nativeSetScale", "(JDDDD)V", reinterpret_cast<void*>(&nativeSetScale) },
|
||||
{ "nativeGetScale", "(J)D", reinterpret_cast<void*>(&nativeGetScale) },
|
||||
{ "nativeSetZoom", "(JDD)V", reinterpret_cast<void*>(&nativeSetZoom) },
|
||||
{ "nativeGetZoom", "(J)D", reinterpret_cast<void*>(&nativeGetZoom) },
|
||||
{ "nativeSetLonLatZoom", "(JLcom/mapbox/mapboxgl/lib/LonLatZoom;D)V", reinterpret_cast<void*>(&nativeSetLonLatZoom) },
|
||||
{ "nativeGetLonLatZoom", "(J)Lcom/mapbox/mapboxgl/lib/LonLatZoom;", reinterpret_cast<void*>(&nativeGetLonLatZoom) },
|
||||
{ "nativeResetZoom", "(J)V", reinterpret_cast<void*>(&nativeResetZoom) },
|
||||
{ "nativeStartPanning", "(J)V", reinterpret_cast<void*>(&nativeStartScaling) },
|
||||
{ "nativeStopPanning", "(J)V", reinterpret_cast<void*>(&nativeStopScaling) },
|
||||
{ "nativeGetMinZoom", "(J)D", reinterpret_cast<void*>(&nativeGetMinZoom) },
|
||||
{ "nativeGetMaxZoom", "(J)D", reinterpret_cast<void*>(&nativeGetMaxZoom) },
|
||||
{ "nativeRotateBy", "(JDDDDD)V", reinterpret_cast<void*>(&nativeRotateBy) },
|
||||
{ "nativeSetBearing", "(JDD)V", reinterpret_cast<void*>(static_cast<void JNICALL(*)(JNIEnv*,jobject,jlong,jdouble,jdouble)>(&nativeSetBearing)) },
|
||||
{ "nativeSetBearing", "(JDDD)V", reinterpret_cast<void*>(static_cast<void JNICALL(*)(JNIEnv*,jobject,jlong,jdouble,jdouble,jdouble)>(&nativeSetBearing)) },
|
||||
{ "nativeGetBearing", "(J)D", reinterpret_cast<void*>(&nativeGetBearing) },
|
||||
{ "nativeResetNorth", "(J)V", reinterpret_cast<void*>(&nativeResetNorth) },
|
||||
{ "nativeStartRotating", "(J)V", reinterpret_cast<void*>(&nativeStartRotating) },
|
||||
{ "nativeStopRotating", "(J)V", reinterpret_cast<void*>(&nativeStopRotating) },
|
||||
{ "nativeCanRotate", "(J)Z", reinterpret_cast<void*>(&nativeCanRotate) },
|
||||
{ "nativeSetDebug", "(JZ)V", reinterpret_cast<void*>(&nativeSetDebug) },
|
||||
{ "nativeToggleDebug", "(J)V", reinterpret_cast<void*>(&nativeToggleDebug) },
|
||||
{ "nativeGetDebug", "(J)Z", reinterpret_cast<void*>(&nativeGetDebug) }
|
||||
}};
|
||||
|
||||
if (env->RegisterNatives(native_map_view_class, methods.data(), methods.size()) < 0) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_class = reinterpret_cast<jclass>(env->NewGlobalRef(lon_lat_class));
|
||||
if (lon_lat_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
lon_lat_zoom_class = reinterpret_cast<jclass>(env->NewGlobalRef(lon_lat_zoom_class));
|
||||
if (lon_lat_zoom_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
env->DeleteGlobalRef(lon_lat_class);
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
runtime_exception_class = reinterpret_cast<jclass>(env->NewGlobalRef(runtime_exception_class));
|
||||
if (runtime_exception_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
env->DeleteGlobalRef(lon_lat_class);
|
||||
env->DeleteGlobalRef(lon_lat_zoom_class);
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
tree_set_class = reinterpret_cast<jclass>(env->NewGlobalRef(tree_set_class));
|
||||
if (tree_set_class == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
env->DeleteGlobalRef(lon_lat_class);
|
||||
env->DeleteGlobalRef(lon_lat_zoom_class);
|
||||
env->DeleteGlobalRef(runtime_exception_class);
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
VERBOSE("JNI_OnUnload");
|
||||
|
||||
JNIEnv* env = nullptr;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
ERROR("GetEnv() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
env->DeleteGlobalRef(lon_lat_class);
|
||||
lon_lat_class = nullptr;
|
||||
lon_lat_constructor_id = nullptr;
|
||||
lon_lat_lon_id = nullptr;
|
||||
lon_lat_lat_id = nullptr;
|
||||
|
||||
env->DeleteGlobalRef(lon_lat_zoom_class);
|
||||
lon_lat_zoom_class = nullptr;
|
||||
lon_lat_zoom_constructor_id = nullptr;
|
||||
lon_lat_zoom_lon_id = nullptr;
|
||||
lon_lat_zoom_lat_id = nullptr;
|
||||
lon_lat_zoom_zoom_id = nullptr;
|
||||
|
||||
on_map_changed_id = nullptr;
|
||||
|
||||
env->DeleteGlobalRef(runtime_exception_class);
|
||||
runtime_exception_class = nullptr;
|
||||
|
||||
set_to_array_id = nullptr;
|
||||
|
||||
env->DeleteGlobalRef(tree_set_class);
|
||||
tree_set_class = nullptr;
|
||||
tree_set_constructor_id = nullptr;
|
||||
tree_set_add_id = nullptr;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
559
android/cpp/NativeMapView.cpp
Normal file
559
android/cpp/NativeMapView.cpp
Normal file
@@ -0,0 +1,559 @@
|
||||
//#include <cstdio>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "NativeMapView.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void log_egl_string(EGLDisplay display, EGLint name, const char* label) {
|
||||
const char* str = eglQueryString(display, name);
|
||||
if (str == nullptr) {
|
||||
ERROR("eglQueryString(%d) returned error %d", name, eglGetError());
|
||||
} else {
|
||||
INFO("EGL %s: %s", label, str);
|
||||
}
|
||||
}
|
||||
|
||||
void log_gl_string(GLenum name, const char* label) {
|
||||
const GLubyte* str = glGetString(name);
|
||||
if (str == nullptr) {
|
||||
ERROR("glGetString(%d) returned error %d", name, glGetError());
|
||||
} else {
|
||||
INFO("GL %s: %s", label, str);
|
||||
}
|
||||
}
|
||||
|
||||
NativeMapView::NativeMapView(JNIEnv* env, jobject obj_,
|
||||
std::string default_style_json_) :
|
||||
default_style_json(default_style_json_) {
|
||||
VERBOSE("NativeMapView::NativeMapView");
|
||||
|
||||
ASSERT(env != nullptr);
|
||||
ASSERT(obj_ != nullptr);
|
||||
|
||||
if (env->GetJavaVM(&vm) < 0) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
obj = env->NewGlobalRef(obj_);
|
||||
if (obj == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO replace all printfs in map code with android logging
|
||||
//freopen("/sdcard/stdout.txt", "w", stdout); // NOTE: can't use <cstdio> till NDK fix the stdout macro bug
|
||||
//freopen("/sdcard/stderr.txt", "w", stderr);
|
||||
|
||||
view = new MBGLView(this);
|
||||
map = new mbgl::Map(*view);
|
||||
|
||||
// FIXME need way to load this from Java
|
||||
map->setAccessToken("pk.eyJ1IjoibGpiYWRlIiwiYSI6IlJSQ0FEZ2MifQ.7mE4aOegldh3595AG9dxpQ");
|
||||
|
||||
// FIXME this asserts because it creates FileSource of different thread from run thread
|
||||
//map->setStyleJSON(default_style_json);
|
||||
map->setStyleURL("https://raw.githubusercontent.com/mapbox/mapbox-gl-styles/mb-pages/styles/bright-v6.json");
|
||||
}
|
||||
|
||||
NativeMapView::~NativeMapView() {
|
||||
VERBOSE("NativeMapView::~NativeMapView");
|
||||
terminateContext();
|
||||
|
||||
delete map;
|
||||
map = nullptr;
|
||||
|
||||
delete view;
|
||||
view = nullptr;
|
||||
|
||||
ASSERT(vm != nullptr);
|
||||
ASSERT(obj != nullptr);
|
||||
|
||||
jint ret;
|
||||
JNIEnv* env = nullptr;
|
||||
if ((ret = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) == JNI_OK) {
|
||||
env->DeleteGlobalRef(obj);
|
||||
} else {
|
||||
ERROR("GetEnv() failed with %i", ret);
|
||||
}
|
||||
obj = nullptr;
|
||||
vm = nullptr;
|
||||
}
|
||||
|
||||
bool NativeMapView::initializeDisplay() {
|
||||
VERBOSE("NativeMapView::initializeDisplay");
|
||||
|
||||
ASSERT(display == EGL_NO_DISPLAY);
|
||||
ASSERT(config == nullptr);
|
||||
ASSERT(format < 0);
|
||||
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
ERROR("eglGetDisplay() returned error %d", eglGetError());
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLint major, minor;
|
||||
if (!eglInitialize(display, &major, &minor)) {
|
||||
ERROR("eglInitialize() returned error %d", eglGetError());
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
if ((major <= 1) && (minor < 3)) {
|
||||
ERROR("EGL version is too low, need 1.3, got %d.%d", major, minor);
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
|
||||
log_egl_string(display, EGL_VENDOR, "Vendor");
|
||||
log_egl_string(display, EGL_VERSION, "Version");
|
||||
log_egl_string(display, EGL_CLIENT_APIS, "Client APIs");
|
||||
log_egl_string(display, EGL_EXTENSIONS, "Client Extensions");
|
||||
|
||||
// TODO should try 565, then 8888?
|
||||
bool use565 = true;
|
||||
|
||||
const EGLint config_attribs[] = {
|
||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||
EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
||||
EGL_BUFFER_SIZE, use565 ? 16 : 32, // Ensure we get 32bit color buffer on Tegra, 24 bit will be sorted first without it (slow software mode)
|
||||
EGL_RED_SIZE, use565 ? 5 : 8,
|
||||
EGL_GREEN_SIZE, use565 ? 6 : 8,
|
||||
EGL_BLUE_SIZE, use565 ? 5 : 8,
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint num_configs;
|
||||
if (!eglChooseConfig(display, config_attribs, nullptr, 0, &num_configs)) {
|
||||
ERROR("eglChooseConfig(NULL) returned error %d", eglGetError());
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
if (num_configs < 1) {
|
||||
ERROR("eglChooseConfig() returned no configs");
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO make_unique missing in Android NDK?
|
||||
// const std::unique_ptr<EGLConfig[]> configs = std::make_unique(new EGLConfig[num_configs]);
|
||||
const std::unique_ptr<EGLConfig[]> configs(new EGLConfig[num_configs]);
|
||||
if (!eglChooseConfig(display, config_attribs, configs.get(), num_configs,
|
||||
&num_configs)) {
|
||||
ERROR("eglChooseConfig() returned error %d", eglGetError());
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
|
||||
config = chooseConfig(configs.get(), num_configs, use565);
|
||||
if (config == nullptr) {
|
||||
ERROR("No config chosen");
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
|
||||
ERROR("eglGetConfigAttrib() returned error %d", eglGetError());
|
||||
terminateDisplay();
|
||||
return false;
|
||||
}
|
||||
DEBUG("Chosen window format is %d", format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeMapView::terminateDisplay() {
|
||||
VERBOSE("NativeMapView::terminateDisplay");
|
||||
|
||||
if (display != EGL_NO_DISPLAY) {
|
||||
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT)) {
|
||||
ERROR("eglMakeCurrent(EGL_NO_CONTEXT) returned error %d",
|
||||
eglGetError());
|
||||
}
|
||||
|
||||
if (!eglTerminate(display)) {
|
||||
ERROR("eglTerminate() returned error %d", eglGetError());
|
||||
}
|
||||
}
|
||||
|
||||
display = EGL_NO_DISPLAY;
|
||||
config = nullptr;
|
||||
format = -1;
|
||||
}
|
||||
|
||||
bool NativeMapView::initializeContext() {
|
||||
VERBOSE("NativeMapView::initializeContext");
|
||||
|
||||
ASSERT(display != EGL_NO_DISPLAY);
|
||||
ASSERT(context == EGL_NO_CONTEXT);
|
||||
ASSERT(config != nullptr);
|
||||
|
||||
const EGLint context_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
ERROR("eglCreateContext() returned error %d", eglGetError());
|
||||
terminateContext();
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO("Context initialized");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeMapView::terminateContext() {
|
||||
VERBOSE("NativeMapView::terminateContext");
|
||||
|
||||
map->terminate();
|
||||
|
||||
// TODO: there is a bug when you double tap home to go app switcher, as map is black if you immediately switch to the map again
|
||||
// TODO: this is in the onPause/onResume path
|
||||
// TODO: the bug causes an GL_INVALID_VALUE with glDelteProgram (I think due to context being deleted first)
|
||||
// TODO: we need to free resources before we terminate
|
||||
// TODO: but cause terminate and stop is async they try to do stuff with no context and crash!
|
||||
|
||||
if (display != EGL_NO_DISPLAY) {
|
||||
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT)) {
|
||||
ERROR("eglMakeCurrent(EGL_NO_CONTEXT) returned error %d",
|
||||
eglGetError());
|
||||
}
|
||||
|
||||
if (context != EGL_NO_CONTEXT) {
|
||||
if (!eglDestroyContext(display, context)) {
|
||||
ERROR("eglDestroyContext() returned error %d", eglGetError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
bool NativeMapView::createSurface(ANativeWindow* window_) {
|
||||
VERBOSE("NativeMapView::createSurface");
|
||||
|
||||
ASSERT(window == nullptr);
|
||||
ASSERT(window_ != nullptr);
|
||||
window = window_;
|
||||
|
||||
ASSERT(display != EGL_NO_DISPLAY);
|
||||
ASSERT(surface == EGL_NO_SURFACE);
|
||||
ASSERT(config != nullptr);
|
||||
ASSERT(format >= 0);
|
||||
|
||||
ANativeWindow_setBuffersGeometry(window, 0, 0, format);
|
||||
|
||||
const EGLint surface_attribs[] = {
|
||||
EGL_NONE
|
||||
};
|
||||
surface = eglCreateWindowSurface(display, config, window, surface_attribs);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
ERROR("eglCreateWindowSurface() returned error %d", eglGetError());
|
||||
destroySurface();
|
||||
return false;
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeMapView::destroySurface() {
|
||||
VERBOSE("NativeMapView::destroySurface");
|
||||
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
if (!eglDestroySurface(display, surface)) {
|
||||
ERROR("eglDestroySurface() returned error %d", eglGetError());
|
||||
}
|
||||
}
|
||||
|
||||
surface = EGL_NO_SURFACE;
|
||||
|
||||
if (window != nullptr) {
|
||||
ANativeWindow_release(window);
|
||||
window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[],
|
||||
EGLint num_configs, bool use565) const {
|
||||
INFO("Found %d configs", num_configs);
|
||||
|
||||
int chosen_config = -1;
|
||||
for (int i = 0; i < num_configs; i++) {
|
||||
INFO("Config %d:", i);
|
||||
|
||||
EGLint bits, red, green, blue, alpha, alpha_mask, depth, stencil,
|
||||
sample_buffers, samples;
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_BUFFER_SIZE, &bits)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_BUFFER_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_RED_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_GREEN_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_BLUE_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_ALPHA_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_ALPHA_MASK_SIZE,
|
||||
&alpha_mask)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_ALPHA_MASK_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_DEPTH_SIZE, &depth)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_DEPTH_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_STENCIL_SIZE,
|
||||
&stencil)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_STENCIL_SIZE) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_SAMPLE_BUFFERS,
|
||||
&sample_buffers)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_SAMPLE_BUFFERS) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(display, configs[i], EGL_SAMPLES, &samples)) {
|
||||
ERROR("eglGetConfigAttrib(EGL_SAMPLES) returned error %d",
|
||||
eglGetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
INFO("Color: %d", bits);
|
||||
INFO("Red: %d", red);
|
||||
INFO("Green: %d", green);
|
||||
INFO("Blue: %d", blue);
|
||||
INFO("Alpha: %d", alpha);
|
||||
INFO("Alpha mask: %d", alpha_mask);
|
||||
INFO("Depth: %d", depth);
|
||||
INFO("Stencil: %d", stencil);
|
||||
INFO("Sample buffers: %d", sample_buffers);
|
||||
INFO("Samples: %d", samples);
|
||||
|
||||
bool config_ok = true;
|
||||
config_ok &= bits == (use565 ? 16 : 32);
|
||||
config_ok &= red == (use565 ? 5 : 8);
|
||||
config_ok &= green == (use565 ? 6 : 8);
|
||||
config_ok &= blue == (use565 ? 5 : 8);
|
||||
//config_ok &= (alpha == 0) || (alpha == 8); // Can be either 0 for RGBX or 8 for RGBA but we don't care either way
|
||||
config_ok &= alpha == 0; // TODO should prefer no alpha over alpha, and 565 over 8888?
|
||||
//config_ok &= depth == 16;
|
||||
//config_ok &= stencil == 8;
|
||||
//config_ok &= sample_buffers == 0;
|
||||
config_ok &= samples == 0;
|
||||
|
||||
if (config_ok) { // Choose the last matching config, that way we get RGBX if possible (since it is sorted highest to lowest bits)
|
||||
chosen_config = i;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("Chosen config is %d", chosen_config);
|
||||
if (chosen_config >= 0) {
|
||||
return configs[chosen_config];
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::start() {
|
||||
VERBOSE("NativeMapView::start");
|
||||
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
initializeDisplay();
|
||||
}
|
||||
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
initializeContext();
|
||||
}
|
||||
|
||||
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)
|
||||
&& (context != EGL_NO_CONTEXT)) {
|
||||
|
||||
if (!eglMakeCurrent(display, surface, surface, context)) {
|
||||
ERROR("eglMakeCurrent() returned error %d", eglGetError());
|
||||
}
|
||||
|
||||
log_gl_string(GL_VENDOR, "Vendor");
|
||||
log_gl_string(GL_RENDERER, "Renderer");
|
||||
log_gl_string(GL_VERSION, "Version");
|
||||
log_gl_string(GL_SHADING_LANGUAGE_VERSION, "SL Version");
|
||||
log_gl_string(GL_EXTENSIONS, "Extensions");
|
||||
|
||||
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT)) {
|
||||
ERROR("eglMakeCurrent(EGL_NO_CONTEXT) returned error %d",
|
||||
eglGetError());
|
||||
}
|
||||
|
||||
map->start();
|
||||
} else {
|
||||
DEBUG("Not starting because we are not ready");
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::stop() {
|
||||
VERBOSE("NativeMapView::stop");
|
||||
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)
|
||||
&& (context != EGL_NO_CONTEXT)) {
|
||||
map->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::notifyMapChange() {
|
||||
DEBUG("NativeMapView::notify_map_change()");
|
||||
|
||||
ASSERT(vm != nullptr);
|
||||
ASSERT(obj != nullptr);
|
||||
|
||||
JavaVMAttachArgs args = {
|
||||
JNI_VERSION_1_2,
|
||||
"NativeMapView::notify_map_change()",
|
||||
NULL
|
||||
};
|
||||
|
||||
jint ret;
|
||||
JNIEnv* env = nullptr;
|
||||
bool detach = false;
|
||||
if ((ret = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) != JNI_OK) {
|
||||
if (ret != JNI_EDETACHED) {
|
||||
ERROR("GetEnv() failed with %i", ret);
|
||||
return;
|
||||
} else {
|
||||
if ((ret = vm->AttachCurrentThread(&env, &args)) != JNI_OK) {
|
||||
ERROR("AttachCurrentThread() failed with %i", ret);
|
||||
return;
|
||||
}
|
||||
detach = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
env->CallVoidMethod(obj, on_map_changed_id);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
}
|
||||
|
||||
if (detach) {
|
||||
if ((ret = vm->DetachCurrentThread()) != JNI_OK) {
|
||||
ERROR("DetachCurrentThread() failed with %i", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
env = nullptr;
|
||||
}
|
||||
|
||||
void MBGLView::make_active() {
|
||||
VERBOSE("MBGLView::make_active");
|
||||
if ((nativeView->display != EGL_NO_DISPLAY)
|
||||
&& (nativeView->surface != EGL_NO_SURFACE)
|
||||
&& (nativeView->context != EGL_NO_CONTEXT)) {
|
||||
if (!eglMakeCurrent(nativeView->display, nativeView->surface,
|
||||
nativeView->surface, nativeView->context)) {
|
||||
ERROR("eglMakeCurrent() returned error %d", eglGetError());
|
||||
}
|
||||
|
||||
// TODO still can't fix the black screen problem :-(
|
||||
EGLint width, height;
|
||||
if (!(eglQuerySurface(nativeView->display, nativeView->surface, EGL_WIDTH, &width)
|
||||
& eglQuerySurface(nativeView->display, nativeView->surface, EGL_HEIGHT, &height))) {
|
||||
ERROR("eglQuerySurface() returned error %d", eglGetError());
|
||||
}
|
||||
map->resize(width, height);
|
||||
|
||||
} else {
|
||||
DEBUG("Not activating as we are not ready");
|
||||
}
|
||||
}
|
||||
|
||||
void MBGLView::make_inactive() {
|
||||
VERBOSE("MBGLView::make_inactive");
|
||||
// FIXME: this gets called before swap? bug?
|
||||
if (!eglMakeCurrent(nativeView->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT)) {
|
||||
ERROR("eglMakeCurrent(EGL_NO_CONTEXT) returned error %d",
|
||||
eglGetError());
|
||||
}
|
||||
}
|
||||
|
||||
void MBGLView::swap() {
|
||||
VERBOSE("MBGLView::swap");
|
||||
// FIXME bug workaround
|
||||
make_active();
|
||||
|
||||
if (map->needsSwap() && (nativeView->display != EGL_NO_DISPLAY)
|
||||
&& (nativeView->surface != EGL_NO_SURFACE)) {
|
||||
if (!eglSwapBuffers(nativeView->display, nativeView->surface)) {
|
||||
ERROR("eglSwapBuffers() returned error %d", eglGetError());
|
||||
ERROR("%u", reinterpret_cast<unsigned int>(nativeView->surface)); // TODO remove
|
||||
}
|
||||
map->swapped();
|
||||
} else {
|
||||
DEBUG("Not swapping as we are not ready");
|
||||
}
|
||||
// FIXME bug workaround
|
||||
make_inactive();
|
||||
}
|
||||
|
||||
void MBGLView::notify() {
|
||||
DEBUG("MBGLView::notify()");
|
||||
// noop
|
||||
}
|
||||
|
||||
void MBGLView::notify_map_change(mbgl::MapChange change, mbgl::timestamp delay) {
|
||||
DEBUG("MBGLView::notify_map_change()");
|
||||
nativeView->notifyMapChange();
|
||||
// TODO: use new variables - do i need to?
|
||||
(void)change;
|
||||
(void)delay;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
111
android/cpp/NativeMapView.hpp
Normal file
111
android/cpp/NativeMapView.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef MAP_VIEW_HPP
|
||||
#define MAP_VIEW_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <android/native_window.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <mbgl/mbgl.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
extern jmethodID on_map_changed_id;
|
||||
|
||||
extern jclass lon_lat_class;
|
||||
extern jmethodID lon_lat_constructor_id;
|
||||
extern jfieldID lon_lat_lon_id;
|
||||
extern jfieldID lon_lat_lat_id;
|
||||
|
||||
extern jclass lon_lat_zoom_class;
|
||||
extern jmethodID lon_lat_zoom_constructor_id;
|
||||
extern jfieldID lon_lat_zoom_lon_id;
|
||||
extern jfieldID lon_lat_zoom_lat_id;
|
||||
extern jfieldID lon_lat_zoom_zoom_id;
|
||||
|
||||
extern jclass runtime_exception_class;
|
||||
|
||||
extern jmethodID set_to_array_id;
|
||||
|
||||
extern jclass tree_set_class;
|
||||
extern jmethodID tree_set_constructor_id;
|
||||
extern jmethodID tree_set_add_id;
|
||||
|
||||
class MBGLView;
|
||||
|
||||
class NativeMapView {
|
||||
friend class MBGLView;
|
||||
|
||||
public:
|
||||
NativeMapView(JNIEnv* env, jobject obj, std::string default_style_json);
|
||||
~NativeMapView();
|
||||
|
||||
mbgl::Map* getMap() const {
|
||||
return map;
|
||||
}
|
||||
|
||||
bool initializeDisplay();
|
||||
void terminateDisplay();
|
||||
|
||||
bool initializeContext();
|
||||
void terminateContext();
|
||||
|
||||
bool createSurface(ANativeWindow* window);
|
||||
void destroySurface();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void notifyMapChange();
|
||||
|
||||
private:
|
||||
EGLConfig chooseConfig(const EGLConfig configs[], EGLint num_configs,
|
||||
bool use565) const;
|
||||
|
||||
private:
|
||||
JavaVM* vm = nullptr;
|
||||
jobject obj = nullptr;
|
||||
|
||||
ANativeWindow* window = nullptr;
|
||||
|
||||
mbgl::Map* map = nullptr;
|
||||
MBGLView* view = nullptr;
|
||||
|
||||
EGLDisplay display = EGL_NO_DISPLAY;
|
||||
EGLSurface surface = EGL_NO_SURFACE;
|
||||
EGLContext context = EGL_NO_CONTEXT;
|
||||
|
||||
EGLConfig config = nullptr;
|
||||
EGLint format = -1;
|
||||
|
||||
std::string default_style_json;
|
||||
};
|
||||
|
||||
class MBGLView: public mbgl::View {
|
||||
public:
|
||||
MBGLView(NativeMapView* nativeView_) :
|
||||
nativeView(nativeView_) {
|
||||
}
|
||||
virtual ~MBGLView() {
|
||||
}
|
||||
|
||||
void make_active() override;
|
||||
void make_inactive() override;
|
||||
|
||||
void swap() override;
|
||||
|
||||
void notify() override;
|
||||
void notify_map_change(mbgl::MapChange change, mbgl::timestamp delay = 0) override;
|
||||
|
||||
private:
|
||||
NativeMapView* nativeView = nullptr;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
|
||||
#endif // MAP_VIEW_HPP
|
||||
18
android/cpp/log.h
Normal file
18
android/cpp/log.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define S(x) #x
|
||||
#define S_(x) S(x)
|
||||
#define S__LINE__ S_(__LINE__)
|
||||
|
||||
#define VERBOSE(fmt, args...) __android_log_print(ANDROID_LOG_VERBOSE, __FILE__ ":" S__LINE__, fmt, ##args)
|
||||
#define DEBUG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, __FILE__ ":" S__LINE__, fmt, ##args)
|
||||
#define INFO(fmt, args...) __android_log_print(ANDROID_LOG_INFO, __FILE__ ":" S__LINE__, fmt, ##args)
|
||||
#define WARN(fmt, args...) __android_log_print(ANDROID_LOG_WARN, __FILE__ ":" S__LINE__, fmt, ##args)
|
||||
#define ERROR(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, __FILE__ ":" S__LINE__, fmt, ##args)
|
||||
#define ASSERT(cond, ...) ((cond)?(void)0:__android_log_assert(#cond, __FILE__ ":" S__LINE__, NULL))
|
||||
#define ASSERTMSG(cond, fmt, args...) ((cond)?(void)0:__android_log_assert(#cond, __FILE__ ":" S__LINE__, fmt, ##args))
|
||||
|
||||
#endif // LOG_H
|
||||
14
android/java/.gitignore
vendored
Normal file
14
android/java/.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Gradle files
|
||||
.gradle/
|
||||
|
||||
# IntelliJ files
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
# Build files
|
||||
build/
|
||||
*/build/
|
||||
*.so
|
||||
|
||||
# Local settings
|
||||
local.properties
|
||||
23
android/java/app/build.gradle
Normal file
23
android/java/app/build.gradle
Normal file
@@ -0,0 +1,23 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.mapbox.mapboxgl.app"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 21
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
runProguard false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':lib')
|
||||
}
|
||||
3
android/java/app/lint.xml
Normal file
3
android/java/app/lint.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
</lint>
|
||||
33
android/java/app/src/main/AndroidManifest.xml
Normal file
33
android/java/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mapbox.mapboxgl.app"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="com.mapbox.mapboxgl.app.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize">
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.mapbox.mapboxgl.app.FragmentActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.mapbox.mapboxgl.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class FragmentActivity extends Activity {
|
||||
|
||||
//
|
||||
// Static members
|
||||
//
|
||||
|
||||
// Tag used for logging
|
||||
private static final String TAG = "FragmentActivity";
|
||||
|
||||
//
|
||||
// Lifecycle events
|
||||
//
|
||||
|
||||
// Called when activity is created
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.v(TAG, "onCreate");
|
||||
|
||||
// Load the layout
|
||||
setContentView(R.layout.activity_fragment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.mapbox.mapboxgl.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.mapbox.mapboxgl.lib.MapView;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
//
|
||||
// Static members
|
||||
//
|
||||
|
||||
// Tag used for logging
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
// The map
|
||||
private MapView mMapView;
|
||||
|
||||
//
|
||||
// Lifecycle events
|
||||
//
|
||||
|
||||
// Called when the activity is created
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.v(TAG, "onCreate");
|
||||
|
||||
// Load the layout
|
||||
setContentView(R.layout.activity_main);
|
||||
mMapView = (MapView) findViewById(R.id.map);
|
||||
|
||||
// Need to pass on any saved state to the map
|
||||
mMapView.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
// Called when the activity is destroyed
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.v(TAG, "onDestroy");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onDestroy();
|
||||
}
|
||||
|
||||
// Called when the activity is visible
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
Log.v(TAG, "onStart");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onStart();
|
||||
}
|
||||
|
||||
// Called when the activity is invisible
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Log.v(TAG, "onStop");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onStop();
|
||||
}
|
||||
|
||||
// Called when the activity is in the background
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
Log.v(TAG, "onPause");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onPause();
|
||||
}
|
||||
|
||||
// Called when the activity is no longer in the background
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Log.v(TAG, "onResume");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onResume();
|
||||
}
|
||||
|
||||
// Called before activity is destroyed
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
Log.v(TAG, "onSaveInstanceState");
|
||||
|
||||
// Need to retrieve any saved state from the map
|
||||
mMapView.onSaveInstanceState(outState);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
BIN
android/java/app/src/main/res/drawable-hdpi/ic_launcher.png
Normal file
BIN
android/java/app/src/main/res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
android/java/app/src/main/res/drawable-mdpi/ic_launcher.png
Normal file
BIN
android/java/app/src/main/res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
android/java/app/src/main/res/drawable-xhdpi/ic_launcher.png
Normal file
BIN
android/java/app/src/main/res/drawable-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
android/java/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
BIN
android/java/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
11
android/java/app/src/main/res/layout/activity_fragment.xml
Normal file
11
android/java/app/src/main/res/layout/activity_fragment.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="${packageName}.${activityClass}" >
|
||||
|
||||
<fragment
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
class="com.mapbox.mapboxgl.lib.MapFragment"
|
||||
android:id="@+id/map_fragment" />
|
||||
|
||||
</merge>
|
||||
11
android/java/app/src/main/res/layout/activity_main.xml
Normal file
11
android/java/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="${packageName}.${activityClass}" >
|
||||
|
||||
<view
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
class="com.mapbox.mapboxgl.lib.MapView"
|
||||
android:id="@+id/map" />
|
||||
|
||||
</merge>
|
||||
11
android/java/app/src/main/res/values-v11/styles.xml
Normal file
11
android/java/app/src/main/res/values-v11/styles.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 11+. This theme completely replaces
|
||||
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||
<!-- API 11 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
12
android/java/app/src/main/res/values-v14/styles.xml
Normal file
12
android/java/app/src/main/res/values-v14/styles.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 14+. This theme completely replaces
|
||||
AppBaseTheme from BOTH res/values/styles.xml and
|
||||
res/values-v11/styles.xml on API 14+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||
<!-- API 14 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
6
android/java/app/src/main/res/values/strings.xml
Normal file
6
android/java/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">Mapbox GL</string>
|
||||
|
||||
</resources>
|
||||
20
android/java/app/src/main/res/values/styles.xml
Normal file
20
android/java/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
15
android/java/build.gradle
Normal file
15
android/java/build.gradle
Normal file
@@ -0,0 +1,15 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.13.2'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
BIN
android/java/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/java/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/java/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/java/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Wed Apr 10 15:27:10 PDT 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
|
||||
164
android/java/gradlew
vendored
Executable file
164
android/java/gradlew
vendored
Executable file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
android/java/gradlew.bat
vendored
Normal file
90
android/java/gradlew.bat
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
31
android/java/lib/build.gradle
Normal file
31
android/java/lib/build.gradle
Normal file
@@ -0,0 +1,31 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.mapbox.mapboxgl.lib"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 21
|
||||
|
||||
ndk {
|
||||
moduleName "NativeMapView"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
jniDebugBuild true
|
||||
}
|
||||
|
||||
release {
|
||||
runProguard false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "commons-io:commons-io:2.4"
|
||||
}
|
||||
3
android/java/lib/lint.xml
Normal file
3
android/java/lib/lint.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
</lint>
|
||||
12
android/java/lib/src/main/AndroidManifest.xml
Normal file
12
android/java/lib/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mapbox.mapboxgl.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public abstract class BaseGestureDetector {
|
||||
protected final Context mContext;
|
||||
protected boolean mGestureInProgress;
|
||||
|
||||
protected MotionEvent mPrevEvent;
|
||||
protected MotionEvent mCurrEvent;
|
||||
|
||||
protected float mCurrPressure;
|
||||
protected float mPrevPressure;
|
||||
protected long mTimeDelta;
|
||||
|
||||
/**
|
||||
* This value is the threshold ratio between the previous combined pressure
|
||||
* and the current combined pressure. When pressure decreases rapidly
|
||||
* between events the position values can often be imprecise, as it usually
|
||||
* indicates that the user is in the process of lifting a pointer off of the
|
||||
* device. This value was tuned experimentally.
|
||||
*/
|
||||
protected static final float PRESSURE_THRESHOLD = 0.67f;
|
||||
|
||||
public BaseGestureDetector(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* All gesture detectors need to be called through this method to be able to
|
||||
* detect gestures. This method delegates work to handler methods
|
||||
* (handleStartProgressEvent, handleInProgressEvent) implemented in
|
||||
* extending classes.
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
final int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (!mGestureInProgress) {
|
||||
handleStartProgressEvent(actionCode, event);
|
||||
} else {
|
||||
handleInProgressEvent(actionCode, event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the current event occurred when NO gesture is in progress
|
||||
* yet. The handling in this implementation may set the gesture in progress
|
||||
* (via mGestureInProgress) or out of progress
|
||||
*
|
||||
* @param actionCode
|
||||
* @param event
|
||||
*/
|
||||
protected abstract void handleStartProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
/**
|
||||
* Called when the current event occurred when a gesture IS in progress. The
|
||||
* handling in this implementation may set the gesture out of progress (via
|
||||
* mGestureInProgress).
|
||||
*
|
||||
* @param action
|
||||
* @param event
|
||||
*/
|
||||
protected abstract void handleInProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
final MotionEvent prev = mPrevEvent;
|
||||
|
||||
// Reset mCurrEvent
|
||||
if (mCurrEvent != null) {
|
||||
mCurrEvent.recycle();
|
||||
mCurrEvent = null;
|
||||
}
|
||||
mCurrEvent = MotionEvent.obtain(curr);
|
||||
|
||||
// Delta time
|
||||
mTimeDelta = curr.getEventTime() - prev.getEventTime();
|
||||
|
||||
// Pressure
|
||||
mCurrPressure = curr.getPressure(curr.getActionIndex());
|
||||
mPrevPressure = prev.getPressure(prev.getActionIndex());
|
||||
}
|
||||
|
||||
protected void resetState() {
|
||||
if (mPrevEvent != null) {
|
||||
mPrevEvent.recycle();
|
||||
mPrevEvent = null;
|
||||
}
|
||||
if (mCurrEvent != null) {
|
||||
mCurrEvent.recycle();
|
||||
mCurrEvent = null;
|
||||
}
|
||||
mGestureInProgress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if a gesture is currently in progress.
|
||||
*
|
||||
* @return {@code true} if a gesture is currently in progress, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isInProgress() {
|
||||
return mGestureInProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time difference in milliseconds between the previous accepted
|
||||
* GestureDetector event and the current GestureDetector event.
|
||||
*
|
||||
* @return Time difference since the last move event in milliseconds.
|
||||
*/
|
||||
public long getTimeDelta() {
|
||||
return mTimeDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the event time of the current GestureDetector event being
|
||||
* processed.
|
||||
*
|
||||
* @return Current GestureDetector event time in milliseconds.
|
||||
*/
|
||||
public long getEventTime() {
|
||||
return mCurrEvent.getEventTime();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public class MoveGestureDetector extends BaseGestureDetector {
|
||||
|
||||
/**
|
||||
* Listener which must be implemented which is used by MoveGestureDetector
|
||||
* to perform callbacks to any implementing class which is registered to a
|
||||
* MoveGestureDetector via the constructor.
|
||||
*
|
||||
* @see MoveGestureDetector.SimpleOnMoveGestureListener
|
||||
*/
|
||||
public interface OnMoveGestureListener {
|
||||
public boolean onMove(MoveGestureDetector detector);
|
||||
|
||||
public boolean onMoveBegin(MoveGestureDetector detector);
|
||||
|
||||
public void onMoveEnd(MoveGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class which may be extended and where the methods may be
|
||||
* implemented. This way it is not necessary to implement all methods of
|
||||
* OnMoveGestureListener.
|
||||
*/
|
||||
public static class SimpleOnMoveGestureListener implements
|
||||
OnMoveGestureListener {
|
||||
public boolean onMove(MoveGestureDetector detector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onMoveBegin(MoveGestureDetector detector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onMoveEnd(MoveGestureDetector detector) {
|
||||
// Do nothing, overridden implementation may be used
|
||||
}
|
||||
}
|
||||
|
||||
private static final PointF FOCUS_DELTA_ZERO = new PointF();
|
||||
|
||||
private final OnMoveGestureListener mListener;
|
||||
|
||||
private PointF mCurrFocusInternal;
|
||||
private PointF mPrevFocusInternal;
|
||||
private PointF mFocusExternal = new PointF();
|
||||
private PointF mFocusDeltaExternal = new PointF();
|
||||
|
||||
public MoveGestureDetector(Context context, OnMoveGestureListener listener) {
|
||||
super(context);
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
resetState(); // In case we missed an UP/CANCEL event
|
||||
|
||||
mPrevEvent = MotionEvent.obtain(event);
|
||||
mTimeDelta = 0;
|
||||
|
||||
updateStateByEvent(event);
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mGestureInProgress = mListener.onMoveBegin(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mListener.onMoveEnd(this);
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateStateByEvent(event);
|
||||
|
||||
// Only accept the event if our relative pressure is within
|
||||
// a certain limit. This can help filter shaky data as a
|
||||
// finger is lifted.
|
||||
if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
|
||||
final boolean updatePrevious = mListener.onMove(this);
|
||||
if (updatePrevious) {
|
||||
mPrevEvent.recycle();
|
||||
mPrevEvent = MotionEvent.obtain(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
super.updateStateByEvent(curr);
|
||||
|
||||
final MotionEvent prev = mPrevEvent;
|
||||
|
||||
// Focus intenal
|
||||
mCurrFocusInternal = determineFocalPoint(curr);
|
||||
mPrevFocusInternal = determineFocalPoint(prev);
|
||||
|
||||
// Focus external
|
||||
// - Prevent skipping of focus delta when a finger is added or removed
|
||||
boolean mSkipNextMoveEvent = prev.getPointerCount() != curr
|
||||
.getPointerCount();
|
||||
mFocusDeltaExternal = mSkipNextMoveEvent ? FOCUS_DELTA_ZERO
|
||||
: new PointF(mCurrFocusInternal.x - mPrevFocusInternal.x,
|
||||
mCurrFocusInternal.y - mPrevFocusInternal.y);
|
||||
|
||||
// - Don't directly use mFocusInternal (or skipping will occur). Add
|
||||
// unskipped delta values to mFocusExternal instead.
|
||||
mFocusExternal.x += mFocusDeltaExternal.x;
|
||||
mFocusExternal.y += mFocusDeltaExternal.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine (multi)finger focal point (a.k.a. center point between all
|
||||
* fingers)
|
||||
*
|
||||
* @param MotionEvent
|
||||
* e
|
||||
* @return PointF focal point
|
||||
*/
|
||||
private PointF determineFocalPoint(MotionEvent e) {
|
||||
// Number of fingers on screen
|
||||
final int pCount = e.getPointerCount();
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
for (int i = 0; i < pCount; i++) {
|
||||
x += e.getX(i);
|
||||
y += e.getY(i);
|
||||
}
|
||||
|
||||
return new PointF(x / pCount, y / pCount);
|
||||
}
|
||||
|
||||
public float getFocusX() {
|
||||
return mFocusExternal.x;
|
||||
}
|
||||
|
||||
public float getFocusY() {
|
||||
return mFocusExternal.y;
|
||||
}
|
||||
|
||||
public PointF getFocusDelta() {
|
||||
return mFocusDeltaExternal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public class RotateGestureDetector extends TwoFingerGestureDetector {
|
||||
|
||||
/**
|
||||
* Listener which must be implemented which is used by RotateGestureDetector
|
||||
* to perform callbacks to any implementing class which is registered to a
|
||||
* RotateGestureDetector via the constructor.
|
||||
*
|
||||
* @see RotateGestureDetector.SimpleOnRotateGestureListener
|
||||
*/
|
||||
public interface OnRotateGestureListener {
|
||||
public boolean onRotate(RotateGestureDetector detector);
|
||||
|
||||
public boolean onRotateBegin(RotateGestureDetector detector);
|
||||
|
||||
public void onRotateEnd(RotateGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class which may be extended and where the methods may be
|
||||
* implemented. This way it is not necessary to implement all methods of
|
||||
* OnRotateGestureListener.
|
||||
*/
|
||||
public static class SimpleOnRotateGestureListener implements
|
||||
OnRotateGestureListener {
|
||||
public boolean onRotate(RotateGestureDetector detector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onRotateBegin(RotateGestureDetector detector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onRotateEnd(RotateGestureDetector detector) {
|
||||
// Do nothing, overridden implementation may be used
|
||||
}
|
||||
}
|
||||
|
||||
private final OnRotateGestureListener mListener;
|
||||
private boolean mSloppyGesture;
|
||||
|
||||
public RotateGestureDetector(Context context,
|
||||
OnRotateGestureListener listener) {
|
||||
super(context);
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
// At least the second finger is on screen now
|
||||
|
||||
resetState(); // In case we missed an UP/CANCEL event
|
||||
mPrevEvent = MotionEvent.obtain(event);
|
||||
mTimeDelta = 0;
|
||||
|
||||
updateStateByEvent(event);
|
||||
|
||||
// See if we have a sloppy gesture
|
||||
mSloppyGesture = isSloppyGesture(event);
|
||||
if (!mSloppyGesture) {
|
||||
// No, start gesture now
|
||||
mGestureInProgress = mListener.onRotateBegin(this);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!mSloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
// See if we still have a sloppy gesture
|
||||
mSloppyGesture = isSloppyGesture(event);
|
||||
if (!mSloppyGesture) {
|
||||
// No, start normal gesture now
|
||||
mGestureInProgress = mListener.onRotateBegin(this);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (!mSloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
// Gesture ended but
|
||||
updateStateByEvent(event);
|
||||
|
||||
if (!mSloppyGesture) {
|
||||
mListener.onRotateEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!mSloppyGesture) {
|
||||
mListener.onRotateEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateStateByEvent(event);
|
||||
|
||||
// Only accept the event if our relative pressure is within
|
||||
// a certain limit. This can help filter shaky data as a
|
||||
// finger is lifted.
|
||||
if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
|
||||
final boolean updatePrevious = mListener.onRotate(this);
|
||||
if (updatePrevious) {
|
||||
mPrevEvent.recycle();
|
||||
mPrevEvent = MotionEvent.obtain(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetState() {
|
||||
super.resetState();
|
||||
mSloppyGesture = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rotation difference from the previous rotate event to the
|
||||
* current event.
|
||||
*
|
||||
* @return The current rotation //difference in degrees.
|
||||
*/
|
||||
public float getRotationDegreesDelta() {
|
||||
double diffRadians = Math.atan2(mPrevFingerDiffY, mPrevFingerDiffX)
|
||||
- Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX);
|
||||
return (float) (diffRadians * 180.0 / Math.PI);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Robert Nordan (robert.nordan@norkart.no)
|
||||
*
|
||||
* Copyright (c) 2013, Norkart AS
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public class ShoveGestureDetector extends TwoFingerGestureDetector {
|
||||
|
||||
/**
|
||||
* Listener which must be implemented which is used by ShoveGestureDetector
|
||||
* to perform callbacks to any implementing class which is registered to a
|
||||
* ShoveGestureDetector via the constructor.
|
||||
*
|
||||
* @see ShoveGestureDetector.SimpleOnShoveGestureListener
|
||||
*/
|
||||
public interface OnShoveGestureListener {
|
||||
public boolean onShove(ShoveGestureDetector detector);
|
||||
|
||||
public boolean onShoveBegin(ShoveGestureDetector detector);
|
||||
|
||||
public void onShoveEnd(ShoveGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class which may be extended and where the methods may be
|
||||
* implemented. This way it is not necessary to implement all methods of
|
||||
* OnShoveGestureListener.
|
||||
*/
|
||||
public static class SimpleOnShoveGestureListener implements
|
||||
OnShoveGestureListener {
|
||||
public boolean onShove(ShoveGestureDetector detector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onShoveBegin(ShoveGestureDetector detector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onShoveEnd(ShoveGestureDetector detector) {
|
||||
// Do nothing, overridden implementation may be used
|
||||
}
|
||||
}
|
||||
|
||||
private float mPrevAverageY;
|
||||
private float mCurrAverageY;
|
||||
|
||||
private final OnShoveGestureListener mListener;
|
||||
private boolean mSloppyGesture;
|
||||
|
||||
public ShoveGestureDetector(Context context, OnShoveGestureListener listener) {
|
||||
super(context);
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
// At least the second finger is on screen now
|
||||
|
||||
resetState(); // In case we missed an UP/CANCEL event
|
||||
mPrevEvent = MotionEvent.obtain(event);
|
||||
mTimeDelta = 0;
|
||||
|
||||
updateStateByEvent(event);
|
||||
|
||||
// See if we have a sloppy gesture
|
||||
mSloppyGesture = isSloppyGesture(event);
|
||||
if (!mSloppyGesture) {
|
||||
// No, start gesture now
|
||||
mGestureInProgress = mListener.onShoveBegin(this);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!mSloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
// See if we still have a sloppy gesture
|
||||
mSloppyGesture = isSloppyGesture(event);
|
||||
if (!mSloppyGesture) {
|
||||
// No, start normal gesture now
|
||||
mGestureInProgress = mListener.onShoveBegin(this);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (!mSloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
// Gesture ended but
|
||||
updateStateByEvent(event);
|
||||
|
||||
if (!mSloppyGesture) {
|
||||
mListener.onShoveEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!mSloppyGesture) {
|
||||
mListener.onShoveEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateStateByEvent(event);
|
||||
|
||||
// Only accept the event if our relative pressure is within
|
||||
// a certain limit. This can help filter shaky data as a
|
||||
// finger is lifted. Also check that shove is meaningful.
|
||||
if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD
|
||||
&& Math.abs(getShovePixelsDelta()) > 0.5f) {
|
||||
final boolean updatePrevious = mListener.onShove(this);
|
||||
if (updatePrevious) {
|
||||
mPrevEvent.recycle();
|
||||
mPrevEvent = MotionEvent.obtain(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetState() {
|
||||
super.resetState();
|
||||
mSloppyGesture = false;
|
||||
mPrevAverageY = 0.0f;
|
||||
mCurrAverageY = 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
super.updateStateByEvent(curr);
|
||||
|
||||
final MotionEvent prev = mPrevEvent;
|
||||
float py0 = prev.getY(0);
|
||||
float py1 = prev.getY(1);
|
||||
mPrevAverageY = (py0 + py1) / 2.0f;
|
||||
|
||||
float cy0 = curr.getY(0);
|
||||
float cy1 = curr.getY(1);
|
||||
mCurrAverageY = (cy0 + cy1) / 2.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSloppyGesture(MotionEvent event) {
|
||||
boolean sloppy = super.isSloppyGesture(event);
|
||||
if (sloppy)
|
||||
return true;
|
||||
|
||||
// If it's not traditionally sloppy, we check if the angle between
|
||||
// fingers
|
||||
// is acceptable.
|
||||
double angle = Math.abs(Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX));
|
||||
// about 20 degrees, left or right
|
||||
return !((0.0f < angle && angle < 0.35f) || 2.79f < angle
|
||||
&& angle < Math.PI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the distance in pixels from the previous shove event to the
|
||||
* current event.
|
||||
*
|
||||
* @return The current distance in pixels.
|
||||
*/
|
||||
public float getShovePixelsDelta() {
|
||||
return mCurrAverageY - mPrevAverageY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public abstract class TwoFingerGestureDetector extends BaseGestureDetector {
|
||||
|
||||
private final float mEdgeSlop;
|
||||
private float mRightSlopEdge;
|
||||
private float mBottomSlopEdge;
|
||||
|
||||
protected float mPrevFingerDiffX;
|
||||
protected float mPrevFingerDiffY;
|
||||
protected float mCurrFingerDiffX;
|
||||
protected float mCurrFingerDiffY;
|
||||
|
||||
private float mCurrLen;
|
||||
private float mPrevLen;
|
||||
|
||||
private PointF mFocus;
|
||||
|
||||
public TwoFingerGestureDetector(Context context) {
|
||||
super(context);
|
||||
|
||||
ViewConfiguration config = ViewConfiguration.get(context);
|
||||
mEdgeSlop = config.getScaledEdgeSlop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract void handleStartProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
@Override
|
||||
protected abstract void handleInProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
super.updateStateByEvent(curr);
|
||||
|
||||
final MotionEvent prev = mPrevEvent;
|
||||
|
||||
mCurrLen = -1;
|
||||
mPrevLen = -1;
|
||||
|
||||
// Previous
|
||||
final float px0 = prev.getX(0);
|
||||
final float py0 = prev.getY(0);
|
||||
final float px1 = prev.getX(1);
|
||||
final float py1 = prev.getY(1);
|
||||
final float pvx = px1 - px0;
|
||||
final float pvy = py1 - py0;
|
||||
mPrevFingerDiffX = pvx;
|
||||
mPrevFingerDiffY = pvy;
|
||||
|
||||
// Current
|
||||
final float cx0 = curr.getX(0);
|
||||
final float cy0 = curr.getY(0);
|
||||
final float cx1 = curr.getX(1);
|
||||
final float cy1 = curr.getY(1);
|
||||
final float cvx = cx1 - cx0;
|
||||
final float cvy = cy1 - cy0;
|
||||
mCurrFingerDiffX = cvx;
|
||||
mCurrFingerDiffY = cvy;
|
||||
mFocus = determineFocalPoint(curr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current distance between the two pointers forming the gesture
|
||||
* in progress.
|
||||
*
|
||||
* @return Distance between pointers in pixels.
|
||||
*/
|
||||
public float getCurrentSpan() {
|
||||
if (mCurrLen == -1) {
|
||||
final float cvx = mCurrFingerDiffX;
|
||||
final float cvy = mCurrFingerDiffY;
|
||||
mCurrLen = (float) Math.sqrt(cvx * cvx + cvy * cvy);
|
||||
}
|
||||
return mCurrLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the previous distance between the two pointers forming the gesture
|
||||
* in progress.
|
||||
*
|
||||
* @return Previous distance between pointers in pixels.
|
||||
*/
|
||||
public float getPreviousSpan() {
|
||||
if (mPrevLen == -1) {
|
||||
final float pvx = mPrevFingerDiffX;
|
||||
final float pvy = mPrevFingerDiffY;
|
||||
mPrevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy);
|
||||
}
|
||||
return mPrevLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* MotionEvent has no getRawX(int) method; simulate it pending future API
|
||||
* approval.
|
||||
*
|
||||
* @param event
|
||||
* @param pointerIndex
|
||||
* @return
|
||||
*/
|
||||
protected static float getRawX(MotionEvent event, int pointerIndex) {
|
||||
float offset = event.getX() - event.getRawX();
|
||||
if (pointerIndex < event.getPointerCount()) {
|
||||
return event.getX(pointerIndex) + offset;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* MotionEvent has no getRawY(int) method; simulate it pending future API
|
||||
* approval.
|
||||
*
|
||||
* @param event
|
||||
* @param pointerIndex
|
||||
* @return
|
||||
*/
|
||||
protected static float getRawY(MotionEvent event, int pointerIndex) {
|
||||
float offset = event.getY() - event.getRawY();
|
||||
if (pointerIndex < event.getPointerCount()) {
|
||||
return event.getY(pointerIndex) + offset;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we have a sloppy gesture. Sloppy gestures can happen if the edge
|
||||
* of the user's hand is touching the screen, for example.
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
protected boolean isSloppyGesture(MotionEvent event) {
|
||||
// As orientation can change, query the metrics in touch down
|
||||
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
|
||||
mRightSlopEdge = metrics.widthPixels - mEdgeSlop;
|
||||
mBottomSlopEdge = metrics.heightPixels - mEdgeSlop;
|
||||
|
||||
final float edgeSlop = mEdgeSlop;
|
||||
final float rightSlop = mRightSlopEdge;
|
||||
final float bottomSlop = mBottomSlopEdge;
|
||||
|
||||
final float x0 = event.getRawX();
|
||||
final float y0 = event.getRawY();
|
||||
final float x1 = getRawX(event, 1);
|
||||
final float y1 = getRawY(event, 1);
|
||||
|
||||
boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlop
|
||||
|| y0 > bottomSlop;
|
||||
boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlop
|
||||
|| y1 > bottomSlop;
|
||||
|
||||
if (p0sloppy && p1sloppy) {
|
||||
return true;
|
||||
} else if (p0sloppy) {
|
||||
return true;
|
||||
} else if (p1sloppy) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine (multi)finger focal point (a.k.a. center point between all
|
||||
* fingers)
|
||||
*
|
||||
* @param MotionEvent
|
||||
* e
|
||||
* @return PointF focal point
|
||||
*/
|
||||
public static PointF determineFocalPoint(MotionEvent e) {
|
||||
// Number of fingers on screen
|
||||
final int pCount = e.getPointerCount();
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
for (int i = 0; i < pCount; i++) {
|
||||
x += e.getX(i);
|
||||
y += e.getY(i);
|
||||
}
|
||||
|
||||
return new PointF(x / pCount, y / pCount);
|
||||
}
|
||||
|
||||
public float getFocusX() {
|
||||
return mFocus.x;
|
||||
}
|
||||
|
||||
public float getFocusY() {
|
||||
return mFocus.y;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.mapbox.mapboxgl.lib;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class LonLat implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<LonLat> CREATOR = new Parcelable.Creator<LonLat>() {
|
||||
public LonLat createFromParcel(Parcel in) {
|
||||
return new LonLat(in);
|
||||
}
|
||||
|
||||
public LonLat[] newArray(int size) {
|
||||
return new LonLat[size];
|
||||
}
|
||||
};
|
||||
|
||||
private double lon;
|
||||
private double lat;
|
||||
|
||||
public LonLat(double lon, double lat) {
|
||||
this.lon = lon;
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
private LonLat(Parcel in) {
|
||||
lon = in.readDouble();
|
||||
lat = in.readDouble();
|
||||
}
|
||||
|
||||
public double getLon() {
|
||||
return lon;
|
||||
}
|
||||
|
||||
public void setLon(double lon) {
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public double getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public void setLat(double lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(lat);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(lon);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
LonLat other = (LonLat) obj;
|
||||
if (Double.doubleToLongBits(lat) != Double.doubleToLongBits(other.lat))
|
||||
return false;
|
||||
if (Double.doubleToLongBits(lon) != Double.doubleToLongBits(other.lon))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LonLat [lon=" + lon + ", lat=" + lat + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeDouble(lon);
|
||||
out.writeDouble(lat);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.mapbox.mapboxgl.lib;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class LonLatZoom implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<LonLatZoom> CREATOR = new Parcelable.Creator<LonLatZoom>() {
|
||||
public LonLatZoom createFromParcel(Parcel in) {
|
||||
return new LonLatZoom(in);
|
||||
}
|
||||
|
||||
public LonLatZoom[] newArray(int size) {
|
||||
return new LonLatZoom[size];
|
||||
}
|
||||
};
|
||||
|
||||
private double lon;
|
||||
private double lat;
|
||||
private double zoom;
|
||||
|
||||
public LonLatZoom(double lon, double lat, double zoom) {
|
||||
this.lon = lon;
|
||||
this.lat = lat;
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
public LonLatZoom(LonLat lonLat, double zoom) {
|
||||
this.lon = lonLat.getLon();
|
||||
this.lat = lonLat.getLat();
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
private LonLatZoom(Parcel in) {
|
||||
lon = in.readDouble();
|
||||
lat = in.readDouble();
|
||||
zoom = in.readDouble();
|
||||
}
|
||||
|
||||
public double getLon() {
|
||||
return lon;
|
||||
}
|
||||
|
||||
public void setLon(double lon) {
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public double getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public void setLat(double lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
public double getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
|
||||
public void setZoom(double zoom) {
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
public LonLat getLonLat() {
|
||||
return new LonLat(lon, lat);
|
||||
}
|
||||
|
||||
public void setLonLat(LonLat lonLat) {
|
||||
this.lon = lonLat.getLon();
|
||||
this.lat = lonLat.getLat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(lat);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(lon);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(zoom);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
LonLatZoom other = (LonLatZoom) obj;
|
||||
if (Double.doubleToLongBits(lat) != Double.doubleToLongBits(other.lat))
|
||||
return false;
|
||||
if (Double.doubleToLongBits(lon) != Double.doubleToLongBits(other.lon))
|
||||
return false;
|
||||
if (Double.doubleToLongBits(zoom) != Double
|
||||
.doubleToLongBits(other.zoom))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LonLatZoom [lon=" + lon + ", lat=" + lat + ", zoom=" + zoom
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeDouble(lon);
|
||||
out.writeDouble(lat);
|
||||
out.writeDouble(zoom);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.mapbox.mapboxgl.lib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
public class MapFragment extends Fragment {
|
||||
|
||||
//
|
||||
// Static members
|
||||
//
|
||||
|
||||
// Tag used for logging
|
||||
private static final String TAG = "MapFragment";
|
||||
|
||||
// The map
|
||||
private MapView mMapView;
|
||||
|
||||
// The style attrs to load into the map
|
||||
AttributeSet mAttrs;
|
||||
|
||||
//
|
||||
// Lifecycle events
|
||||
//
|
||||
|
||||
// Called when the fragment is created
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
Log.v(TAG, "onCreateView");
|
||||
|
||||
// Create the map
|
||||
mMapView = new MapView(getActivity());
|
||||
|
||||
// Load the attributes
|
||||
TypedArray typedArray = getActivity().obtainStyledAttributes(mAttrs,
|
||||
R.styleable.MapFragment, 0, 0);
|
||||
try {
|
||||
double centerLongitude = typedArray.getFloat(
|
||||
R.styleable.MapFragment_centerLongitude, 0.0f);
|
||||
double centerLatitude = typedArray.getFloat(
|
||||
R.styleable.MapFragment_centerLatitude, 0.0f);
|
||||
LonLat centerCoordinate = new LonLat(centerLongitude,
|
||||
centerLatitude);
|
||||
mMapView.setCenterCoordinate(centerCoordinate);
|
||||
mMapView.setDirection(typedArray.getFloat(
|
||||
R.styleable.MapFragment_direction, 0.0f));
|
||||
mMapView.setZoomLevel(typedArray.getFloat(
|
||||
R.styleable.MapFragment_zoomLevel, 0.0f));
|
||||
mMapView.setZoomEnabled(typedArray.getBoolean(
|
||||
R.styleable.MapFragment_zoomEnabled, true));
|
||||
mMapView.setScrollEnabled(typedArray.getBoolean(
|
||||
R.styleable.MapFragment_scrollEnabled, true));
|
||||
mMapView.setRotateEnabled(typedArray.getBoolean(
|
||||
R.styleable.MapFragment_rotateEnabled, true));
|
||||
mMapView.setDebugActive(typedArray.getBoolean(
|
||||
R.styleable.MapFragment_debugActive, false));
|
||||
} finally {
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
// Need to pass on any saved state to the map
|
||||
mMapView.onCreate(savedInstanceState);
|
||||
|
||||
// Return the map as the root view
|
||||
return mMapView;
|
||||
}
|
||||
|
||||
// Called when the fragment is destroyed
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
Log.v(TAG, "onDestroyView");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onDestroy();
|
||||
mMapView = null;
|
||||
}
|
||||
|
||||
// Called to load any fragment attributes set in the activity's layout
|
||||
@Override
|
||||
public void onInflate(Activity activity, AttributeSet attrs,
|
||||
Bundle savedInstanceState) {
|
||||
super.onInflate(activity, attrs, savedInstanceState);
|
||||
Log.v(TAG, "onInflate");
|
||||
|
||||
// TODO seems this is called before onCreateView
|
||||
// Kinda strange, is it supposed to be like this?
|
||||
// Need to keep a copy of these and pass on to MapView later
|
||||
|
||||
mAttrs = attrs;
|
||||
}
|
||||
|
||||
// Called when the fragment is visible
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Log.v(TAG, "onStart");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onStart();
|
||||
}
|
||||
|
||||
// Called when the fragment is invisible
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
Log.v(TAG, "onStop");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onStop();
|
||||
}
|
||||
|
||||
// Called when the fragment is in the background
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
Log.v(TAG, "onPause");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onPause();
|
||||
}
|
||||
|
||||
// Called when the fragment is no longer in the background
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Log.v(TAG, "onResume");
|
||||
|
||||
// Need to pass on to view
|
||||
mMapView.onResume();
|
||||
}
|
||||
|
||||
// Called before fragment is destroyed
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
Log.v(TAG, "onSaveInstanceState");
|
||||
|
||||
// Need to retrieve any saved state from the map
|
||||
mMapView.onSaveInstanceState(outState);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
1171
android/java/lib/src/main/java/com/mapbox/mapboxgl/lib/MapView.java
Normal file
1171
android/java/lib/src/main/java/com/mapbox/mapboxgl/lib/MapView.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,476 @@
|
||||
package com.mapbox.mapboxgl.lib;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
// Class that wraps the native methods for convenience
|
||||
class NativeMapView {
|
||||
|
||||
//
|
||||
// Static members
|
||||
//
|
||||
|
||||
// Tag used for logging
|
||||
private static final String TAG = "NativeMapView";
|
||||
|
||||
//
|
||||
// Instance members
|
||||
//
|
||||
|
||||
// Holds the pointer to JNI NativeMapView
|
||||
private long mNativeMapViewPtr = 0;
|
||||
|
||||
// Used for callbacks
|
||||
private MapView mMapView;
|
||||
|
||||
//
|
||||
// Static methods
|
||||
//
|
||||
|
||||
static {
|
||||
System.loadLibrary("mapbox-gl");
|
||||
}
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
|
||||
public NativeMapView(MapView mapView, String defaultStyleJSON) {
|
||||
mMapView = mapView;
|
||||
|
||||
// Create the NativeMapView
|
||||
mNativeMapViewPtr = nativeCreate(defaultStyleJSON);
|
||||
}
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
public void initializeDisplay() {
|
||||
nativeInitializeDisplay(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void terminateDisplay() {
|
||||
nativeTerminateDisplay(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void initializeContext() {
|
||||
nativeInitializeContext(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void terminateContext() {
|
||||
nativeTerminateContext(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void createSurface(Surface surface) {
|
||||
nativeCreateSurface(mNativeMapViewPtr, surface);
|
||||
}
|
||||
|
||||
public void destroySurface() {
|
||||
nativeDestroySurface(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
nativeStart(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
nativeStop(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void rerender() {
|
||||
nativeRerender(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
nativeUpdate(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
nativeCleanup(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void resize(int width, int height) {
|
||||
resize(width, height, 1.0f);
|
||||
}
|
||||
|
||||
public void resize(int width, int height, float ratio) {
|
||||
if (width < 0) {
|
||||
throw new IllegalArgumentException("width cannot be negative.");
|
||||
}
|
||||
|
||||
if (height < 0) {
|
||||
throw new IllegalArgumentException("height cannot be negative.");
|
||||
}
|
||||
|
||||
if (width > 65535) {
|
||||
throw new IllegalArgumentException(
|
||||
"width cannot be greater than 65535.");
|
||||
}
|
||||
|
||||
if (height > 65535) {
|
||||
throw new IllegalArgumentException(
|
||||
"height cannot be greater than 65535.");
|
||||
}
|
||||
|
||||
nativeResize(mNativeMapViewPtr, width, height, ratio);
|
||||
}
|
||||
|
||||
public void resize(int width, int height, float ratio, int fbWidth,
|
||||
int fbHeight) {
|
||||
if (width < 0) {
|
||||
throw new IllegalArgumentException("width cannot be negative.");
|
||||
}
|
||||
|
||||
if (height < 0) {
|
||||
throw new IllegalArgumentException("height cannot be negative.");
|
||||
}
|
||||
|
||||
if (fbWidth < 0) {
|
||||
throw new IllegalArgumentException("fbWidth cannot be negative.");
|
||||
}
|
||||
|
||||
if (fbHeight < 0) {
|
||||
throw new IllegalArgumentException("fbHeight cannot be negative.");
|
||||
}
|
||||
|
||||
if (fbWidth > 65535) {
|
||||
throw new IllegalArgumentException(
|
||||
"fbWidth cannot be greater than 65535.");
|
||||
}
|
||||
|
||||
if (fbHeight > 65535) {
|
||||
throw new IllegalArgumentException(
|
||||
"fbHeight cannot be greater than 65535.");
|
||||
}
|
||||
nativeResize(mNativeMapViewPtr, width, height, ratio, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
public void setAppliedClasses(Set<String> appliedClasses) {
|
||||
nativeSetAppliedClasses(mNativeMapViewPtr, appliedClasses);
|
||||
}
|
||||
|
||||
public Set<String> getAppliedClasses() {
|
||||
return nativeGetAppliedClasses(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void setDefaultTransitionDuration() {
|
||||
setDefaultTransitionDuration(0);
|
||||
}
|
||||
|
||||
public void setDefaultTransitionDuration(long durationMilliseconds) {
|
||||
if (durationMilliseconds < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"durationMilliseconds cannot be negative.");
|
||||
}
|
||||
|
||||
nativeSetDefaultTransitionDuration(mNativeMapViewPtr,
|
||||
durationMilliseconds);
|
||||
}
|
||||
|
||||
public void setStyleJSON(String newStyleJSON) {
|
||||
nativeSetStyleJSON(mNativeMapViewPtr, newStyleJSON);
|
||||
}
|
||||
|
||||
public String getStyleJSON() {
|
||||
return nativeGetStyleJSON(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void cancelTransitions() {
|
||||
nativeCancelTransitions(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void moveBy(double dx, double dy) {
|
||||
moveBy(dx, dy, 0.0);
|
||||
}
|
||||
|
||||
public void moveBy(double dx, double dy, double duration) {
|
||||
nativeMoveBy(mNativeMapViewPtr, dx, dy, duration);
|
||||
}
|
||||
|
||||
public void setLonLat(LonLat lonLat) {
|
||||
setLonLat(lonLat, 0.0);
|
||||
}
|
||||
|
||||
public void setLonLat(LonLat lonLat, double duration) {
|
||||
nativeSetLonLat(mNativeMapViewPtr, lonLat, duration);
|
||||
}
|
||||
|
||||
public LonLat getLonLat() {
|
||||
return nativeGetLonLat(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void startPanning() {
|
||||
nativeStartPanning(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void stopPanning() {
|
||||
nativeStopPanning(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void resetPosition() {
|
||||
nativeResetPosition(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void scaleBy(double ds) {
|
||||
scaleBy(ds, -1.0, -1.0);
|
||||
}
|
||||
|
||||
public void scaleBy(double ds, double cx, double cy) {
|
||||
scaleBy(ds, cx, cy, 0.0);
|
||||
}
|
||||
|
||||
public void scaleBy(double ds, double cx, double cy, double duration) {
|
||||
nativeScaleBy(mNativeMapViewPtr, ds, cx, cy, duration);
|
||||
}
|
||||
|
||||
public void setScale(double scale) {
|
||||
setScale(scale, -1.0, -1.0);
|
||||
}
|
||||
|
||||
public void setScale(double scale, double cx, double cy) {
|
||||
setScale(scale, cx, cy, 0.0);
|
||||
}
|
||||
|
||||
public void setScale(double scale, double cx, double cy, double duration) {
|
||||
nativeSetScale(mNativeMapViewPtr, scale, cx, cy, duration);
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return nativeGetScale(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void setZoom(double zoom) {
|
||||
setZoom(zoom, 0.0);
|
||||
}
|
||||
|
||||
public void setZoom(double zoom, double duration) {
|
||||
nativeSetZoom(mNativeMapViewPtr, zoom, duration);
|
||||
}
|
||||
|
||||
public double getZoom() {
|
||||
return nativeGetZoom(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void setLonLatZoom(LonLatZoom lonLatZoom) {
|
||||
setLonLatZoom(lonLatZoom, 0.0);
|
||||
}
|
||||
|
||||
public void setLonLatZoom(LonLatZoom lonLatZoom, double duration) {
|
||||
nativeSetLonLatZoom(mNativeMapViewPtr, lonLatZoom, duration);
|
||||
}
|
||||
|
||||
public LonLatZoom getLonLatZoom() {
|
||||
return nativeGetLonLatZoom(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void resetZoom() {
|
||||
nativeResetZoom(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void startScaling() {
|
||||
nativeStartScaling(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void stopScaling() {
|
||||
nativeStopScaling(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public double getMinZoom() {
|
||||
return nativeGetMinZoom(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public double getMaxZoom() {
|
||||
return nativeGetMaxZoom(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void rotateBy(double sx, double sy, double ex, double ey) {
|
||||
rotateBy(sx, sy, ex, ey, 0.0);
|
||||
}
|
||||
|
||||
public void rotateBy(double sx, double sy, double ex, double ey,
|
||||
double duration) {
|
||||
nativeRotateBy(mNativeMapViewPtr, sx, sy, ex, ey, duration);
|
||||
}
|
||||
|
||||
public void setBearing(double degrees) {
|
||||
setBearing(degrees, 0.0);
|
||||
}
|
||||
|
||||
public void setBearing(double degrees, double duration) {
|
||||
nativeSetBearing(mNativeMapViewPtr, degrees, duration);
|
||||
}
|
||||
|
||||
public void setBearing(double degrees, double cx, double cy) {
|
||||
nativeSetBearing(mNativeMapViewPtr, degrees, cx, cy);
|
||||
}
|
||||
|
||||
public double getBearing() {
|
||||
return nativeGetBearing(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void resetNorth() {
|
||||
nativeResetNorth(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void startRotating() {
|
||||
nativeStartRotating(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void stopRotating() {
|
||||
nativeStopRotating(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public boolean canRotate() {
|
||||
return nativeCanRotate(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void setDebug(boolean debug) {
|
||||
nativeSetDebug(mNativeMapViewPtr, debug);
|
||||
}
|
||||
|
||||
public void toggleDebug() {
|
||||
nativeToggleDebug(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public boolean getDebug() {
|
||||
return nativeGetDebug(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
//
|
||||
// Callbacks
|
||||
//
|
||||
|
||||
protected void onMapChanged() {
|
||||
Log.v(TAG, "onMapChanged");
|
||||
mMapView.onMapChanged();
|
||||
}
|
||||
|
||||
//
|
||||
// JNI methods
|
||||
//
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
nativeDestroy(mNativeMapViewPtr);
|
||||
mNativeMapViewPtr = 0;
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
private native long nativeCreate(String defaultStyleJSON);
|
||||
|
||||
private native void nativeDestroy(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeInitializeDisplay(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeTerminateDisplay(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeInitializeContext(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeTerminateContext(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeCreateSurface(long nativeMapViewPtr,
|
||||
Surface surface);
|
||||
|
||||
private native void nativeDestroySurface(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStart(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStop(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeRerender(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeUpdate(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeCleanup(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResize(long nativeMapViewPtr, int width,
|
||||
int height, float ratio);
|
||||
|
||||
private native void nativeResize(long nativeMapViewPtr, int width,
|
||||
int height, float ratio, int fbWidth, int fbHeight);
|
||||
|
||||
private native void nativeSetAppliedClasses(long nativeMapViewPtr,
|
||||
Set<String> appliedClasses);
|
||||
|
||||
private native Set<String> nativeGetAppliedClasses(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeSetDefaultTransitionDuration(
|
||||
long nativeMapViewPtr, long durationMilliseconds);
|
||||
|
||||
private native void nativeSetStyleJSON(long nativeMapViewPtr,
|
||||
String newStyleJSON);
|
||||
|
||||
private native String nativeGetStyleJSON(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeCancelTransitions(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeMoveBy(long nativeMapViewPtr, double dx,
|
||||
double dy, double duration);
|
||||
|
||||
private native void nativeSetLonLat(long nativeMapViewPtr, LonLat lonLat,
|
||||
double duration);
|
||||
|
||||
private native LonLat nativeGetLonLat(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStartPanning(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStopPanning(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResetPosition(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeScaleBy(long nativeMapViewPtr, double ds,
|
||||
double cx, double cy, double duration);
|
||||
|
||||
private native void nativeSetScale(long nativeMapViewPtr, double scale,
|
||||
double cx, double cy, double duration);
|
||||
|
||||
private native double nativeGetScale(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeSetZoom(long nativeMapViewPtr, double zoom,
|
||||
double duration);
|
||||
|
||||
private native double nativeGetZoom(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeSetLonLatZoom(long nativeMapViewPtr,
|
||||
LonLatZoom lonLatZoom, double duration);
|
||||
|
||||
private native LonLatZoom nativeGetLonLatZoom(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResetZoom(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStartScaling(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStopScaling(long nativeMapViewPtr);
|
||||
|
||||
private native double nativeGetMinZoom(long nativeMapViewPtr);
|
||||
|
||||
private native double nativeGetMaxZoom(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeRotateBy(long nativeMapViewPtr, double sx,
|
||||
double sy, double ex, double ey, double duration);
|
||||
|
||||
private native void nativeSetBearing(long nativeMapViewPtr, double degrees,
|
||||
double duration);
|
||||
|
||||
private native void nativeSetBearing(long nativeMapViewPtr, double degrees,
|
||||
double cx, double cy);
|
||||
|
||||
private native double nativeGetBearing(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResetNorth(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStartRotating(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeStopRotating(long nativeMapViewPtr);
|
||||
|
||||
private native boolean nativeCanRotate(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeSetDebug(long nativeMapViewPtr, boolean debug);
|
||||
|
||||
private native void nativeToggleDebug(long nativeMapViewPtr);
|
||||
|
||||
private native boolean nativeGetDebug(long nativeMapViewPtr);
|
||||
}
|
||||
1
android/java/lib/src/main/res/raw/style.min.js
vendored
Normal file
1
android/java/lib/src/main/res/raw/style.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
32
android/java/lib/src/main/res/values/attrs.xml
Normal file
32
android/java/lib/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<resources>
|
||||
<attr name="centerLongitude" format="float" />
|
||||
<attr name="centerLatitude" format="float" />
|
||||
<attr name="zoomLevel" format="float" />
|
||||
<attr name="direction" format="float" />
|
||||
<attr name="zoomEnabled" format="boolean" />
|
||||
<attr name="scrollEnabled" format="boolean" />
|
||||
<attr name="rotateEnabled" format="boolean" />
|
||||
<attr name="debugActive" format="boolean" />
|
||||
|
||||
<declare-styleable name="MapView">
|
||||
<attr name="centerLongitude" />
|
||||
<attr name="centerLatitude" />
|
||||
<attr name="zoomLevel" />
|
||||
<attr name="direction" />
|
||||
<attr name="zoomEnabled" />
|
||||
<attr name="scrollEnabled" />
|
||||
<attr name="rotateEnabled" />
|
||||
<attr name="debugActive" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MapFragment">
|
||||
<attr name="centerLongitude" />
|
||||
<attr name="centerLatitude" />
|
||||
<attr name="zoomLevel" />
|
||||
<attr name="direction" />
|
||||
<attr name="zoomEnabled" />
|
||||
<attr name="scrollEnabled" />
|
||||
<attr name="rotateEnabled" />
|
||||
<attr name="debugActive" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
3
android/java/lib/src/main/res/values/strings.xml
Normal file
3
android/java/lib/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
|
||||
</resources>
|
||||
2
android/java/settings.gradle
Normal file
2
android/java/settings.gradle
Normal file
@@ -0,0 +1,2 @@
|
||||
include ':app'
|
||||
include ':lib'
|
||||
50
android/mapboxgl-app.gyp
Normal file
50
android/mapboxgl-app.gyp
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
'includes': [
|
||||
'../gyp/common.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'androidapp',
|
||||
'product_name': 'mapbox-gl',
|
||||
'type': 'shared_library',
|
||||
'sources': [
|
||||
'./cpp/NativeMapView.cpp',
|
||||
'./cpp/JNI.cpp',
|
||||
],
|
||||
'cflags_cc': [
|
||||
'-I<(boost_root)/include',
|
||||
],
|
||||
'libraries': [
|
||||
'<@(openssl_static_libs)',
|
||||
'<@(curl_static_libs)',
|
||||
'<@(png_static_libs)',
|
||||
'<@(sqlite3_static_libs)',
|
||||
'<@(uv_static_libs)',
|
||||
'<@(nu_static_libs)',
|
||||
],
|
||||
'variables': {
|
||||
'ldflags': [
|
||||
'-llog -landroid -lEGL -lGLESv2 -lstdc++ -latomic '
|
||||
'<@(png_ldflags)',
|
||||
'<@(sqlite3_ldflags)',
|
||||
'<@(openssl_ldflags)',
|
||||
'<@(curl_ldflags)',
|
||||
'<@(zlib_ldflags)',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [ '<@(ldflags)' ],
|
||||
}
|
||||
}, {
|
||||
'libraries': [ '<@(ldflags)' ],
|
||||
}]
|
||||
],
|
||||
'dependencies': [
|
||||
'../mapboxgl.gyp:mbgl-standalone',
|
||||
'../mapboxgl.gyp:mbgl-android',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
10
configure
vendored
10
configure
vendored
@@ -26,6 +26,9 @@ case ${MASON_PLATFORM} in
|
||||
;;
|
||||
'android')
|
||||
SQLITE_VERSION=3.8.6
|
||||
LIBPNG_VERSION=1.6.13
|
||||
OPENSSL_VERSION=1.0.1i
|
||||
LIBCURL_VERSION=7.38.0
|
||||
LIBUV_VERSION=0.11.29
|
||||
ZLIB_VERSION=system
|
||||
BOOST_VERSION=1.57.0
|
||||
@@ -75,6 +78,13 @@ if [ ! -z ${BOOST_VERSION} ]; then
|
||||
CONFIG+=" 'boost_root': '$(mason prefix boost ${BOOST_VERSION})',"$LN
|
||||
fi
|
||||
|
||||
if [ ! -z ${OPENSSL_VERSION} ]; then
|
||||
mason install openssl ${OPENSSL_VERSION}
|
||||
CONFIG+=" 'openssl_static_libs': $(quote_flags $(mason static_libs openssl ${OPENSSL_VERSION})),"$LN
|
||||
CONFIG+=" 'openssl_cflags': $(quote_flags $(mason cflags openssl ${OPENSSL_VERSION})),"$LN
|
||||
CONFIG+=" 'openssl_ldflags': $(quote_flags $(mason ldflags openssl ${OPENSSL_VERSION})),"$LN
|
||||
fi
|
||||
|
||||
if [ ! -z ${LIBCURL_VERSION} ]; then
|
||||
mason install libcurl ${LIBCURL_VERSION}
|
||||
CONFIG+=" 'curl_static_libs': $(quote_flags $(mason static_libs libcurl ${LIBCURL_VERSION})),"$LN
|
||||
|
||||
69
gyp/mbgl-android.gypi
Normal file
69
gyp/mbgl-android.gypi
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
'targets': [
|
||||
{ 'target_name': 'mbgl-android',
|
||||
'product_name': 'mbgl-android',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'variables': {
|
||||
'cflags_cc': [
|
||||
'<@(png_cflags)',
|
||||
'<@(uv_cflags)',
|
||||
'<@(curl_cflags)',
|
||||
'<@(nu_cflags)',
|
||||
'-I<(boost_root)/include',
|
||||
],
|
||||
'cflags': [
|
||||
'<@(uv_cflags)',
|
||||
'<@(nu_cflags)',
|
||||
],
|
||||
'ldflags': [
|
||||
'<@(png_ldflags)',
|
||||
'<@(uv_ldflags)',
|
||||
'<@(curl_ldflags)',
|
||||
'<@(nu_ldflags)',
|
||||
],
|
||||
},
|
||||
'sources': [
|
||||
'../platform/android/cache_database_data.cpp',
|
||||
'../platform/android/log_android.cpp',
|
||||
'../platform/default/string_stdlib.cpp',
|
||||
'../platform/default/http_request_baton_curl.cpp',
|
||||
'../platform/default/image.cpp',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'<@(png_static_libs)',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
'xcode_settings': {
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '<@(cflags_cc)' ],
|
||||
'OTHER_CFLAGS': [ '<@(cflags)' ],
|
||||
}
|
||||
}, {
|
||||
'cflags_cc': [ '<@(cflags_cc)' ],
|
||||
'cflags': [ '<@(cflags)' ],
|
||||
}]
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
],
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [ '<@(ldflags)' ],
|
||||
}
|
||||
}, {
|
||||
'ldflags': [ '<@(ldflags)' ],
|
||||
}]
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -12,5 +12,9 @@
|
||||
'includes': ['mbgl-linux.gypi'],
|
||||
'variables': { 'platform_library': 'mbgl-linux' },
|
||||
}],
|
||||
['platform == "android"', {
|
||||
'includes': ['mbgl-android.gypi'],
|
||||
'variables': { 'platform_library': 'mbgl-android' },
|
||||
}],
|
||||
],
|
||||
}
|
||||
|
||||
13
platform/android/cache_database_data.cpp
Normal file
13
platform/android/cache_database_data.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace platform {
|
||||
|
||||
// Returns the path to the default cache database on this system.
|
||||
std::string defaultCacheDatabase() {
|
||||
// TODO need to use get cache dir from java
|
||||
return "/data/data/com.mapbox.mapboxgl.app/mbgl-cache.db";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
32
platform/android/log_android.cpp
Normal file
32
platform/android/log_android.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <mbgl/platform/default/log_stderr.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
// TODO use android logging
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, const std::string &msg) {
|
||||
std::cerr << "[" << severity << "] " << event << ": " << msg << std::endl;
|
||||
}
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, const char* format, ...) {
|
||||
std::cerr << "[" << severity << "] " << event << ": ";
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, int64_t code) {
|
||||
std::cerr << "[" << severity << "] " << event << ": (" << code << ")" << std::endl;
|
||||
}
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) {
|
||||
std::cerr << "[" << severity << "] " << event << ": (" << code << ") " << msg << std::endl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -266,7 +266,11 @@ void on_timeout(uv_timer_t *) {
|
||||
|
||||
void start_timeout(CURLM *, long timeout_ms, void *) {
|
||||
if (timeout_ms <= 0) {
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
on_timeout(&timeout, 0);
|
||||
#else
|
||||
on_timeout(&timeout);
|
||||
#endif
|
||||
} else {
|
||||
uv_timer_start(&timeout, on_timeout, timeout_ms, 0);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
set -o pipefail
|
||||
|
||||
if [[ "${MASON_PLATFORM}" == "android" ]]; then
|
||||
echo "debug: unpacking"
|
||||
#mapbox_time "unpacking NDK" \
|
||||
echo "debug: installing 7z"
|
||||
#mapbox_time "installing 7z" \
|
||||
MASON_PLATFORM= ./.mason/mason install 7z 9.20
|
||||
|
||||
echo "debug: setting 7z path"
|
||||
@@ -18,10 +18,31 @@ if [[ "${MASON_PLATFORM}" == "android" ]]; then
|
||||
echo "debug: chmod NDK"
|
||||
chmod a+x ./android-ndk-r10c-linux-x86_64.bin
|
||||
|
||||
echo "debug: upacking NDK"
|
||||
echo "debug: unpacking NDK"
|
||||
#mapbox_time "unpacking NDK" \
|
||||
$SEVEN_ZIP_PATH x ./android-ndk-r10c-linux-x86_64.bin > .tmp-ndk-log
|
||||
rm .tmp-ndk-log
|
||||
|
||||
echo "debug: fetching JDK"
|
||||
#mapbox_time "fetching JDK" \
|
||||
wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u71-b14/jdk-7u71-linux-x64.tar.gz
|
||||
|
||||
echo "debug: unpacking JDK"
|
||||
#mapbox_time "unpacking JDK" \
|
||||
tar -xzf ./jdk-7u71-linux-x64.tar.gz
|
||||
|
||||
echo "debug: fetching SDK"
|
||||
#mapbox_time "fetching SDK" \
|
||||
wget http://dl.google.com/android/android-sdk_r23.0.2-linux.tgz
|
||||
|
||||
echo "debug: unpacking SDK"
|
||||
#mapbox_time "unpacking SDK" \
|
||||
tar -xzf ./android-sdk_r23.0.2-linux.tgz
|
||||
|
||||
echo "debug: installing SDK"
|
||||
#mapbox_time "installing SDK" \
|
||||
sudo apt-get -y install lib32stdc++6 lib32z1
|
||||
echo y | ./android-sdk-linux/tools/android update sdk -u -a -t tools,platform-tools,build-tools-21.1.0,android-19,android-21
|
||||
fi
|
||||
|
||||
if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then
|
||||
|
||||
@@ -66,7 +66,7 @@ void Painter::setup() {
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Set clear values
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClearDepth(1.0f);
|
||||
glClearStencil(0x0);
|
||||
|
||||
@@ -174,7 +174,7 @@ void Painter::clear() {
|
||||
glStencilMask(0xFF);
|
||||
depthMask(true);
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClearColor(1, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ void Painter::preparePrerender(RasterBucket &bucket) {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
// Render the actual tile.
|
||||
#if GL_EXT_discard_framebuffer
|
||||
#if GL_EXT_discard_framebuffer && !__ANDROID__
|
||||
const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
|
||||
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards);
|
||||
#endif
|
||||
|
||||
@@ -117,7 +117,7 @@ void PrerenderedTexture::blur(Painter& painter, uint16_t passes) {
|
||||
for (int i = 0; i < passes; i++) {
|
||||
// Render horizontal
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, secondary_texture, 0);
|
||||
#if GL_EXT_discard_framebuffer
|
||||
#if GL_EXT_discard_framebuffer && !__ANDROID__
|
||||
const GLenum discards[] = { GL_COLOR_ATTACHMENT0 };
|
||||
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards);
|
||||
#endif
|
||||
@@ -132,7 +132,7 @@ void PrerenderedTexture::blur(Painter& painter, uint16_t passes) {
|
||||
|
||||
// Render vertical
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, original_texture, 0);
|
||||
#if GL_EXT_discard_framebuffer
|
||||
#if GL_EXT_discard_framebuffer && !__ANDROID__
|
||||
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards);
|
||||
#endif
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
Reference in New Issue
Block a user