diff --git a/android/YoPme/jni/MapRenderer.cpp b/android/YoPme/jni/MapRenderer.cpp index 8c5f4601d9..a5a6ac80fe 100644 --- a/android/YoPme/jni/MapRenderer.cpp +++ b/android/YoPme/jni/MapRenderer.cpp @@ -10,9 +10,6 @@ namespace static shared_ptr s_framework; } -// @TODO refactor and remove that -void InitNVEvent(JavaVM * jvm) {} - extern "C" { diff --git a/android/jni/Android.mk b/android/jni/Android.mk index ac9d2963bf..08d1a387ad 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -61,6 +61,7 @@ TARGET_PLATFORM := android-15 LOCAL_HEADER_FILES := \ ../../private.h \ com/mapswithme/core/jni_helper.hpp \ + com/mapswithme/core/ScopedLocalRef.hpp \ com/mapswithme/core/logging.hpp \ com/mapswithme/maps/Framework.hpp \ com/mapswithme/maps/MapStorage.hpp \ @@ -92,6 +93,7 @@ LOCAL_SRC_FILES := \ com/mapswithme/maps/PrivateVariables.cpp \ com/mapswithme/maps/SearchEngine.cpp \ com/mapswithme/maps/SearchRecents.cpp \ + com/mapswithme/maps/UserMarkHelper.cpp \ com/mapswithme/maps/settings/UnitLocale.cpp \ com/mapswithme/platform/Platform.cpp \ com/mapswithme/platform/HttpThread.cpp \ @@ -104,6 +106,7 @@ LOCAL_SRC_FILES := \ com/mapswithme/opengl/androidoglcontext.cpp \ com/mapswithme/opengl/androidoglcontextfactory.cpp \ com/mapswithme/maps/editor/OpeningHours.cpp \ + com/mapswithme/maps/editor/Editor.cpp LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 -latomic -lz diff --git a/android/jni/com/mapswithme/core/ScopedLocalRef.hpp b/android/jni/com/mapswithme/core/ScopedLocalRef.hpp new file mode 100644 index 0000000000..735c1459e3 --- /dev/null +++ b/android/jni/com/mapswithme/core/ScopedLocalRef.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include + +namespace jni +{ + +// A smart pointer that deletes a JNI local reference when it goes out of scope. +template +class ScopedLocalRef { +public: + ScopedLocalRef(JNIEnv * env, T localRef) : m_env(env), m_localRef(localRef) { } + + ~ScopedLocalRef() + { + reset(); + } + + void reset(T ptr = nullptr) + { + if (ptr == m_localRef) + return; + + if (m_localRef != nullptr) + m_env->DeleteLocalRef(m_localRef); + m_localRef = ptr; + } + + T get() const + { + return m_localRef; + } +private: + JNIEnv * m_env; + T m_localRef; + + // Disallow copy and assignment. + ScopedLocalRef(ScopedLocalRef const &) = delete; + void operator = (ScopedLocalRef const &) = delete; +}; + +} // namespace jni diff --git a/android/jni/com/mapswithme/core/jni_helper.cpp b/android/jni/com/mapswithme/core/jni_helper.cpp index 904b49224b..592785d424 100644 --- a/android/jni/com/mapswithme/core/jni_helper.cpp +++ b/android/jni/com/mapswithme/core/jni_helper.cpp @@ -1,7 +1,10 @@ #include "jni_helper.hpp" #include "logging.hpp" +#include "ScopedLocalRef.hpp" #include "base/assert.hpp" +#include "base/exception.hpp" +#include "base/logging.hpp" #include "std/vector.hpp" static JavaVM * g_jvm = 0; @@ -10,17 +13,10 @@ extern JavaVM * GetJVM() return g_jvm; } -// TODO refactor cached jclass to smth more -// TODO finish this logic after refactoring -// cached classloader that can be used to find classes & methods from native threads. -//static shared_ptr g_classLoader; -//static jmethodID g_findClassMethod; - // caching is necessary to create class from native threads jclass g_indexClazz; - -// @TODO remove after refactoring. Needed for NVidia code -void InitNVEvent(JavaVM * jvm); +jclass g_mapObjectClazz; +jclass g_bookmarkClazz; extern "C" { @@ -32,20 +28,9 @@ extern "C" jni::InitAssertLog(); JNIEnv * env = jni::GetEnv(); - // TODO - // init classloader & findclass methodID. -// auto randomClass = env->FindClass("com/mapswithme/maps/MapStorage"); -// jclass classClass = env->GetObjectClass(randomClass); -// auto classLoaderClass = env->FindClass("java/lang/ClassLoader"); -// auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", -// "()Ljava/lang/ClassLoader;"); -// g_classLoader = jni::make_global_ref(env->CallObjectMethod(randomClass, getClassLoaderMethod)); -// ASSERT(*g_classLoader, ("Classloader can't be 0")); -// g_findClassMethod = env->GetMethodID(classLoaderClass, "findClass", -// "(Ljava/lang/String;)Ljava/lang/Class;"); -// ASSERT(g_findClassMethod, ("FindClass methodId can't be 0")); - g_indexClazz = static_cast(env->NewGlobalRef(env->FindClass("com/mapswithme/maps/MapStorage$Index"))); - ASSERT(g_indexClazz, ("Index class not found!")); + g_indexClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/MapStorage$Index"); + g_mapObjectClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/bookmarks/data/MapObject"); + g_bookmarkClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/bookmarks/data/Bookmark"); return JNI_VERSION_1_6; } @@ -54,38 +39,47 @@ extern "C" JNI_OnUnload(JavaVM *, void *) { g_jvm = 0; - jni::GetEnv()->DeleteGlobalRef(g_indexClazz); + JNIEnv * env = jni::GetEnv(); + env->DeleteGlobalRef(g_indexClazz); + env->DeleteGlobalRef(g_mapObjectClazz); + env->DeleteGlobalRef(g_bookmarkClazz); } } // extern "C" namespace jni { - // -// jclass FindClass(char const * name) -// { -// JNIEnv * env = GetEnv(); -// jstring className = env->NewStringUTF(name); -// jclass clazz = static_cast(GetEnv()->CallObjectMethod(*g_classLoader, g_findClassMethod, className)); -// env->DeleteLocalRef(className); -// return clazz; -// } - - jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig) + JNIEnv * GetEnv() { - ASSERT(env, ("JNIEnv can't be 0")); - ASSERT(obj, ("jobject can't be 0")); + JNIEnv * env; + if (JNI_OK != g_jvm->GetEnv((void **)&env, JNI_VERSION_1_6)) + MYTHROW(RootException, ("Can't get JNIEnv. Was thread attached to JVM?")); - jclass cls = env->GetObjectClass(obj); - ASSERT(cls, ("Can't get class: ", DescribeException())); + return env; + } - jmethodID mid = env->GetMethodID(cls, fn, sig); + JavaVM * GetJVM() + { + ASSERT(g_jvm, ("JVM is not initialized")); + return g_jvm; + } + + jmethodID GetMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig) + { + TScopedLocalClassRef clazz(env, env->GetObjectClass(obj)); + ASSERT(clazz.get(), ("Can't get class: ", DescribeException())); + + jmethodID mid = env->GetMethodID(clazz.get(), fn, sig); ASSERT(mid, ("Can't get methodID", fn, sig, DescribeException())); - - env->DeleteLocalRef(cls); - return mid; } + jmethodID GetConstructorID(JNIEnv * env, jclass clazz, char const * sig) + { + jmethodID const ctorID = env->GetMethodID(clazz, "", sig); + ASSERT(ctorID, (DescribeException())); + return ctorID; + } + jclass GetGlobalClassRef(JNIEnv * env, char const * sig) { jclass klass = env->FindClass(sig); @@ -128,28 +122,11 @@ namespace jni return "java/lang/String"; } - JNIEnv * GetEnv() - { - JNIEnv * env; - if (JNI_OK != g_jvm->GetEnv((void **)&env, JNI_VERSION_1_6)) - { - ASSERT(false, ("Can't get JNIEnv. Was thread attached to JVM?")); - return 0; - } - return env; - } - - JavaVM * GetJVM() - { - ASSERT(g_jvm, ("JVM is not initialized")); - return g_jvm; - } - struct global_ref_deleter { void operator()(jobject * ref) { - jni::GetEnv()->DeleteGlobalRef(*ref); + GetEnv()->DeleteGlobalRef(*ref); delete ref; } }; @@ -157,13 +134,13 @@ namespace jni shared_ptr make_global_ref(jobject obj) { jobject * ref = new jobject; - *ref = jni::GetEnv()->NewGlobalRef(obj); + *ref = GetEnv()->NewGlobalRef(obj); return shared_ptr(ref, global_ref_deleter()); } string DescribeException() { - JNIEnv * env = jni::GetEnv(); + JNIEnv * env = GetEnv(); if (env->ExceptionCheck()) { @@ -188,14 +165,11 @@ namespace jni { jclass klass = env->FindClass("com/mapswithme/maps/bookmarks/data/ParcelablePointD"); ASSERT ( klass, () ); - jmethodID methodID = env->GetMethodID( - klass, "", - "(DD)V"); - ASSERT ( methodID, () ); + jmethodID methodID = GetConstructorID(env, klass, "(DD)V"); return env->NewObject(klass, methodID, - static_cast(point.x), - static_cast(point.y)); + static_cast(point.x), + static_cast(point.y)); } jobject GetNewPoint(JNIEnv * env, m2::PointD const & point) @@ -207,24 +181,17 @@ namespace jni { jclass klass = env->FindClass("android/graphics/Point"); ASSERT ( klass, () ); - jmethodID methodID = env->GetMethodID( - klass, "", - "(II)V"); - ASSERT ( methodID, () ); + jmethodID methodID = GetConstructorID(env, klass, "(II)V"); return env->NewObject(klass, methodID, static_cast(point.x), static_cast(point.y)); } - // TODO - // make ScopedLocalRef wrapper similar to https://android.googlesource.com/platform/libnativehelper/+/jb-mr1.1-dev-plus-aosp/include/nativehelper/ScopedLocalRef.h - // for localrefs automatically removed after going out of scope - // This util method dumps content of local and global reference jni tables to logcat for debug and testing purposes void DumpDalvikReferenceTables() { - JNIEnv * env = jni::GetEnv(); + JNIEnv * env = GetEnv(); jclass vm_class = env->FindClass("dalvik/system/VMDebug"); jmethodID dump_mid = env->GetStaticMethodID(vm_class, "dumpReferenceTables", "()V"); env->CallStaticVoidMethod(vm_class, dump_mid); diff --git a/android/jni/com/mapswithme/core/jni_helper.hpp b/android/jni/com/mapswithme/core/jni_helper.hpp index e47082e4c2..1e34acff13 100644 --- a/android/jni/com/mapswithme/core/jni_helper.hpp +++ b/android/jni/com/mapswithme/core/jni_helper.hpp @@ -2,35 +2,33 @@ #include +#include "ScopedLocalRef.hpp" + #include "geometry/point2d.hpp" #include "std/string.hpp" #include "std/shared_ptr.hpp" -// cache MapIndex jclass extern jclass g_indexClazz; +extern jclass g_mapObjectClazz; +extern jclass g_bookmarkClazz; namespace jni { -// TODO yunitsky uncomment and use to load classes from native threads. -// jclass FindClass(char const * name); + JNIEnv * GetEnv(); + JavaVM * GetJVM(); - jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig); + jmethodID GetMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig); + jmethodID GetConstructorID(JNIEnv * env, jclass clazz, char const * sig); // Result value should be DeleteGlobalRef`ed by caller jclass GetGlobalClassRef(JNIEnv * env, char const * s); - JNIEnv * GetEnv(); - JavaVM * GetJVM(); - string ToNativeString(JNIEnv * env, jstring str); - // Converts UTF-8 array to native UTF-8 string. Result differs from simple GetStringUTFChars call for characters greater than U+10000, // since jni uses modified UTF (MUTF-8) for strings. string ToNativeString(JNIEnv * env, jbyteArray const & utfBytes); - jstring ToJavaString(JNIEnv * env, char const * s); - inline jstring ToJavaString(JNIEnv * env, string const & s) { return ToJavaString(env, s.c_str()); @@ -42,6 +40,8 @@ namespace jni string DescribeException(); shared_ptr make_global_ref(jobject obj); + using TScopedLocalRef = ScopedLocalRef; + using TScopedLocalClassRef = ScopedLocalRef; jobject GetNewParcelablePointD(JNIEnv * env, m2::PointD const & point); diff --git a/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp b/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp index 9406a39ba3..e3878253c6 100644 --- a/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp +++ b/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp @@ -163,7 +163,7 @@ extern "C" JNIEnv * env = jni::GetEnv(); - jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onDownloadFinished", "(I)V"); + jmethodID methodID = jni::GetMethodID(env, *obj.get(), "onDownloadFinished", "(I)V"); env->CallVoidMethod(*obj.get(), methodID, errorCode); } @@ -180,10 +180,10 @@ extern "C" JNIEnv * env = jni::GetEnv(); - jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onDownloadProgress", "(IIII)V"); + jmethodID methodID = jni::GetMethodID(env, *obj.get(), "onDownloadProgress", "(IIII)V"); env->CallVoidMethod(*obj.get(), methodID, - curTotal, curProgress, - glbTotal, glbProgress); + curTotal, curProgress, + glbTotal, glbProgress); } typedef HttpRequest::CallbackT CallbackT; diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index b538051948..430ebfd678 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -1,13 +1,10 @@ #include "Framework.hpp" #include "MapStorage.hpp" - -#include "../opengl/androidoglcontextfactory.hpp" - -#include "../core/jni_helper.hpp" - -#include "../country/country_helper.hpp" - -#include "../platform/Platform.hpp" +#include "UserMarkHelper.hpp" +#include "com/mapswithme/core/jni_helper.hpp" +#include "com/mapswithme/country/country_helper.hpp" +#include "com/mapswithme/opengl/androidoglcontextfactory.hpp" +#include "com/mapswithme/platform/Platform.hpp" #include "map/user_mark.hpp" @@ -449,10 +446,8 @@ void Framework::ItemStatusChanged(int childPosition) return; JNIEnv * env = jni::GetEnv(); - static jmethodID const methodID = jni::GetJavaMethodID(env, - *m_javaCountryListener, - "onItemStatusChanged", - "(I)V"); + static jmethodID const methodID = jni::GetMethodID(env, *m_javaCountryListener, + "onItemStatusChanged", "(I)V"); ASSERT ( methodID, () ); env->CallVoidMethod(*m_javaCountryListener, methodID, childPosition); @@ -464,10 +459,8 @@ void Framework::ItemProgressChanged(int childPosition, LocalAndRemoteSizeT const return; JNIEnv * env = jni::GetEnv(); - static jmethodID const methodID = jni::GetJavaMethodID(env, - *m_javaCountryListener, - "onItemProgressChanged", - "(I[J)V"); + static jmethodID const methodID = jni::GetMethodID(env, *m_javaCountryListener, + "onItemProgressChanged", "(I[J)V"); ASSERT ( methodID, () ); env->CallVoidMethod(*m_javaCountryListener, methodID, childPosition, storage_utils::ToArray(env, sizes)); @@ -479,7 +472,7 @@ void Framework::CountryGroupChanged(ActiveMapsLayout::TGroup const & oldGroup, i JNIEnv * env = jni::GetEnv(); for (TListenerMap::const_iterator it = m_javaActiveMapListeners.begin(); it != m_javaActiveMapListeners.end(); ++it) { - jmethodID const methodID = jni::GetJavaMethodID(env, *(it->second), "onCountryGroupChanged", "(IIII)V"); + jmethodID const methodID = jni::GetMethodID(env, *(it->second), "onCountryGroupChanged", "(IIII)V"); ASSERT ( methodID, () ); env->CallVoidMethod(*(it->second), methodID, oldGroup, oldPosition, newGroup, newPosition); @@ -492,7 +485,7 @@ void Framework::CountryStatusChanged(ActiveMapsLayout::TGroup const & group, int JNIEnv * env = jni::GetEnv(); for (TListenerMap::const_iterator it = m_javaActiveMapListeners.begin(); it != m_javaActiveMapListeners.end(); ++it) { - jmethodID const methodID = jni::GetJavaMethodID(env, *(it->second), "onCountryStatusChanged", "(IIII)V"); + jmethodID const methodID = jni::GetMethodID(env, *(it->second), "onCountryStatusChanged", "(IIII)V"); ASSERT ( methodID, () ); env->CallVoidMethod(*(it->second), methodID, group, position, @@ -506,7 +499,7 @@ void Framework::CountryOptionsChanged(ActiveMapsLayout::TGroup const & group, in JNIEnv * env = jni::GetEnv(); for (TListenerMap::const_iterator it = m_javaActiveMapListeners.begin(); it != m_javaActiveMapListeners.end(); ++it) { - jmethodID const methodID = jni::GetJavaMethodID(env, *(it->second), "onCountryOptionsChanged", "(IIII)V"); + jmethodID const methodID = jni::GetMethodID(env, *(it->second), "onCountryOptionsChanged", "(IIII)V"); ASSERT ( methodID, () ); env->CallVoidMethod(*(it->second), methodID, group, position, @@ -520,32 +513,13 @@ void Framework::DownloadingProgressUpdate(ActiveMapsLayout::TGroup const & group JNIEnv * env = jni::GetEnv(); for (TListenerMap::const_iterator it = m_javaActiveMapListeners.begin(); it != m_javaActiveMapListeners.end(); ++it) { - jmethodID const methodID = jni::GetJavaMethodID(env, *(it->second), "onCountryProgressChanged", "(II[J)V"); + jmethodID const methodID = jni::GetMethodID(env, *(it->second), "onCountryProgressChanged", "(II[J)V"); ASSERT ( methodID, () ); env->CallVoidMethod(*(it->second), methodID, group, position, storage_utils::ToArray(env, progress)); } } -// Fills mapobject's metadata -void Framework::InjectMetadata(JNIEnv * env, jclass const clazz, jobject const mapObject, feature::Metadata const & metadata) -{ - static jmethodID const addId = env->GetMethodID(clazz, "addMetadata", "(ILjava/lang/String;)V"); - ASSERT ( addId, () ); - - for (auto const t : metadata.GetPresentTypes()) - { - // TODO: It is not a good idea to pass raw strings to UI. Calling separate getters should be a better way. - // Upcoming change: how to pass opening hours (parsed) into Editor's UI? How to get edited changes back? - jstring metaString = t == feature::Metadata::FMD_WIKIPEDIA ? - jni::ToJavaString(env, metadata.GetWikiURL()) : - jni::ToJavaString(env, metadata.Get(t)); - env->CallVoidMethod(mapObject, addId, t, metaString); - // TODO use unique_ptrs for autoallocation of local refs - env->DeleteLocalRef(metaString); - } -} - void Framework::PostDrapeTask(TDrapeTask && task) { ASSERT(task != nullptr, ()); @@ -563,14 +537,17 @@ void Framework::ExecuteDrapeTasks() m_drapeTasksQueue.clear(); } -} // namespace android - -template -T const * CastMark(UserMark const * data) +void Framework::SetActiveUserMark(UserMark const * mark) { - return static_cast(data); + m_activeUserMark = mark; } +UserMark const * Framework::GetActiveUserMark() +{ + return m_activeUserMark; +} + +} // namespace android //============ GLUE CODE for com.mapswithme.maps.Framework class =============// /* ____ @@ -581,128 +558,23 @@ T const * CastMark(UserMark const * data) * \/ */ -namespace -{ -pair NativeMetadataToJavaMetadata(JNIEnv * env, feature::Metadata const & metadata) -{ - using feature::Metadata; - - auto const metaTypes = metadata.GetPresentTypes(); - // FIXME arrays, allocated through NewArray should be deleted manually in the method. - // refactor that to delete refs locally or pass arrays from outside context - const jintArray j_metaTypes = env->NewIntArray(metadata.Size()); - jint * arr = env->GetIntArrayElements(j_metaTypes, 0); - const jobjectArray j_metaValues = env->NewObjectArray(metadata.Size(), jni::GetStringClass(env), 0); - - for (size_t i = 0; i < metaTypes.size(); i++) - { - auto const type = metaTypes[i]; - arr[i] = type; - // TODO: Refactor code to use separate getters for each metadata. - jstring metaString = type == Metadata::FMD_WIKIPEDIA ? - jni::ToJavaString(env, metadata.GetWikiURL()) : - jni::ToJavaString(env, metadata.Get(type)); - env->SetObjectArrayElement(j_metaValues, i, metaString); - env->DeleteLocalRef(metaString); - } - env->ReleaseIntArrayElements(j_metaTypes, arr, 0); - - return make_pair(j_metaTypes, j_metaValues); -} -} // namespace - extern "C" { - // API - void CallOnApiPointActivatedListener(shared_ptr obj, ApiMarkPoint const * data, double lat, double lon) + void CallOnMapObjectActivatedListener(shared_ptr listener, jobject mapObject) { JNIEnv * env = jni::GetEnv(); - static jmethodID const methodID = jni::GetJavaMethodID(env, - *obj.get(), - "onApiPointActivated", - "(DDLjava/lang/String;Ljava/lang/String;)V"); - - jstring j_name = jni::ToJavaString(env, data->GetName()); - jstring j_id = jni::ToJavaString(env, data->GetID()); - - env->CallVoidMethod(*obj.get(), methodID, lat, lon, j_name, j_id); - - // TODO use unique_ptrs for autoallocation of local refs - env->DeleteLocalRef(j_id); - env->DeleteLocalRef(j_name); + static jmethodID const methodId = + jni::GetMethodID(env, *listener.get(), "onMapObjectActivated", + "(Lcom/mapswithme/maps/bookmarks/data/MapObject;)V"); + ASSERT(methodId, ()); + //public MapObject(@MapObjectType int mapObjectType, String name, double lat, double lon, String typeName) + env->CallVoidMethod(*listener.get(), methodId, mapObject); } - // Additional layer - void CallOnAdditionalLayerActivatedListener(shared_ptr obj, m2::PointD const & globalPoint, - search::AddressInfo const & addrInfo, feature::Metadata const & metadata) - { - JNIEnv * env = jni::GetEnv(); - - const jstring j_name = jni::ToJavaString(env, addrInfo.GetPinName()); - const jstring j_type = jni::ToJavaString(env, addrInfo.GetPinType()); - const double lon = MercatorBounds::XToLon(globalPoint.x); - const double lat = MercatorBounds::YToLat(globalPoint.y); - - pair const meta = NativeMetadataToJavaMetadata(env, metadata); - - const char * signature = "(Ljava/lang/String;Ljava/lang/String;DD[I[Ljava/lang/String;)V"; - static jmethodID const methodId = jni::GetJavaMethodID(env, *obj.get(), - "onAdditionalLayerActivated", signature); - env->CallVoidMethod(*obj.get(), methodId, j_name, j_type, lat, lon, meta.first, meta.second); - - env->DeleteLocalRef(j_type); - env->DeleteLocalRef(j_name); - - env->DeleteLocalRef(meta.second); - env->DeleteLocalRef(meta.first); - } - - // POI - void CallOnPoiActivatedListener(shared_ptr obj, m2::PointD const & globalPoint, - search::AddressInfo const & addrInfo, feature::Metadata const & metadata) - { - JNIEnv * env = jni::GetEnv(); - - const jstring j_name = jni::ToJavaString(env, addrInfo.GetPinName()); - const jstring j_type = jni::ToJavaString(env, addrInfo.GetPinType()); - const jstring j_address = jni::ToJavaString(env, addrInfo.FormatAddress()); - const double lon = MercatorBounds::XToLon(globalPoint.x); - const double lat = MercatorBounds::YToLat(globalPoint.y); - - pair const meta = NativeMetadataToJavaMetadata(env, metadata); - - const char * signature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;DD[I[Ljava/lang/String;)V"; - static jmethodID const methodId = jni::GetJavaMethodID(env, *obj.get(), - "onPoiActivated", signature); - env->CallVoidMethod(*obj.get(), methodId, j_name, j_type, j_address, lat, lon, meta.first, meta.second); - - env->DeleteLocalRef(meta.second); - env->DeleteLocalRef(meta.first); - } - - // Bookmark - void CallOnBookmarkActivatedListener(shared_ptr obj, BookmarkAndCategory const & bmkAndCat) - { - JNIEnv * env = jni::GetEnv(); - static jmethodID const methodId = jni::GetJavaMethodID(env, *obj.get(), - "onBookmarkActivated", "(II)V"); - env->CallVoidMethod(*obj.get(), methodId, bmkAndCat.first, bmkAndCat.second); - } - - // My position - void CallOnMyPositionActivatedListener(shared_ptr obj, double lat, double lon) - { - JNIEnv * env = jni::GetEnv(); - static jmethodID const methodId = jni::GetJavaMethodID(env, *obj.get(), - "onMyPositionActivated", "(DD)V"); - env->CallVoidMethod(*obj.get(), methodId, lat, lon); - } - - // Dismiss information box void CallOnDismissListener(shared_ptr obj) { JNIEnv * env = jni::GetEnv(); - static jmethodID const methodId = jni::GetJavaMethodID(env, *obj.get(), "onDismiss", "()V"); + static jmethodID const methodId = jni::GetMethodID(env, *obj.get(), "onDismiss", "()V"); ASSERT(methodId, ()); env->CallVoidMethod(*obj.get(), methodId); } @@ -711,68 +583,15 @@ extern "C" { if (markCopy == nullptr) { + g_framework->SetActiveUserMark(nullptr); CallOnDismissListener(obj); return; } - ::Framework * fm = frm(); UserMark const * mark = markCopy->GetUserMark(); - search::AddressInfo info; - feature::Metadata metadata; - auto const * feature = mark->GetFeature(); - if (feature) - { - info = fm->GetFeatureAddressInfo(*feature); - metadata = feature->GetMetadata(); - } - else - { - // Calculate at least country name for a point. Can we provide more address information? - info.m_country = fm->GetCountryName(mark->GetPivot()); - } - switch (mark->GetMarkType()) - { - case UserMark::Type::API: - { - ms::LatLon const ll = mark->GetLatLon(); - CallOnApiPointActivatedListener(obj, CastMark(mark), ll.lat, ll.lon); - break; - } - - case UserMark::Type::BOOKMARK: - { - BookmarkAndCategory bmAndCat = fm->FindBookmark(mark); - if (IsValid(bmAndCat)) - CallOnBookmarkActivatedListener(obj, bmAndCat); - break; - } - - case UserMark::Type::POI: - { - // TODO(AlexZ): Refactor out passing custom name for shared links. - auto const & cn = static_cast(mark)->GetCustomName(); - if (!cn.empty()) - info.m_name = cn; - CallOnPoiActivatedListener(obj, mark->GetPivot(), info, metadata); - break; - } - - case UserMark::Type::SEARCH: - { - CallOnAdditionalLayerActivatedListener(obj, mark->GetPivot(), info, metadata); - break; - } - - case UserMark::Type::MY_POSITION: - { - ms::LatLon const ll = mark->GetLatLon(); - CallOnMyPositionActivatedListener(obj, ll.lat, ll.lon); - break; - } - case UserMark::Type::DEBUG_MARK: - // Ignore clicks to debug marks. - break; - } + g_framework->SetActiveUserMark(mark); + jni::TScopedLocalRef mapObject(jni::GetEnv(), usermark_helper::CreateMapObject(mark)); + CallOnMapObjectActivatedListener(obj, mapObject.get()); } void CallRoutingListener(shared_ptr obj, int errorCode, vector const & absentCountries, vector const & absentRoutes) @@ -780,7 +599,7 @@ extern "C" JNIEnv * env = jni::GetEnv(); // cache methodID - it cannot change after class is loaded. // http://developer.android.com/training/articles/perf-jni.html#jclass_jmethodID_and_jfieldID more details here - static jmethodID const methodId = jni::GetJavaMethodID(env, *obj.get(), "onRoutingEvent", + static jmethodID const methodId = jni::GetMethodID(env, *obj.get(), "onRoutingEvent", "(I[Lcom/mapswithme/maps/MapStorage$Index;[Lcom/mapswithme/maps/MapStorage$Index;)V"); ASSERT(methodId, ()); @@ -809,7 +628,7 @@ extern "C" { JNIEnv * env = jni::GetEnv(); jobject listener = *sharedListener.get(); - static jmethodID const methodId = jni::GetJavaMethodID(env, listener, "onRouteBuildingProgress", "(F)V"); + static jmethodID const methodId = jni::GetMethodID(env, listener, "onRouteBuildingProgress", "(F)V"); env->CallVoidMethod(listener, methodId, progress); } @@ -830,13 +649,13 @@ extern "C" } JNIEXPORT void JNICALL - Java_com_mapswithme_maps_Framework_nativeSetBalloonListener(JNIEnv * env, jclass clazz, jobject l) + Java_com_mapswithme_maps_Framework_nativeSetMapObjectListener(JNIEnv * env, jclass clazz, jobject l) { frm()->SetUserMarkActivationListener(bind(&CallOnUserMarkActivated, jni::make_global_ref(l), _1)); } JNIEXPORT void JNICALL - Java_com_mapswithme_maps_Framework_nativeRemoveBalloonListener(JNIEnv * env, jobject thiz) + Java_com_mapswithme_maps_Framework_nativeRemoveMapObjectListener(JNIEnv * env, jobject thiz) { frm()->SetUserMarkActivationListener(::Framework::TActivateCallbackFn()); } @@ -1158,33 +977,12 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_mapswithme_maps_Framework_nativeGetMapObjectForPoint(JNIEnv * env, jclass clazz, jdouble lat, jdouble lon) { - PoiMarkPoint const * poiMark = frm()->GetAddressMark(MercatorBounds::FromLatLon(lat, lon)); - search::AddressInfo info; - feature::Metadata metadata; - auto const * feature = poiMark->GetFeature(); - if (feature) - { - metadata = feature->GetMetadata(); - info = frm()->GetFeatureAddressInfo(*feature); - } - // TODO(AlexZ): else case? - - static jclass const klass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/bookmarks/data/MapObject$Poi"); - // Java signature : Poi(String name, double lat, double lon, String typeName) - static jmethodID const methodID = env->GetMethodID(klass, "", "(Ljava/lang/String;DDLjava/lang/String;)V"); - - jobject const mapObject = env->NewObject(klass, methodID, jni::ToJavaString(env, info.GetPinName()), - lat, lon, jni::ToJavaString(env, info.GetPinType())); - ASSERT(mapObject, ()); - - g_framework->InjectMetadata(env, klass, mapObject, metadata); - - return mapObject; + return usermark_helper::CreateMapObject(frm()->GetAddressMark(MercatorBounds::FromLatLon(lat, lon))); } JNIEXPORT jstring JNICALL Java_com_mapswithme_maps_Framework_nativeGetCountryNameIfAbsent(JNIEnv * env, jobject thiz, - jdouble lat, jdouble lon) + jdouble lat, jdouble lon) { string const name = g_framework->GetCountryNameIfAbsent(MercatorBounds::FromLatLon(lat, lon)); @@ -1200,7 +998,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_mapswithme_maps_Framework_nativeGetCountryIndex(JNIEnv * env, jobject thiz, - jdouble lat, jdouble lon) + jdouble lat, jdouble lon) { TIndex const idx = g_framework->GetCountryIndex(lat, lon); @@ -1354,4 +1152,10 @@ extern "C" static jfieldID const buildingsField = env->GetFieldID(resultClass, "buildings", "Z"); env->SetBooleanField(result, buildingsField, buildings); } + + JNIEXPORT jobject JNICALL + Java_com_mapswithme_maps_Framework_nativeGetActiveMapObject(JNIEnv * env, jclass thiz) + { + return usermark_helper::CreateMapObject(g_framework->GetActiveUserMark()); + } } // extern "C" diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index 798d1d0236..cb08400053 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -56,6 +56,8 @@ namespace android location::EMyPositionMode m_currentMode; bool m_isCurrentModeInitialized; + UserMark const * m_activeUserMark; + public: Framework(); ~Framework(); @@ -160,13 +162,13 @@ namespace android void ApplyWidgets(); void CleanWidgets(); - // Fills mapobject's metadata from UserMark - void InjectMetadata(JNIEnv * env, jclass clazz, jobject const mapObject, feature::Metadata const & metadata); - using TDrapeTask = function; // Posts a task which must be executed when Drape Engine is alive. void PostDrapeTask(TDrapeTask && task); + void SetActiveUserMark(UserMark const * mark); + UserMark const * GetActiveUserMark(); + public: virtual void ItemStatusChanged(int childPosition); virtual void ItemProgressChanged(int childPosition, storage::LocalAndRemoteSizeT const & sizes); diff --git a/android/jni/com/mapswithme/maps/LocationState.cpp b/android/jni/com/mapswithme/maps/LocationState.cpp index 319261b198..b5e739ae55 100644 --- a/android/jni/com/mapswithme/maps/LocationState.cpp +++ b/android/jni/com/mapswithme/maps/LocationState.cpp @@ -23,7 +23,7 @@ extern "C" g_framework->SetMyPositionMode(mode); JNIEnv * env = jni::GetEnv(); - env->CallVoidMethod(*obj.get(), jni::GetJavaMethodID(env, *obj.get(), "onMyPositionModeChangedCallback", "(I)V"), static_cast(mode)); + env->CallVoidMethod(*obj.get(), jni::GetMethodID(env, *obj.get(), "onMyPositionModeChangedCallback", "(I)V"), static_cast(mode)); } JNIEXPORT void JNICALL diff --git a/android/jni/com/mapswithme/maps/MapFragment.cpp b/android/jni/com/mapswithme/maps/MapFragment.cpp index f7c5b49c71..e17839b167 100644 --- a/android/jni/com/mapswithme/maps/MapFragment.cpp +++ b/android/jni/com/mapswithme/maps/MapFragment.cpp @@ -40,7 +40,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_mapswithme_maps_MapFragment_nativeConnectDownloadButton(JNIEnv * env, jobject thiz) { - jmethodID methodID = jni::GetJavaMethodID(env, thiz, "onDownloadCountryClicked", "(IIII)V"); + jmethodID methodID = jni::GetMethodID(env, thiz, "onDownloadCountryClicked", "(IIII)V"); g_framework->NativeFramework()->SetDownloadCountryListener(bind(&CallOnDownloadCountryClicked, jni::make_global_ref(thiz), _1, _2, methodID)); } diff --git a/android/jni/com/mapswithme/maps/MapStorage.cpp b/android/jni/com/mapswithme/maps/MapStorage.cpp index 0593af5fac..3cc6726320 100644 --- a/android/jni/com/mapswithme/maps/MapStorage.cpp +++ b/android/jni/com/mapswithme/maps/MapStorage.cpp @@ -114,7 +114,7 @@ extern "C" { JNIEnv * env = jni::GetEnv(); - jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onCountryStatusChanged", "(Lcom/mapswithme/maps/MapStorage$Index;)V"); + jmethodID methodID = jni::GetMethodID(env, *obj.get(), "onCountryStatusChanged", "(Lcom/mapswithme/maps/MapStorage$Index;)V"); env->CallVoidMethod(*obj.get(), methodID, ToJava(idx)); } @@ -125,7 +125,7 @@ extern "C" JNIEnv * env = jni::GetEnv(); - jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onCountryProgress", "(Lcom/mapswithme/maps/MapStorage$Index;JJ)V"); + jmethodID methodID = jni::GetMethodID(env, *obj.get(), "onCountryProgress", "(Lcom/mapswithme/maps/MapStorage$Index;JJ)V"); env->CallVoidMethod(*obj.get(), methodID, ToJava(idx), current, total); } diff --git a/android/jni/com/mapswithme/maps/SearchEngine.cpp b/android/jni/com/mapswithme/maps/SearchEngine.cpp index c10167b383..96148d7459 100644 --- a/android/jni/com/mapswithme/maps/SearchEngine.cpp +++ b/android/jni/com/mapswithme/maps/SearchEngine.cpp @@ -144,20 +144,13 @@ extern "C" if ( g_javaListener ) env->DeleteGlobalRef(g_javaListener); g_javaListener = env->NewGlobalRef(thiz); - g_updateResultsId = jni::GetJavaMethodID(env, g_javaListener, "onResultsUpdate", "([Lcom/mapswithme/maps/search/SearchResult;J)V"); - ASSERT(g_updateResultsId, ()); - g_endResultsId = jni::GetJavaMethodID(env, g_javaListener, "onResultsEnd", "(J)V"); - ASSERT(g_endResultsId, ()); + g_updateResultsId = jni::GetMethodID(env, g_javaListener, "onResultsUpdate", "([Lcom/mapswithme/maps/search/SearchResult;J)V"); + g_endResultsId = jni::GetMethodID(env, g_javaListener, "onResultsEnd", "(J)V"); g_resultClass = static_cast(env->NewGlobalRef(env->FindClass("com/mapswithme/maps/search/SearchResult"))); - ASSERT(g_resultClass, ()); - g_resultConstructor = env->GetMethodID(g_resultClass, "", "(Ljava/lang/String;Lcom/mapswithme/maps/search/SearchResult$Description;DD[I)V"); - ASSERT(g_resultConstructor, ()); - g_suggestConstructor = env->GetMethodID(g_resultClass, "", "(Ljava/lang/String;Ljava/lang/String;[I)V"); - ASSERT(g_suggestConstructor, ()); + g_resultConstructor = jni::GetConstructorID(env, g_resultClass, "(Ljava/lang/String;Lcom/mapswithme/maps/search/SearchResult$Description;DD[I)V"); + g_suggestConstructor = jni::GetConstructorID(env, g_resultClass, "(Ljava/lang/String;Ljava/lang/String;[I)V"); g_descriptionClass = static_cast(env->NewGlobalRef(env->FindClass("com/mapswithme/maps/search/SearchResult$Description"))); - ASSERT(g_descriptionClass, ()); - g_descriptionConstructor = env->GetMethodID(g_descriptionClass, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)V"); - ASSERT(g_descriptionConstructor, ()); + g_descriptionConstructor = jni::GetConstructorID(env, g_descriptionClass, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)V"); } JNIEXPORT jboolean JNICALL diff --git a/android/jni/com/mapswithme/maps/UserMarkHelper.cpp b/android/jni/com/mapswithme/maps/UserMarkHelper.cpp new file mode 100644 index 0000000000..6ce815a4b9 --- /dev/null +++ b/android/jni/com/mapswithme/maps/UserMarkHelper.cpp @@ -0,0 +1,153 @@ +#include "UserMarkHelper.hpp" + +namespace usermark_helper +{ +using search::AddressInfo; +using feature::Metadata; + +template +T const * CastMark(UserMark const * data) +{ + return static_cast(data); +} + +void InjectMetadata(JNIEnv * env, jclass const clazz, jobject const mapObject, feature::Metadata const & metadata) +{ + static jmethodID const addId = env->GetMethodID(clazz, "addMetadata", "(ILjava/lang/String;)V"); + ASSERT(addId, ()); + + for (auto const t : metadata.GetPresentTypes()) + { + // TODO: It is not a good idea to pass raw strings to UI. Calling separate getters should be a better way. + jni::TScopedLocalRef metaString(env, t == feature::Metadata::FMD_WIKIPEDIA ? + jni::ToJavaString(env, metadata.GetWikiURL()) : + jni::ToJavaString(env, metadata.Get(t))); + env->CallVoidMethod(mapObject, addId, t, metaString.get()); + } +} + +pair NativeMetadataToJavaMetadata(JNIEnv * env, Metadata const & metadata) +{ + auto const metaTypes = metadata.GetPresentTypes(); + const jintArray j_metaTypes = env->NewIntArray(metadata.Size()); + jint * arr = env->GetIntArrayElements(j_metaTypes, 0); + const jobjectArray j_metaValues = env->NewObjectArray(metadata.Size(), jni::GetStringClass(env), 0); + + for (size_t i = 0; i < metaTypes.size(); i++) + { + auto const type = metaTypes[i]; + arr[i] = type; + // TODO: Refactor code to use separate getters for each metadata. + jni::TScopedLocalRef metaString(env, type == Metadata::FMD_WIKIPEDIA ? + jni::ToJavaString(env, metadata.GetWikiURL()) : + jni::ToJavaString(env, metadata.Get(type))); + env->SetObjectArrayElement(j_metaValues, i, metaString.get()); + } + env->ReleaseIntArrayElements(j_metaTypes, arr, 0); + + return make_pair(j_metaTypes, j_metaValues); +} + +void FillAddressAndMetadata(UserMark const * mark, AddressInfo & info, Metadata & metadata) +{ + Framework * frm = g_framework->NativeFramework(); + auto const * feature = mark->GetFeature(); + if (feature) + { + info = frm->GetFeatureAddressInfo(*feature); + metadata = feature->GetMetadata(); + } + else + { + // Calculate at least country name for a point. Can we provide more address information? + info.m_country = frm->GetCountryName(mark->GetPivot()); + } +} + +jobject CreateBookmark(int categoryId, int bookmarkId, string const & typeName, Metadata const & metadata) +{ + JNIEnv * env = jni::GetEnv(); + // Java signature : + // public Bookmark(@IntRange(from = 0) int categoryId, @IntRange(from = 0) int bookmarkId, String name) + static jmethodID const ctorId = jni::GetConstructorID(env, g_bookmarkClazz, "(IILjava/lang/String;)V"); + jni::TScopedLocalRef name(env, jni::ToJavaString(env, typeName)); + jobject mapObject = env->NewObject(g_bookmarkClazz, ctorId, + static_cast(categoryId), + static_cast(bookmarkId), + name.get()); + + InjectMetadata(env, g_mapObjectClazz, mapObject, metadata); + return mapObject; +} + +jobject CreateMapObject(int mapObjectType, string const & name, double lat, double lon, string const & typeName, string const & street, string const & house, Metadata const & metadata) +{ + JNIEnv * env = jni::GetEnv(); + // Java signature : + // public MapObject(@MapObjectType int mapObjectType, String name, double lat, double lon, String typeName, String street, String house) + static jmethodID const ctorId = + jni::GetConstructorID(env, g_mapObjectClazz, "(ILjava/lang/String;DDLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + + jobject mapObject = env->NewObject(g_mapObjectClazz, ctorId, + static_cast(mapObjectType), + jni::ToJavaString(env, name), + static_cast(lat), + static_cast(lon), + jni::ToJavaString(env, typeName), + jni::ToJavaString(env, street), + jni::ToJavaString(env, house)); + + InjectMetadata(env, g_mapObjectClazz, mapObject, metadata); + return mapObject; +} + +jobject CreateMapObject(UserMark const * userMark) +{ + search::AddressInfo info; + feature::Metadata metadata; + FillAddressAndMetadata(userMark, info, metadata); + jobject mapObject = nullptr; + ms::LatLon ll; + switch (userMark->GetMarkType()) + { + case UserMark::Type::API: + { + ll = userMark->GetLatLon(); + ApiMarkPoint const * apiMark = CastMark(userMark); + mapObject = CreateMapObject(kApiPoint, apiMark->GetName(), ll.lat, ll.lon, apiMark->GetID(), "", "", metadata); + break; + } + case UserMark::Type::BOOKMARK: + { + BookmarkAndCategory bmAndCat = g_framework->NativeFramework()->FindBookmark(userMark); + Bookmark const * bookmark = CastMark(userMark); + if (IsValid(bmAndCat)) + mapObject = CreateBookmark(bmAndCat.first, bmAndCat.second, bookmark->GetName(), metadata); + break; + } + case UserMark::Type::POI: + { + mapObject = CreateMapObject(kPoi, info.GetPinName(), userMark->GetPivot().x, userMark->GetPivot().y, info.GetPinType(), info.m_street, info.m_house, metadata); + break; + } + case UserMark::Type::SEARCH: + { + mapObject = CreateMapObject(kSearch, info.GetPinName(), userMark->GetPivot().x, userMark->GetPivot().y, info.GetPinType(), info.m_street, info.m_house, metadata); + break; + } + case UserMark::Type::MY_POSITION: + { + ll = userMark->GetLatLon(); + mapObject = CreateMapObject(kMyPosition, "", ll.lat, ll.lon, "", "", "", metadata); + break; + } + case UserMark::Type::DEBUG_MARK: + { + // Ignore clicks to debug marks. + break; + } + } + + return mapObject; +} +} // namespace usermark_helper diff --git a/android/jni/com/mapswithme/maps/UserMarkHelper.hpp b/android/jni/com/mapswithme/maps/UserMarkHelper.hpp new file mode 100644 index 0000000000..7757223a4e --- /dev/null +++ b/android/jni/com/mapswithme/maps/UserMarkHelper.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "com/mapswithme/core/jni_helper.hpp" +#include "com/mapswithme/maps/Framework.hpp" + +#include "map/user_mark.hpp" + +namespace usermark_helper +{ +// should be equal with definitions in MapObject.java +static constexpr int kPoi = 0; +static constexpr int kApiPoint = 1; +static constexpr int kBookmark = 2; +static constexpr int kMyPosition = 3; +static constexpr int kSearch = 4; + +// Fills mapobject's metadata from UserMark +void InjectMetadata(JNIEnv * env, jclass clazz, jobject const mapObject, feature::Metadata const & metadata); + +template +T const * CastMark(UserMark const * data); + +pair NativeMetadataToJavaMetadata(JNIEnv * env, feature::Metadata const & metadata); + +void FillAddressAndMetadata(UserMark const * mark, search::AddressInfo & info, feature::Metadata & metadata); + +jobject CreateBookmark(int categoryId, int bookmarkId, string const & typeName, feature::Metadata const & metadata); + +jobject CreateMapObject(int mapObjectType, string const & name, double lat, double lon, string const & typeName, feature::Metadata const & metadata); + +jobject CreateMapObject(UserMark const * userMark); +} // namespace usermark diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp index 9102e6fe56..c4d50022cf 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp @@ -19,28 +19,28 @@ namespace extern "C" { JNIEXPORT jstring JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_getName( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetName( JNIEnv * env, jobject thiz, jint cat, jlong bmk) { return jni::ToJavaString(env, getBookmark(cat, bmk)->GetName()); } JNIEXPORT jstring JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_getBookmarkDescription( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetBookmarkDescription( JNIEnv * env, jobject thiz, jint cat, jlong bmk) { return jni::ToJavaString(env, getBookmark(cat, bmk)->GetDescription()); } JNIEXPORT jstring JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_getIcon( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetIcon( JNIEnv * env, jobject thiz, jint cat, jlong bmk) { return jni::ToJavaString(env, getBookmark(cat, bmk)->GetType()); } JNIEXPORT void JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_setBookmarkParams( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeSetBookmarkParams( JNIEnv * env, jobject thiz, jint cat, jlong bmk, jstring name, jstring type, jstring descr) { @@ -48,7 +48,7 @@ extern "C" // initialize new bookmark BookmarkData bm(jni::ToNativeString(env, name), jni::ToNativeString(env, type)); - if (descr != 0) + if (descr) bm.SetDescription(jni::ToNativeString(env, descr)); else bm.SetDescription(p->GetDescription()); @@ -57,28 +57,28 @@ extern "C" } JNIEXPORT jint JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_changeCategory( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeChangeCategory( JNIEnv * env, jobject thiz, jint oldCat, jint newCat, jlong bmk) { return g_framework->ChangeBookmarkCategory(BookmarkAndCategory(oldCat, bmk), newCat); } JNIEXPORT jobject JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_getXY( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetXY( JNIEnv * env, jobject thiz, jint cat, jlong bmk) { return jni::GetNewParcelablePointD(env, getBookmark(cat, bmk)->GetPivot()); } JNIEXPORT jdouble JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_getScale( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetScale( JNIEnv * env, jobject thiz, jint cat, jlong bmk) { return getBookmark(cat, bmk)->GetScale(); } JNIEXPORT jstring JNICALL - Java_com_mapswithme_maps_bookmarks_data_Bookmark_encode2Ge0Url( + Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeEncode2Ge0Url( JNIEnv * env, jobject thiz, jint cat, jlong bmk, jboolean addName) { return jni::ToJavaString(env, frm()->CodeGe0url(getBookmark(cat, bmk), addName)); diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkCategory.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkCategory.cpp index a7231e4a21..ee3bb1f534 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkCategory.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkCategory.cpp @@ -1,132 +1,114 @@ -#include "../../Framework.hpp" +#include "com/mapswithme/maps/Framework.hpp" +#include "com/mapswithme/maps/UserMarkHelper.hpp" +#include "com/mapswithme/core/jni_helper.hpp" #include "platform/measurement_utils.hpp" -#include "../../../core/jni_helper.hpp" - namespace { - ::Framework * frm() { return g_framework->NativeFramework(); } +::Framework * frm() { return g_framework->NativeFramework(); } - BookmarkCategory * getBmCategory(jint c) - { - BookmarkCategory * pCat = frm()->GetBmCategory(c); - ASSERT(pCat, ("Category not found", c)); - return pCat; - } +BookmarkCategory * getBmCategory(jint c) +{ + BookmarkCategory * pCat = frm()->GetBmCategory(c); + ASSERT(pCat, ("Category not found", c)); + return pCat; +} } extern "C" { - - JNIEXPORT jboolean JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_isVisible( - JNIEnv * env, jobject thiz, jint id) - { - return getBmCategory(id)->IsVisible(); - } - - JNIEXPORT void JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_setVisibility( - JNIEnv * env, jobject thiz, jint id, jboolean b) - { - BookmarkCategory * pCat = getBmCategory(id); - { - BookmarkCategory::Guard guard(*pCat); - guard.m_controller.SetIsVisible(b); - } - pCat->SaveToKMLFile(); - } - - JNIEXPORT void JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_setName( - JNIEnv * env, jobject thiz, jint id, jstring n) - { - BookmarkCategory * pCat = getBmCategory(id); - pCat->SetName(jni::ToNativeString(env, n)); - pCat->SaveToKMLFile(); - } - - JNIEXPORT jstring JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getName( - JNIEnv * env, jobject thiz, jint id) - { - return jni::ToJavaString(env, getBmCategory(id)->GetName()); - } - - JNIEXPORT jint JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getSize( - JNIEnv * env, jobject thiz, jint id) - { - BookmarkCategory * category = getBmCategory(id); - return category->GetUserMarkCount() + category->GetTracksCount(); - } - - JNIEXPORT jint JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getBookmarksCount( - JNIEnv * env, jobject thiz, jint id) - { - return getBmCategory(id)->GetUserMarkCount(); - } - - JNIEXPORT jint JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getTracksCount( - JNIEnv * env, jobject thiz, jint id) - { - return getBmCategory(id)->GetTracksCount(); - } - - JNIEXPORT jobject JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getBookmark( - JNIEnv * env, jobject thiz, jint id, jint index, jclass bookmarkClazz) - { - // Bookmark(int categoryId, int bookmarkId, String name) - jmethodID static const cId = env->GetMethodID(bookmarkClazz, "", "(IILjava/lang/String;)V"); - - BookmarkCategory * category = getBmCategory(id); - Bookmark const * nBookmark = static_cast(category->GetUserMark(index)); - feature::Metadata metadata; - auto const * feature = nBookmark->GetFeature(); - if (feature) - metadata = feature->GetMetadata(); - // TODO(AlexZ): else case? - - ASSERT(nBookmark, ("Bookmark must not be null with index:)", index)); - - jobject jBookmark = env->NewObject(bookmarkClazz, cId, id, index, - jni::ToJavaString(env, nBookmark->GetName())); - g_framework->InjectMetadata(env, bookmarkClazz, jBookmark, metadata); - - return jBookmark; - } - - static uint32_t shift(uint32_t v, uint8_t bitCount) { return v << bitCount; } - - JNIEXPORT jobject JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getTrack( - JNIEnv * env, jobject thiz, jint id, jint index, jclass trackClazz) - { - // Track(int trackId, int categoryId, String name, String lengthString, int color) - static jmethodID cId = env->GetMethodID(trackClazz, "", - "(IILjava/lang/String;Ljava/lang/String;I)V"); - - BookmarkCategory * category = getBmCategory(id); - Track const * nTrack = category->GetTrack(index); - - ASSERT(nTrack, ("Track must not be null with index:)", index)); - - string formattedLenght; - MeasurementUtils::FormatDistance(nTrack->GetLengthMeters(), formattedLenght); - - dp::Color nColor = nTrack->GetColor(0); - - jint androidColor = shift(nColor.GetAlfa(), 24) + - shift(nColor.GetRed(), 16) + - shift(nColor.GetGreen(), 8) + - nColor.GetBlue(); - - return env->NewObject(trackClazz, cId, - index, id, jni::ToJavaString(env, nTrack->GetName()), - jni::ToJavaString(env, formattedLenght), androidColor); - } +JNIEXPORT jboolean JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_isVisible( + JNIEnv * env, jobject thiz, jint id) +{ + return getBmCategory(id)->IsVisible(); } + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_setVisibility( + JNIEnv * env, jobject thiz, jint id, jboolean b) +{ + BookmarkCategory * pCat = getBmCategory(id); + { + BookmarkCategory::Guard guard(*pCat); + guard.m_controller.SetIsVisible(b); + } + pCat->SaveToKMLFile(); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_setName( + JNIEnv * env, jobject thiz, jint id, jstring n) +{ + BookmarkCategory * pCat = getBmCategory(id); + pCat->SetName(jni::ToNativeString(env, n)); + pCat->SaveToKMLFile(); +} + +JNIEXPORT jstring JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getName( + JNIEnv * env, jobject thiz, jint id) +{ + return jni::ToJavaString(env, getBmCategory(id)->GetName()); +} + +JNIEXPORT jint JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getSize( + JNIEnv * env, jobject thiz, jint id) +{ + BookmarkCategory * category = getBmCategory(id); + return category->GetUserMarkCount() + category->GetTracksCount(); +} + +JNIEXPORT jint JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getBookmarksCount( + JNIEnv * env, jobject thiz, jint id) +{ + return getBmCategory(id)->GetUserMarkCount(); +} + +JNIEXPORT jint JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getTracksCount( + JNIEnv * env, jobject thiz, jint id) +{ + return getBmCategory(id)->GetTracksCount(); +} + +JNIEXPORT jobject JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getBookmark( + JNIEnv * env, jobject thiz, jint id, jint index) +{ + return usermark_helper::CreateMapObject(getBmCategory(id)->GetUserMark(index)); +} + +static uint32_t shift(uint32_t v, uint8_t bitCount) { return v << bitCount; } + +JNIEXPORT jobject JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_getTrack( + JNIEnv * env, jobject thiz, jint id, jint index, jclass trackClazz) +{ + // Track(int trackId, int categoryId, String name, String lengthString, int color) + static jmethodID cId = env->GetMethodID(trackClazz, "", + "(IILjava/lang/String;Ljava/lang/String;I)V"); + + BookmarkCategory * category = getBmCategory(id); + Track const * nTrack = category->GetTrack(index); + + ASSERT(nTrack, ("Track must not be null with index:)", index)); + + string formattedLenght; + MeasurementUtils::FormatDistance(nTrack->GetLengthMeters(), formattedLenght); + + dp::Color nColor = nTrack->GetColor(0); + + jint androidColor = shift(nColor.GetAlfa(), 24) + + shift(nColor.GetRed(), 16) + + shift(nColor.GetGreen(), 8) + + nColor.GetBlue(); + + return env->NewObject(trackClazz, cId, + index, id, jni::ToJavaString(env, nTrack->GetName()), + jni::ToJavaString(env, formattedLenght), androidColor); +} +} // extern "C" diff --git a/android/jni/com/mapswithme/maps/editor/Editor.cpp b/android/jni/com/mapswithme/maps/editor/Editor.cpp new file mode 100644 index 0000000000..7fc0e49889 --- /dev/null +++ b/android/jni/com/mapswithme/maps/editor/Editor.cpp @@ -0,0 +1,75 @@ +#include + +#include "com/mapswithme/core/jni_helper.hpp" +#include "com/mapswithme/maps/Framework.hpp" + +#include "base/logging.hpp" +#include "indexer/osm_editor.hpp" + +#include "std/algorithm.hpp" +#include "std/set.hpp" +#include "std/vector.hpp" + +namespace +{ +using feature::Metadata; +using osm::Editor; + +FeatureType * activeFeature() +{ + return g_framework->GetActiveUserMark()->GetFeature(); +} +} // namespace + +extern "C" +{ +using osm::Editor; + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeSetMetadata(JNIEnv * env, jclass clazz, jint type, jstring value) +{ + auto & metadata = activeFeature()->GetMetadata(); + metadata.Set(static_cast(type), jni::ToNativeString(env, value)); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeEditFeature(JNIEnv * env, jclass clazz, jstring street, jstring houseNumber) +{ + Editor::Instance().EditFeature(*activeFeature(), jni::ToNativeString(env, street), jni::ToNativeString(env, houseNumber)); +} + +JNIEXPORT jintArray JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeGetEditableMetadata(JNIEnv * env, jclass clazz) +{ + auto const & editableTypes = Editor::Instance().EditableMetadataForType(*activeFeature()); + int const size = editableTypes.size(); + jintArray jEditableTypes = env->NewIntArray(size); + jint * arr = env->GetIntArrayElements(jEditableTypes, 0); + for (int i = 0; i < size; i++) + arr[i] = static_cast(editableTypes[i]); + env->ReleaseIntArrayElements(jEditableTypes, arr, 0); + + return jEditableTypes; +} + +JNIEXPORT jboolean JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeIsAddressEditable(JNIEnv * env, jclass clazz) +{ + return Editor::Instance().IsAddressEditable(*activeFeature()); +} + +JNIEXPORT jboolean JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeIsNameEditable(JNIEnv * env, jclass clazz) +{ + return Editor::Instance().IsNameEditable(*activeFeature()); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeSetName(JNIEnv * env, jclass clazz, jstring name) +{ + auto * feature = activeFeature(); + auto names = feature->GetNames(); + names.AddString(StringUtf8Multilang::DEFAULT_CODE, jni::ToNativeString(env, name)); + feature->SetNames(names); +} +} // extern "C" diff --git a/android/jni/com/mapswithme/platform/HttpThread.cpp b/android/jni/com/mapswithme/platform/HttpThread.cpp index ef45422434..23d87f00de 100644 --- a/android/jni/com/mapswithme/platform/HttpThread.cpp +++ b/android/jni/com/mapswithme/platform/HttpThread.cpp @@ -70,7 +70,7 @@ public: JNIEnv * env = jni::GetEnv(); ASSERT ( env, () ); - jmethodID methodId = jni::GetJavaMethodID(env, m_self, "cancel", "(Z)Z"); + jmethodID methodId = jni::GetMethodID(env, m_self, "cancel", "(Z)Z"); ASSERT ( methodId, () ); env->CallBooleanMethod(m_self, methodId, false); diff --git a/android/res/layout/fragment_auth_editor.xml b/android/res/layout/fragment_auth_editor.xml new file mode 100644 index 0000000000..3cb3cba631 --- /dev/null +++ b/android/res/layout/fragment_auth_editor.xml @@ -0,0 +1,116 @@ + + + + + + + + + +