diff --git a/android/app/src/main/cpp/CMakeLists.txt b/android/app/src/main/cpp/CMakeLists.txt index 25a839155c..b690785b39 100644 --- a/android/app/src/main/cpp/CMakeLists.txt +++ b/android/app/src/main/cpp/CMakeLists.txt @@ -25,6 +25,20 @@ set(SRC app/organicmaps/sdk/search/DisplayedCategories.cpp app/organicmaps/sdk/search/SearchEngine.cpp app/organicmaps/sdk/search/SearchRecents.cpp + app/organicmaps/sdk/routing/JunctionInfo.hpp + app/organicmaps/sdk/routing/RouteMarkData.hpp + app/organicmaps/sdk/routing/RouteMarkType.hpp + app/organicmaps/sdk/routing/RoutePointInfo.hpp + app/organicmaps/sdk/routing/RouteRecommendationType.hpp + app/organicmaps/sdk/routing/RoutingInfo.hpp + app/organicmaps/sdk/routing/RoutingOptions.cpp + app/organicmaps/sdk/routing/SingleLaneInfo.hpp + app/organicmaps/sdk/routing/TransitRouteInfo.hpp + app/organicmaps/sdk/routing/TransitStepInfo.hpp + app/organicmaps/sdk/ChoosePositionMode.cpp + app/organicmaps/sdk/MapStyle.cpp + app/organicmaps/sdk/OrganicMaps.cpp + app/organicmaps/sdk/Router.cpp app/organicmaps/core/jni_helper.cpp app/organicmaps/core/jni_java_methods.cpp app/organicmaps/core/logging.cpp @@ -38,8 +52,6 @@ set(SRC app/organicmaps/LocationState.cpp app/organicmaps/Map.cpp app/organicmaps/MapManager.cpp - app/organicmaps/MwmApplication.cpp - app/organicmaps/routing/RoutingOptions.cpp app/organicmaps/settings/UnitLocale.cpp app/organicmaps/settings/MapLanguageCode.cpp app/organicmaps/sound/tts.cpp diff --git a/android/app/src/main/cpp/app/organicmaps/Framework.cpp b/android/app/src/main/cpp/app/organicmaps/Framework.cpp index 7b47eef574..010cd21218 100644 --- a/android/app/src/main/cpp/app/organicmaps/Framework.cpp +++ b/android/app/src/main/cpp/app/organicmaps/Framework.cpp @@ -4,6 +4,12 @@ #include "app/organicmaps/UserMarkHelper.hpp" #include "app/organicmaps/opengl/androidoglcontextfactory.hpp" #include "app/organicmaps/platform/AndroidPlatform.hpp" +#include "app/organicmaps/sdk/routing/JunctionInfo.hpp" +#include "app/organicmaps/sdk/routing/RouteMarkData.hpp" +#include "app/organicmaps/sdk/routing/RouteMarkType.hpp" +#include "app/organicmaps/sdk/routing/RouteRecommendationType.hpp" +#include "app/organicmaps/sdk/routing/RoutingInfo.hpp" +#include "app/organicmaps/sdk/routing/TransitRouteInfo.hpp" #include "app/organicmaps/util/Distance.hpp" #include "app/organicmaps/util/FeatureIdBuilder.hpp" #include "app/organicmaps/util/NetworkPolicy.hpp" @@ -804,8 +810,8 @@ void CallRouteRecommendationListener(shared_ptr listener, RoutingManager::Recommendation recommendation) { JNIEnv * env = jni::GetEnv(); - jmethodID const methodId = jni::GetMethodID(env, *listener, "onRecommend", "(I)V"); - env->CallVoidMethod(*listener, methodId, static_cast(recommendation)); + jmethodID const methodId = jni::GetMethodID(env, *listener, "onRecommend", "(Lapp/organicmaps/sdk/routing/RouteRecommendationType;)V"); + env->CallVoidMethod(*listener, methodId, GetRouteRecommendationType(env, recommendation)); } void CallSetRoutingLoadPointsListener(shared_ptr listener, bool success) @@ -1241,7 +1247,7 @@ Java_app_organicmaps_Framework_nativeDisableFollowing(JNIEnv * env, jclass) } JNIEXPORT jobjectArray JNICALL -Java_app_organicmaps_Framework_nativeGenerateNotifications(JNIEnv * env, jclass, bool announceStreets) +Java_app_organicmaps_Framework_nativeGenerateNotifications(JNIEnv * env, jclass, jboolean announceStreets) { ::Framework * fr = frm(); if (!fr->GetRoutingManager().IsRoutingActive()) @@ -1271,64 +1277,16 @@ Java_app_organicmaps_Framework_nativeGetSpeedCamManagerMode(JNIEnv * env, jclass JNIEXPORT jobject JNICALL Java_app_organicmaps_Framework_nativeGetRouteFollowingInfo(JNIEnv * env, jclass) { - ::Framework * fr = frm(); - if (!fr->GetRoutingManager().IsRoutingActive()) + RoutingManager & rm = frm()->GetRoutingManager(); + if (!rm.IsRoutingActive()) return nullptr; routing::FollowingInfo info; - fr->GetRoutingManager().GetRouteFollowingInfo(info); + rm.GetRouteFollowingInfo(info); if (!info.IsValid()) return nullptr; - static jclass const klass = jni::GetGlobalClassRef(env, "app/organicmaps/routing/RoutingInfo"); - // Java signature : RoutingInfo(Distance distToTarget, Distance distToTurn, - // String currentStreet, String nextStreet, String nextNextStreet, - // double completionPercent, int vehicleTurnOrdinal, int - // vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum, - // int totalTime, SingleLaneInfo[] lanes) - static jmethodID const ctorRouteInfoID = - jni::GetConstructorID(env, klass, - "(Lapp/organicmaps/util/Distance;Lapp/organicmaps/util/Distance;" - "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;DIIIII" - "[Lapp/organicmaps/routing/SingleLaneInfo;DZZ)V"); - - vector const & lanes = info.m_lanes; - jobjectArray jLanes = nullptr; - if (!lanes.empty()) - { - static jclass const laneClass = jni::GetGlobalClassRef(env, "app/organicmaps/routing/SingleLaneInfo"); - auto const lanesSize = static_cast(lanes.size()); - jLanes = env->NewObjectArray(lanesSize, laneClass, nullptr); - ASSERT(jLanes, (jni::DescribeException())); - static jmethodID const ctorSingleLaneInfoID = jni::GetConstructorID(env, laneClass, "([BZ)V"); - - for (jsize j = 0; j < lanesSize; ++j) - { - auto const laneSize = static_cast(lanes[j].m_lane.size()); - jni::TScopedLocalByteArrayRef singleLane(env, env->NewByteArray(laneSize)); - ASSERT(singleLane.get(), (jni::DescribeException())); - env->SetByteArrayRegion(singleLane.get(), 0, laneSize, lanes[j].m_lane.data()); - - jni::TScopedLocalRef singleLaneInfo( - env, env->NewObject(laneClass, ctorSingleLaneInfoID, singleLane.get(), - lanes[j].m_isRecommended)); - ASSERT(singleLaneInfo.get(), (jni::DescribeException())); - env->SetObjectArrayElement(jLanes, j, singleLaneInfo.get()); - } - } - - auto const & rm = frm()->GetRoutingManager(); - auto const isSpeedCamLimitExceeded = rm.IsRoutingActive() ? rm.IsSpeedCamLimitExceeded() : false; - auto const shouldPlaySignal = frm()->GetRoutingManager().GetSpeedCamManager().ShouldPlayBeepSignal(); - jobject const result = env->NewObject( - klass, ctorRouteInfoID, ToJavaDistance(env, info.m_distToTarget), - ToJavaDistance(env, info.m_distToTurn), jni::ToJavaString(env, info.m_currentStreetName), - jni::ToJavaString(env, info.m_nextStreetName), jni::ToJavaString(env, info.m_nextNextStreetName), - info.m_completionPercent, info.m_turn, info.m_nextTurn, info.m_pedestrianTurn, info.m_exitNum, - info.m_time, jLanes, info.m_speedLimitMps, static_cast(isSpeedCamLimitExceeded), - static_cast(shouldPlaySignal)); - ASSERT(result, (jni::DescribeException())); - return result; + return CreateRoutingInfo(env, info, rm); } JNIEXPORT jobjectArray JNICALL @@ -1341,17 +1299,7 @@ Java_app_organicmaps_Framework_nativeGetRouteJunctionPoints(JNIEnv * env, jclass return nullptr; } - static jclass const junctionClazz = jni::GetGlobalClassRef(env, "app/organicmaps/routing/JunctionInfo"); - // Java signature : JunctionInfo(double lat, double lon) - static jmethodID const junctionConstructor = jni::GetConstructorID(env, junctionClazz, "(DD)V"); - - return jni::ToJavaArray(env, junctionClazz, junctionPoints, - [](JNIEnv * env, m2::PointD const & point) - { - return env->NewObject(junctionClazz, junctionConstructor, - mercator::YToLat(point.y), - mercator::XToLon(point.x)); - }); + return CreateJunctionInfoArray(env, junctionPoints); } JNIEXPORT jintArray JNICALL @@ -1500,69 +1448,9 @@ Java_app_organicmaps_Framework_nativeDeactivateMapSelectionCircle(JNIEnv * env, return g_framework->DeactivateMapSelectionCircle(); } -JNIEXPORT void JNICALL -Java_app_organicmaps_Framework_nativeSetMapStyle(JNIEnv * env, jclass, jint mapStyle) -{ - MapStyle const val = static_cast(mapStyle); - if (val != g_framework->GetMapStyle()) - g_framework->SetMapStyle(val); -} - -JNIEXPORT jint JNICALL -Java_app_organicmaps_Framework_nativeGetMapStyle(JNIEnv * env, jclass) -{ - return g_framework->GetMapStyle(); -} - -JNIEXPORT void JNICALL -Java_app_organicmaps_Framework_nativeMarkMapStyle(JNIEnv * env, jclass, jint mapStyle) -{ - MapStyle const val = static_cast(mapStyle); - if (val != g_framework->GetMapStyle()) - g_framework->MarkMapStyle(val); -} - -JNIEXPORT void JNICALL -Java_app_organicmaps_Framework_nativeSetRouter(JNIEnv * env, jclass, jint routerType) -{ - using Type = routing::RouterType; - Type type = Type::Vehicle; - switch (routerType) - { - case 0: break; - case 1: type = Type::Pedestrian; break; - case 2: type = Type::Bicycle; break; - case 3: type = Type::Transit; break; - case 4: type = Type::Ruler; break; - default: assert(false); break; - } - g_framework->GetRoutingManager().SetRouter(type); -} - -JNIEXPORT jint JNICALL -Java_app_organicmaps_Framework_nativeGetRouter(JNIEnv * env, jclass) -{ - return static_cast(g_framework->GetRoutingManager().GetRouter()); -} - -JNIEXPORT jint JNICALL -Java_app_organicmaps_Framework_nativeGetLastUsedRouter(JNIEnv * env, jclass) -{ - return static_cast(g_framework->GetRoutingManager().GetLastUsedRouter()); -} - -JNIEXPORT jint JNICALL -Java_app_organicmaps_Framework_nativeGetBestRouter(JNIEnv * env, jclass, - jdouble srcLat, jdouble srcLon, - jdouble dstLat, jdouble dstLon) -{ - return static_cast(frm()->GetRoutingManager().GetBestRouter( - mercator::FromLatLon(srcLat, srcLon), mercator::FromLatLon(dstLat, dstLon))); -} - JNIEXPORT void JNICALL Java_app_organicmaps_Framework_nativeAddRoutePoint(JNIEnv * env, jclass, jstring title, - jstring subtitle, jint markType, + jstring subtitle, jobject markType, jint intermediateIndex, jboolean isMyPosition, jdouble lat, jdouble lon) @@ -1570,7 +1458,7 @@ Java_app_organicmaps_Framework_nativeAddRoutePoint(JNIEnv * env, jclass, jstring RouteMarkData data; data.m_title = jni::ToNativeString(env, title); data.m_subTitle = jni::ToNativeString(env, subtitle); - data.m_pointType = static_cast(markType); + data.m_pointType = GetRouteMarkType(env, markType); data.m_intermediateIndex = static_cast(intermediateIndex); data.m_isMyPosition = static_cast(isMyPosition); data.m_position = m2::PointD(mercator::FromLatLon(lat, lon)); @@ -1585,10 +1473,9 @@ Java_app_organicmaps_Framework_nativeRemoveRoutePoints(JNIEnv * env, jclass) } JNIEXPORT void JNICALL -Java_app_organicmaps_Framework_nativeRemoveRoutePoint(JNIEnv * env, jclass, - jint markType, jint intermediateIndex) +Java_app_organicmaps_Framework_nativeRemoveRoutePoint(JNIEnv * env, jclass, jobject markType, jint intermediateIndex) { - frm()->GetRoutingManager().RemoveRoutePoint(static_cast(markType), + frm()->GetRoutingManager().RemoveRoutePoint(GetRouteMarkType(env, markType), static_cast(intermediateIndex)); } @@ -1607,30 +1494,7 @@ Java_app_organicmaps_Framework_nativeCouldAddIntermediatePoint(JNIEnv * env, jcl JNIEXPORT jobjectArray JNICALL Java_app_organicmaps_Framework_nativeGetRoutePoints(JNIEnv * env, jclass) { - auto const points = frm()->GetRoutingManager().GetRoutePoints(); - - static jclass const pointClazz = jni::GetGlobalClassRef(env, - "app/organicmaps/routing/RouteMarkData"); - // Java signature : RouteMarkData(String title, String subtitle, - // @RoutePointInfo.RouteMarkType int pointType, - // int intermediateIndex, boolean isVisible, boolean isMyPosition, - // boolean isPassed, double lat, double lon) - static jmethodID const pointConstructor = jni::GetConstructorID(env, pointClazz, - "(Ljava/lang/String;Ljava/lang/String;IIZZZDD)V"); - return jni::ToJavaArray(env, pointClazz, points, [&](JNIEnv * jEnv, RouteMarkData const & data) - { - jni::TScopedLocalRef const title(env, jni::ToJavaString(env, data.m_title)); - jni::TScopedLocalRef const subtitle(env, jni::ToJavaString(env, data.m_subTitle)); - return env->NewObject(pointClazz, pointConstructor, - title.get(), subtitle.get(), - static_cast(data.m_pointType), - static_cast(data.m_intermediateIndex), - static_cast(data.m_isVisible), - static_cast(data.m_isMyPosition), - static_cast(data.m_isPassed), - mercator::YToLat(data.m_position.y), - mercator::XToLon(data.m_position.x)); - }); + return CreateRouteMarkDataArray(env, frm()->GetRoutingManager().GetRoutePoints()); } JNIEXPORT void JNICALL @@ -1643,49 +1507,7 @@ Java_app_organicmaps_Framework_nativeMoveRoutePoint(JNIEnv * env, jclass, JNIEXPORT jobject JNICALL Java_app_organicmaps_Framework_nativeGetTransitRouteInfo(JNIEnv * env, jclass) { - auto const routeInfo = frm()->GetRoutingManager().GetTransitRouteInfo(); - - static jclass const transitStepClass = jni::GetGlobalClassRef(env, - "app/organicmaps/routing/TransitStepInfo"); - // Java signature : TransitStepInfo(@TransitType int type, @Nullable String distance, @Nullable String distanceUnits, - // int timeInSec, @Nullable String number, int color, int intermediateIndex) - static jmethodID const transitStepConstructor = jni::GetConstructorID(env, transitStepClass, - "(ILjava/lang/String;Ljava/lang/String;ILjava/lang/String;II)V"); - - jni::TScopedLocalRef const steps(env, jni::ToJavaArray(env, transitStepClass, - routeInfo.m_steps, - [&](JNIEnv * jEnv, TransitStepInfo const & stepInfo) - { - jni::TScopedLocalRef const distance(env, jni::ToJavaString(env, stepInfo.m_distanceStr)); - jni::TScopedLocalRef const distanceUnits(env, jni::ToJavaString(env, stepInfo.m_distanceUnitsSuffix)); - jni::TScopedLocalRef const number(env, jni::ToJavaString(env, stepInfo.m_number)); - return env->NewObject(transitStepClass, transitStepConstructor, - static_cast(stepInfo.m_type), - distance.get(), - distanceUnits.get(), - static_cast(stepInfo.m_timeInSec), - number.get(), - static_cast(stepInfo.m_colorARGB), - static_cast(stepInfo.m_intermediateIndex)); - })); - - static jclass const transitRouteInfoClass = jni::GetGlobalClassRef(env, - "app/organicmaps/routing/TransitRouteInfo"); - // Java signature : TransitRouteInfo(@NonNull String totalDistance, @NonNull String totalDistanceUnits, int totalTimeInSec, - // @NonNull String totalPedestrianDistance, @NonNull String totalPedestrianDistanceUnits, - // int totalPedestrianTimeInSec, @NonNull TransitStepInfo[] steps) - static jmethodID const transitRouteInfoConstructor = jni::GetConstructorID(env, transitRouteInfoClass, - "(Ljava/lang/String;Ljava/lang/String;I" - "Ljava/lang/String;Ljava/lang/String;I" - "[Lapp/organicmaps/routing/TransitStepInfo;)V"); - jni::TScopedLocalRef const distance(env, jni::ToJavaString(env, routeInfo.m_totalDistanceStr)); - jni::TScopedLocalRef const distanceUnits(env, jni::ToJavaString(env, routeInfo.m_totalDistanceUnitsSuffix)); - jni::TScopedLocalRef const distancePedestrian(env, jni::ToJavaString(env, routeInfo.m_totalPedestrianDistanceStr)); - jni::TScopedLocalRef const distancePedestrianUnits(env, jni::ToJavaString(env, routeInfo.m_totalPedestrianUnitsSuffix)); - return env->NewObject(transitRouteInfoClass, transitRouteInfoConstructor, - distance.get(), distanceUnits.get(), static_cast(routeInfo.m_totalTimeInSec), - distancePedestrian.get(), distancePedestrianUnits.get(), static_cast(routeInfo.m_totalPedestrianTimeInSec), - steps.get()); + return CreateTransitRouteInfo(env, frm()->GetRoutingManager().GetTransitRouteInfo()); } JNIEXPORT void JNICALL @@ -1821,25 +1643,6 @@ Java_app_organicmaps_Framework_nativeGetPoiContactUrl(JNIEnv *env, jclass, jint return jni::ToJavaString(env, value); } -JNIEXPORT void JNICALL -Java_app_organicmaps_Framework_nativeSetChoosePositionMode(JNIEnv *, jclass, jint mode, jboolean isBusiness, - jboolean applyPosition) -{ - // TODO(AB): Move this code into the Framework to share with iOS and other platforms. - auto const f = frm(); - if (applyPosition && f->HasPlacePageInfo()) - g_framework->SetChoosePositionMode(static_cast(mode), isBusiness, - &f->GetCurrentPlacePageInfo().GetMercator()); - else - g_framework->SetChoosePositionMode(static_cast(mode), isBusiness, nullptr); -} - -JNIEXPORT jint JNICALL -Java_app_organicmaps_Framework_nativeGetChoosePositionMode(JNIEnv *, jclass) -{ - return static_cast(g_framework->GetChoosePositionMode()); -} - JNIEXPORT jboolean JNICALL Java_app_organicmaps_Framework_nativeIsDownloadedMapAtScreenCenter(JNIEnv *, jclass) { diff --git a/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp b/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp deleted file mode 100644 index 88f38cfb0c..0000000000 --- a/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "app/organicmaps/Framework.hpp" - -#include "app/organicmaps/platform/AndroidPlatform.hpp" - -#include "app/organicmaps/core/jni_helper.hpp" - -extern "C" -{ - // static void nativeSetSettingsDir(String settingsPath); - JNIEXPORT void JNICALL - Java_app_organicmaps_MwmApplication_nativeSetSettingsDir(JNIEnv * env, jclass clazz, jstring settingsPath) - { - android::Platform::Instance().SetSettingsDir(jni::ToNativeString(env, settingsPath)); - } - - // static void nativeInitPlatform(Context context, String apkPath, String storagePath, String privatePath, String tmpPath, - // String flavorName, String buildType, boolean isTablet); - JNIEXPORT void JNICALL - Java_app_organicmaps_MwmApplication_nativeInitPlatform(JNIEnv * env, jclass clazz, jobject context, - jstring apkPath, jstring writablePath, - jstring privatePath, jstring tmpPath, - jstring flavorName, jstring buildType, - jboolean isTablet) - { - android::Platform::Instance().Initialize(env, context, apkPath, writablePath, privatePath, tmpPath, - flavorName, buildType, isTablet); - } - - // static void nativeInitFramework(@NonNull Runnable onComplete); - JNIEXPORT void JNICALL - Java_app_organicmaps_MwmApplication_nativeInitFramework(JNIEnv * env, jclass clazz, jobject onComplete) - { - if (!g_framework) - { - g_framework = std::make_unique([onComplete = jni::make_global_ref(onComplete)]() - { - JNIEnv * env = jni::GetEnv(); - jmethodID const methodId = jni::GetMethodID(env, *onComplete, "run", "()V"); - env->CallVoidMethod(*onComplete, methodId); - }); - } - } - - // static void nativeAddLocalization(String name, String value); - JNIEXPORT void JNICALL - Java_app_organicmaps_MwmApplication_nativeAddLocalization(JNIEnv * env, jclass clazz, jstring name, jstring value) - { - g_framework->AddString(jni::ToNativeString(env, name), - jni::ToNativeString(env, value)); - } - - JNIEXPORT void JNICALL - Java_app_organicmaps_MwmApplication_nativeOnTransit(JNIEnv *, jclass, jboolean foreground) - { - if (static_cast(foreground)) - g_framework->NativeFramework()->EnterForeground(); - else - g_framework->NativeFramework()->EnterBackground(); - } -} diff --git a/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.cpp b/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.cpp index 637352fd60..3ac89dd2f7 100644 --- a/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.cpp +++ b/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.cpp @@ -1,5 +1,7 @@ #include "UserMarkHelper.hpp" +#include "app/organicmaps/sdk/routing/RoutePointInfo.hpp" + #include "map/elevation_info.hpp" #include "map/place_page_info.hpp" @@ -47,7 +49,7 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info, int mapObje static jmethodID const ctorId = jni::GetConstructorID( env, g_mapObjectClazz, "(" - "Lapp/organicmaps/bookmarks/data/FeatureId;" // featureId + "Lapp/organicmaps/bookmarks/data/FeatureId;" // featureId "I" // mapObjectType "Ljava/lang/String;" // title "Ljava/lang/String;" // secondaryTitle @@ -55,7 +57,7 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info, int mapObje "Ljava/lang/String;" // address "DD" // lat, lon "Ljava/lang/String;" // appId - "Lapp/organicmaps/routing/RoutePointInfo;" // routePointInfo + "Lapp/organicmaps/sdk/routing/RoutePointInfo;" // routePointInfo "I" // openingMode "Lapp/organicmaps/sdk/search/Popularity;" // popularity "Ljava/lang/String;" // description @@ -104,7 +106,7 @@ jobject CreateBookmark(JNIEnv *env, const place_page::Info &info, jni::GetConstructorID(env, g_bookmarkClazz, "(Lapp/organicmaps/bookmarks/data/FeatureId;JJLjava/lang/String;" "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;" - "Lapp/organicmaps/routing/RoutePointInfo;" + "Lapp/organicmaps/sdk/routing/RoutePointInfo;" "ILapp/organicmaps/sdk/search/Popularity;Ljava/lang/String;" "[Ljava/lang/String;)V"); static jmethodID const featureCtorId = @@ -213,14 +215,6 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info) routingPointInfo.get(), popularity, jrawTypes.get()); } -jobject CreateRoutePointInfo(JNIEnv * env, place_page::Info const & info) -{ - static jclass const clazz = jni::GetGlobalClassRef(env, "app/organicmaps/routing/RoutePointInfo"); - static jmethodID const ctorId = jni::GetConstructorID(env, clazz, "(II)V"); - int const markType = static_cast(info.GetRouteMarkType()); - return env->NewObject(clazz, ctorId, markType, info.GetIntermediateIndex()); -} - jobject CreateFeatureId(JNIEnv * env, FeatureID const & fid) { static jmethodID const featureCtorId = diff --git a/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.hpp b/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.hpp index fed17e0c59..9a56c4c2f3 100644 --- a/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.hpp +++ b/android/app/src/main/cpp/app/organicmaps/UserMarkHelper.hpp @@ -40,8 +40,6 @@ jobjectArray ToRatingArray(JNIEnv * env, std::vector const & rating jobject CreateLocalAdInfo(JNIEnv * env, place_page::Info const & info); -jobject CreateRoutePointInfo(JNIEnv * env, place_page::Info const & info); - jobject CreateFeatureId(JNIEnv * env, FeatureID const & fid); jobjectArray ToFeatureIdArray(JNIEnv * env, std::vector const & ids); } // namespace usermark_helper diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/ChoosePositionMode.cpp b/android/app/src/main/cpp/app/organicmaps/sdk/ChoosePositionMode.cpp new file mode 100644 index 0000000000..c6e37227bc --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/ChoosePositionMode.cpp @@ -0,0 +1,26 @@ +#include "app/organicmaps/core/jni_helper.hpp" + +#include "app/organicmaps/Framework.hpp" + +#include "indexer/map_style.hpp" + +extern "C" +{ +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_ChoosePositionMode_nativeSet(JNIEnv *, jclass, jint mode, + jboolean isBusiness, + jboolean applyPosition) +{ + // TODO(AB): Move this code into the Framework to share with iOS and other platforms. + auto const f = frm(); + if (applyPosition && f->HasPlacePageInfo()) + g_framework->SetChoosePositionMode(static_cast(mode), isBusiness, + &f->GetCurrentPlacePageInfo().GetMercator()); + else + g_framework->SetChoosePositionMode(static_cast(mode), isBusiness, nullptr); +} + +JNIEXPORT jint JNICALL Java_app_organicmaps_sdk_ChoosePositionMode_nativeGet(JNIEnv *, jclass) +{ + return static_cast(g_framework->GetChoosePositionMode()); +} +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/MapStyle.cpp b/android/app/src/main/cpp/app/organicmaps/sdk/MapStyle.cpp new file mode 100644 index 0000000000..5e51c9c50c --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/MapStyle.cpp @@ -0,0 +1,27 @@ +#include "app/organicmaps/core/jni_helper.hpp" + +#include "app/organicmaps/Framework.hpp" + +#include "indexer/map_style.hpp" + +extern "C" +{ +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_MapStyle_nativeSet(JNIEnv *, jclass, jint mapStyle) +{ + auto const val = static_cast(mapStyle); + if (val != g_framework->GetMapStyle()) + g_framework->SetMapStyle(val); +} + +JNIEXPORT jint JNICALL Java_app_organicmaps_sdk_MapStyle_nativeGet(JNIEnv *, jclass) +{ + return g_framework->GetMapStyle(); +} + +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_MapStyle_nativeMark(JNIEnv *, jclass, jint mapStyle) +{ + auto const val = static_cast(mapStyle); + if (val != g_framework->GetMapStyle()) + g_framework->MarkMapStyle(val); +} +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp b/android/app/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp new file mode 100644 index 0000000000..8e676c7337 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp @@ -0,0 +1,56 @@ +#include "app/organicmaps/Framework.hpp" + +#include "app/organicmaps/platform/AndroidPlatform.hpp" + +#include "app/organicmaps/core/jni_helper.hpp" + +extern "C" +{ +// static void nativeSetSettingsDir(String settingsPath); +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeSetSettingsDir(JNIEnv * env, jclass clazz, + jstring settingsPath) +{ + android::Platform::Instance().SetSettingsDir(jni::ToNativeString(env, settingsPath)); +} + +// static void nativeInitPlatform(Context context, String apkPath, String storagePath, String privatePath, String +// tmpPath, String flavorName, String buildType, boolean isTablet); +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeInitPlatform( + JNIEnv * env, jclass clazz, jobject context, jstring apkPath, jstring writablePath, jstring privatePath, + jstring tmpPath, jstring flavorName, jstring buildType, jboolean isTablet) +{ + android::Platform::Instance().Initialize(env, context, apkPath, writablePath, privatePath, tmpPath, flavorName, + buildType, isTablet); +} + +// static void nativeInitFramework(@NonNull Runnable onComplete); +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeInitFramework(JNIEnv * env, jclass clazz, + jobject onComplete) +{ + if (!g_framework) + { + g_framework = std::make_unique( + [onComplete = jni::make_global_ref(onComplete)]() + { + JNIEnv * env = jni::GetEnv(); + jmethodID const methodId = jni::GetMethodID(env, *onComplete, "run", "()V"); + env->CallVoidMethod(*onComplete, methodId); + }); + } +} + +// static void nativeAddLocalization(String name, String value); +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeAddLocalization(JNIEnv * env, jclass clazz, + jstring name, jstring value) +{ + g_framework->AddString(jni::ToNativeString(env, name), jni::ToNativeString(env, value)); +} + +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeOnTransit(JNIEnv *, jclass, jboolean foreground) +{ + if (static_cast(foreground)) + g_framework->NativeFramework()->EnterForeground(); + else + g_framework->NativeFramework()->EnterBackground(); +} +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/Router.cpp b/android/app/src/main/cpp/app/organicmaps/sdk/Router.cpp new file mode 100644 index 0000000000..6a8aea0a90 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/Router.cpp @@ -0,0 +1,41 @@ +#include "app/organicmaps/core/jni_helper.hpp" + +#include "app/organicmaps/Framework.hpp" + +#include "indexer/map_style.hpp" + +extern "C" +{ +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_Router_nativeSet(JNIEnv *, jclass, jint routerType) +{ + using Type = routing::RouterType; + Type type; + switch (routerType) + { + case 0: type = Type::Vehicle; break; + case 1: type = Type::Pedestrian; break; + case 2: type = Type::Bicycle; break; + case 3: type = Type::Transit; break; + case 4: type = Type::Ruler; break; + default: assert(false); break; + } + frm()->GetRoutingManager().SetRouter(type); +} + +JNIEXPORT jint JNICALL Java_app_organicmaps_sdk_Router_nativeGet(JNIEnv *, jclass) +{ + return static_cast(frm()->GetRoutingManager().GetRouter()); +} + +JNIEXPORT jint JNICALL Java_app_organicmaps_sdk_Router_nativeGetLastUsed(JNIEnv *, jclass) +{ + return static_cast(frm()->GetRoutingManager().GetLastUsedRouter()); +} + +JNIEXPORT jint JNICALL Java_app_organicmaps_sdk_Router_nativeGetBest(JNIEnv *, jclass, jdouble srcLat, jdouble srcLon, + jdouble dstLat, jdouble dstLon) +{ + return static_cast(frm()->GetRoutingManager().GetBestRouter(mercator::FromLatLon(srcLat, srcLon), + mercator::FromLatLon(dstLat, dstLon))); +} +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp new file mode 100644 index 0000000000..8e8ac81017 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +#include "geometry/point2d.hpp" + +#include + +jobjectArray CreateJunctionInfoArray(JNIEnv * env, std::vector const & junctionPoints) +{ + static jclass const junctionClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/JunctionInfo"); + // Java signature : JunctionInfo(double lat, double lon) + static jmethodID const junctionConstructor = jni::GetConstructorID(env, junctionClazz, "(DD)V"); + + return jni::ToJavaArray(env, junctionClazz, junctionPoints, + [](JNIEnv * env, m2::PointD const & point) + { + return env->NewObject(junctionClazz, junctionConstructor, mercator::YToLat(point.y), + mercator::XToLon(point.x)); + }); +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteMarkData.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteMarkData.hpp new file mode 100644 index 0000000000..f36a3d4f9a --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteMarkData.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +#include "geometry/point2d.hpp" + +#include + +jobjectArray CreateRouteMarkDataArray(JNIEnv * env, std::vector const & points) +{ + static jclass const pointClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/RouteMarkData"); + // Java signature : RouteMarkData(String title, String subtitle, int pointType, + // int intermediateIndex, boolean isVisible, boolean isMyPosition, + // boolean isPassed, double lat, double lon) + static jmethodID const pointConstructor = + jni::GetConstructorID(env, pointClazz, "(Ljava/lang/String;Ljava/lang/String;IIZZZDD)V"); + return jni::ToJavaArray(env, pointClazz, points, + [&](JNIEnv * jEnv, RouteMarkData const & data) + { + jni::TScopedLocalRef const title(env, jni::ToJavaString(env, data.m_title)); + jni::TScopedLocalRef const subtitle(env, jni::ToJavaString(env, data.m_subTitle)); + return env->NewObject( + pointClazz, pointConstructor, title.get(), subtitle.get(), + static_cast(data.m_pointType), static_cast(data.m_intermediateIndex), + static_cast(data.m_isVisible), static_cast(data.m_isMyPosition), + static_cast(data.m_isPassed), mercator::YToLat(data.m_position.y), + mercator::XToLon(data.m_position.x)); + }); +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteMarkType.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteMarkType.hpp new file mode 100644 index 0000000000..6e064325d6 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteMarkType.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "app/organicmaps/sdk/routing/RouteMarkType.hpp" + +#include "map/routing_mark.hpp" + +RouteMarkType GetRouteMarkType(JNIEnv * env, jobject markType) +{ + static jmethodID const ordinal = jni::GetMethodID(env, markType, "ordinal", "()I"); + + return static_cast(env->CallIntMethod(markType, ordinal)); +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutePointInfo.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutePointInfo.hpp new file mode 100644 index 0000000000..22008dd3c1 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutePointInfo.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +#include "map/place_page_info.hpp" + +jobject CreateRoutePointInfo(JNIEnv * env, place_page::Info const & info) +{ + static jclass const clazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/RoutePointInfo"); + static jmethodID const ctorId = jni::GetConstructorID(env, clazz, "(II)V"); + int const markType = static_cast(info.GetRouteMarkType()); + return env->NewObject(clazz, ctorId, markType, info.GetIntermediateIndex()); +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteRecommendationType.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteRecommendationType.hpp new file mode 100644 index 0000000000..c944178204 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RouteRecommendationType.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +jobject GetRebuildAfterPointsLoading(JNIEnv * env) +{ + static jobject rebuildAfterPointsLoading = nullptr; + if (rebuildAfterPointsLoading) + return rebuildAfterPointsLoading; + + // Find the RouteRecommendationType class + jclass routeRecommendationTypeClass = env->FindClass("app/organicmaps/sdk/routing/RouteRecommendationType"); + ASSERT(routeRecommendationTypeClass, ()); + + // Get the values() method of RouteRecommendationType + jmethodID valuesMethod = env->GetStaticMethodID(routeRecommendationTypeClass, "values", + "()[Lapp/organicmaps/sdk/routing/RouteRecommendationType;"); + ASSERT(valuesMethod, ()); + + // Call values() to get all enum constants + jobjectArray enumConstants = (jobjectArray)env->CallStaticObjectMethod(routeRecommendationTypeClass, valuesMethod); + ASSERT(enumConstants, ()); + + // Retrieve the first (and only) constant, RebuildAfterPointsLoading + rebuildAfterPointsLoading = env->NewGlobalRef(env->GetObjectArrayElement(enumConstants, 0)); + ASSERT(rebuildAfterPointsLoading, ()); + + return rebuildAfterPointsLoading; +} + +jobject GetRouteRecommendationType(JNIEnv * env, RoutingManager::Recommendation recommendation) +{ + switch (recommendation) + { + case RoutingManager::Recommendation::RebuildAfterPointsLoading: return GetRebuildAfterPointsLoading(env); + default: ASSERT_FAIL("Unknown recommendation type"); + } +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutingInfo.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutingInfo.hpp new file mode 100644 index 0000000000..fbaa4e3298 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutingInfo.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" +#include "app/organicmaps/sdk/routing/SingleLaneInfo.hpp" + +#include "map/routing_manager.hpp" + +jobject CreateRoutingInfo(JNIEnv * env, routing::FollowingInfo const & info, RoutingManager & rm) +{ + static jclass const klass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/RoutingInfo"); + // Java signature : RoutingInfo(Distance distToTarget, Distance distToTurn, + // String currentStreet, String nextStreet, String nextNextStreet, + // double completionPercent, int vehicleTurnOrdinal, int + // vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum, + // int totalTime, SingleLaneInfo[] lanes) + static jmethodID const ctorRouteInfoID = + jni::GetConstructorID(env, klass, + "(Lapp/organicmaps/util/Distance;Lapp/organicmaps/util/Distance;" + "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;DIIIII" + "[Lapp/organicmaps/sdk/routing/SingleLaneInfo;DZZ)V"); + + jobjectArray jLanes = CreateLanesInfo(env, info.m_lanes); + + auto const isSpeedCamLimitExceeded = rm.IsSpeedCamLimitExceeded(); + auto const shouldPlaySignal = rm.GetSpeedCamManager().ShouldPlayBeepSignal(); + jobject const result = env->NewObject( + klass, ctorRouteInfoID, ToJavaDistance(env, info.m_distToTarget), ToJavaDistance(env, info.m_distToTurn), + jni::ToJavaString(env, info.m_currentStreetName), jni::ToJavaString(env, info.m_nextStreetName), + jni::ToJavaString(env, info.m_nextNextStreetName), info.m_completionPercent, info.m_turn, info.m_nextTurn, + info.m_pedestrianTurn, info.m_exitNum, info.m_time, jLanes, info.m_speedLimitMps, + static_cast(isSpeedCamLimitExceeded), static_cast(shouldPlaySignal)); + ASSERT(result, (jni::DescribeException())); + return result; +} diff --git a/android/app/src/main/cpp/app/organicmaps/routing/RoutingOptions.cpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutingOptions.cpp similarity index 71% rename from android/app/src/main/cpp/app/organicmaps/routing/RoutingOptions.cpp rename to android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutingOptions.cpp index 5480edd46d..7befa3174e 100644 --- a/android/app/src/main/cpp/app/organicmaps/routing/RoutingOptions.cpp +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/RoutingOptions.cpp @@ -5,16 +5,15 @@ routing::RoutingOptions::Road makeValue(jint option) { - uint8_t const road = static_cast(1u << static_cast(option)); + auto const road = static_cast(1u << static_cast(option)); CHECK_LESS(road, static_cast(routing::RoutingOptions::Road::Max), ()); return static_cast(road); } extern "C" { - -JNIEXPORT jboolean JNICALL -Java_app_organicmaps_routing_RoutingOptions_nativeHasOption(JNIEnv * env, jclass clazz, jint option) +JNIEXPORT jboolean JNICALL Java_app_organicmaps_sdk_routing_RoutingOptions_nativeHasOption(JNIEnv *, jclass, + jint option) { CHECK(g_framework, ("Framework isn't created yet!")); routing::RoutingOptions routingOptions = routing::RoutingOptions::LoadCarOptionsFromSettings(); @@ -22,8 +21,7 @@ Java_app_organicmaps_routing_RoutingOptions_nativeHasOption(JNIEnv * env, jclass return static_cast(routingOptions.Has(road)); } -JNIEXPORT void JNICALL -Java_app_organicmaps_routing_RoutingOptions_nativeAddOption(JNIEnv * env, jclass clazz, jint option) +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_routing_RoutingOptions_nativeAddOption(JNIEnv *, jclass, jint option) { CHECK(g_framework, ("Framework isn't created yet!")); routing::RoutingOptions routingOptions = routing::RoutingOptions::LoadCarOptionsFromSettings(); @@ -32,9 +30,7 @@ Java_app_organicmaps_routing_RoutingOptions_nativeAddOption(JNIEnv * env, jclass routing::RoutingOptions::SaveCarOptionsToSettings(routingOptions); } - -JNIEXPORT void JNICALL -Java_app_organicmaps_routing_RoutingOptions_nativeRemoveOption(JNIEnv * env, jclass clazz, jint option) +JNIEXPORT void JNICALL Java_app_organicmaps_sdk_routing_RoutingOptions_nativeRemoveOption(JNIEnv *, jclass, jint option) { CHECK(g_framework, ("Framework isn't created yet!")); routing::RoutingOptions routingOptions = routing::RoutingOptions::LoadCarOptionsFromSettings(); diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/SingleLaneInfo.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/SingleLaneInfo.hpp new file mode 100644 index 0000000000..cea8ee6434 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/SingleLaneInfo.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +#include "routing/following_info.hpp" + +#include + +jobjectArray CreateLanesInfo(JNIEnv * env, std::vector const & lanes) +{ + if (lanes.empty()) + return nullptr; + + static jclass const laneClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/SingleLaneInfo"); + auto const lanesSize = static_cast(lanes.size()); + jobjectArray jLanes = env->NewObjectArray(lanesSize, laneClass, nullptr); + ASSERT(jLanes, (jni::DescribeException())); + static jmethodID const ctorSingleLaneInfoID = jni::GetConstructorID(env, laneClass, "([BZ)V"); + + for (jsize j = 0; j < lanesSize; ++j) + { + auto const laneSize = static_cast(lanes[j].m_lane.size()); + jni::TScopedLocalByteArrayRef singleLane(env, env->NewByteArray(laneSize)); + ASSERT(singleLane.get(), (jni::DescribeException())); + env->SetByteArrayRegion(singleLane.get(), 0, laneSize, lanes[j].m_lane.data()); + + jni::TScopedLocalRef singleLaneInfo( + env, env->NewObject(laneClass, ctorSingleLaneInfoID, singleLane.get(), lanes[j].m_isRecommended)); + ASSERT(singleLaneInfo.get(), (jni::DescribeException())); + env->SetObjectArrayElement(jLanes, j, singleLaneInfo.get()); + } + + return jLanes; +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/TransitRouteInfo.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/TransitRouteInfo.hpp new file mode 100644 index 0000000000..1401fa2b43 --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/TransitRouteInfo.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +#include "app/organicmaps/sdk/routing/TransitStepInfo.hpp" + +#include "map/transit/transit_display.hpp" + +jobject CreateTransitRouteInfo(JNIEnv * env, TransitRouteInfo const & routeInfo) +{ + jobjectArray steps = CreateTransitStepInfoArray(env, routeInfo.m_steps); + + static jclass const transitRouteInfoClass = + jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/TransitRouteInfo"); + // Java signature : TransitRouteInfo(@NonNull String totalDistance, @NonNull String totalDistanceUnits, + // int totalTimeInSec, @NonNull String totalPedestrianDistance, @NonNull String + // totalPedestrianDistanceUnits, int totalPedestrianTimeInSec, @NonNull + // TransitStepInfo[] steps) + static jmethodID const transitRouteInfoConstructor = + jni::GetConstructorID(env, transitRouteInfoClass, + "(Ljava/lang/String;Ljava/lang/String;I" + "Ljava/lang/String;Ljava/lang/String;I" + "[Lapp/organicmaps/sdk/routing/TransitStepInfo;)V"); + jni::TScopedLocalRef const distance(env, jni::ToJavaString(env, routeInfo.m_totalDistanceStr)); + jni::TScopedLocalRef const distanceUnits(env, jni::ToJavaString(env, routeInfo.m_totalDistanceUnitsSuffix)); + jni::TScopedLocalRef const distancePedestrian(env, jni::ToJavaString(env, routeInfo.m_totalPedestrianDistanceStr)); + jni::TScopedLocalRef const distancePedestrianUnits(env, + jni::ToJavaString(env, routeInfo.m_totalPedestrianUnitsSuffix)); + return env->NewObject(transitRouteInfoClass, transitRouteInfoConstructor, distance.get(), distanceUnits.get(), + static_cast(routeInfo.m_totalTimeInSec), distancePedestrian.get(), + distancePedestrianUnits.get(), static_cast(routeInfo.m_totalPedestrianTimeInSec), steps); +} diff --git a/android/app/src/main/cpp/app/organicmaps/sdk/routing/TransitStepInfo.hpp b/android/app/src/main/cpp/app/organicmaps/sdk/routing/TransitStepInfo.hpp new file mode 100644 index 0000000000..2cba3b102d --- /dev/null +++ b/android/app/src/main/cpp/app/organicmaps/sdk/routing/TransitStepInfo.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "app/organicmaps/core/jni_helper.hpp" + +#include "map/transit/transit_display.hpp" + +#include + +jobjectArray CreateTransitStepInfoArray(JNIEnv * env, std::vector const & steps) +{ + static jclass const transitStepClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/TransitStepInfo"); + // Java signature : TransitStepInfo(int type, @Nullable String distance, @Nullable String distanceUnits, + // int timeInSec, @Nullable String number, int color, int intermediateIndex) + static jmethodID const transitStepConstructor = + jni::GetConstructorID(env, transitStepClass, "(ILjava/lang/String;Ljava/lang/String;ILjava/lang/String;II)V"); + + return jni::ToJavaArray( + env, transitStepClass, steps, + [&](JNIEnv * jEnv, TransitStepInfo const & stepInfo) + { + jni::TScopedLocalRef const distance(env, jni::ToJavaString(env, stepInfo.m_distanceStr)); + jni::TScopedLocalRef const distanceUnits(env, jni::ToJavaString(env, stepInfo.m_distanceUnitsSuffix)); + jni::TScopedLocalRef const number(env, jni::ToJavaString(env, stepInfo.m_number)); + return env->NewObject(transitStepClass, transitStepConstructor, static_cast(stepInfo.m_type), + distance.get(), distanceUnits.get(), static_cast(stepInfo.m_timeInSec), number.get(), + static_cast(stepInfo.m_colorARGB), static_cast(stepInfo.m_intermediateIndex)); + }); +} diff --git a/android/app/src/main/java/app/organicmaps/Framework.java b/android/app/src/main/java/app/organicmaps/Framework.java index 358c03014b..d67f9a333e 100644 --- a/android/app/src/main/java/app/organicmaps/Framework.java +++ b/android/app/src/main/java/app/organicmaps/Framework.java @@ -2,9 +2,7 @@ package app.organicmaps; import android.graphics.Bitmap; -import androidx.annotation.IntDef; import androidx.annotation.Keep; -import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.Size; @@ -15,19 +13,20 @@ import app.organicmaps.api.RequestType; import app.organicmaps.bookmarks.data.DistanceAndAzimut; import app.organicmaps.bookmarks.data.FeatureId; import app.organicmaps.bookmarks.data.MapObject; -import app.organicmaps.products.Product; import app.organicmaps.products.ProductsConfig; -import app.organicmaps.routing.JunctionInfo; -import app.organicmaps.routing.RouteMarkData; -import app.organicmaps.routing.RoutePointInfo; -import app.organicmaps.routing.RoutingInfo; -import app.organicmaps.routing.TransitRouteInfo; +import app.organicmaps.sdk.routing.JunctionInfo; +import app.organicmaps.sdk.routing.RouteMarkData; +import app.organicmaps.sdk.routing.RouteMarkType; +import app.organicmaps.sdk.routing.RoutingInfo; +import app.organicmaps.sdk.routing.TransitRouteInfo; +import app.organicmaps.sdk.PlacePageActivationListener; +import app.organicmaps.sdk.routing.RoutingListener; +import app.organicmaps.sdk.routing.RoutingLoadPointsListener; +import app.organicmaps.sdk.routing.RoutingProgressListener; +import app.organicmaps.sdk.routing.RoutingRecommendationListener; import app.organicmaps.settings.SettingsPrefsFragment; -import app.organicmaps.widget.placepage.PlacePageData; import app.organicmaps.util.Constants; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -39,87 +38,6 @@ import java.util.Locale; */ public class Framework { - @Retention(RetentionPolicy.SOURCE) - @IntDef({MAP_STYLE_CLEAR, MAP_STYLE_DARK, MAP_STYLE_VEHICLE_CLEAR, MAP_STYLE_VEHICLE_DARK, MAP_STYLE_OUTDOORS_CLEAR, MAP_STYLE_OUTDOORS_DARK}) - - public @interface MapStyle {} - - public static final int MAP_STYLE_CLEAR = 0; - public static final int MAP_STYLE_DARK = 1; - public static final int MAP_STYLE_VEHICLE_CLEAR = 3; - public static final int MAP_STYLE_VEHICLE_DARK = 4; - public static final int MAP_STYLE_OUTDOORS_CLEAR = 5; - public static final int MAP_STYLE_OUTDOORS_DARK = 6; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ ROUTER_TYPE_VEHICLE, ROUTER_TYPE_PEDESTRIAN, ROUTER_TYPE_BICYCLE, ROUTER_TYPE_TRANSIT, ROUTER_TYPE_RULER }) - - public @interface RouterType {} - - public static final int ROUTER_TYPE_VEHICLE = 0; - public static final int ROUTER_TYPE_PEDESTRIAN = 1; - public static final int ROUTER_TYPE_BICYCLE = 2; - public static final int ROUTER_TYPE_TRANSIT = 3; - public static final int ROUTER_TYPE_RULER = 4; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ROUTE_REBUILD_AFTER_POINTS_LOADING}) - public @interface RouteRecommendationType {} - - public static final int ROUTE_REBUILD_AFTER_POINTS_LOADING = 0; - - public interface PlacePageActivationListener - { - // Called from JNI. - @Keep - @SuppressWarnings("unused") - void onPlacePageActivated(@NonNull PlacePageData data); - - // Called from JNI - @Keep - @SuppressWarnings("unused") - void onPlacePageDeactivated(); - - // Called from JNI - @Keep - @SuppressWarnings("unused") - void onSwitchFullScreenMode(); - } - - public interface RoutingListener - { - // Called from JNI - @Keep - @SuppressWarnings("unused") - @MainThread - void onRoutingEvent(int resultCode, String[] missingMaps); - } - - public interface RoutingProgressListener - { - // Called from JNI. - @Keep - @SuppressWarnings("unused") - @MainThread - void onRouteBuildingProgress(float progress); - } - - public interface RoutingRecommendationListener - { - // Called from JNI. - @Keep - @SuppressWarnings("unused") - void onRecommend(@RouteRecommendationType int recommendation); - } - - public interface RoutingLoadPointsListener - { - // Called from JNI. - @Keep - @SuppressWarnings("unused") - void onRoutePointsLoaded(boolean success); - } - // Used by JNI. @Keep @SuppressWarnings("unused") @@ -301,38 +219,16 @@ public class Framework private static native void nativeSetSpeedCamManagerMode(int mode); - public static native void nativeSetRoutingListener(RoutingListener listener); + public static native void nativeSetRoutingListener(@NonNull RoutingListener listener); - public static native void nativeSetRouteProgressListener(RoutingProgressListener listener); + public static native void nativeSetRouteProgressListener(@NonNull RoutingProgressListener listener); - public static native void nativeSetRoutingRecommendationListener(RoutingRecommendationListener listener); + public static native void nativeSetRoutingRecommendationListener(@NonNull RoutingRecommendationListener listener); - public static native void nativeSetRoutingLoadPointsListener( - @Nullable RoutingLoadPointsListener listener); + public static native void nativeSetRoutingLoadPointsListener(@NonNull RoutingLoadPointsListener listener); public static native void nativeShowCountry(String countryId, boolean zoomToDownloadButton); - public static native void nativeSetMapStyle(int mapStyle); - - @MapStyle - public static native int nativeGetMapStyle(); - - /** - * This method allows to set new map style without immediate applying. It can be used before - * engine recreation instead of nativeSetMapStyle to avoid huge flow of OpenGL invocations. - * @param mapStyle style index - */ - public static native void nativeMarkMapStyle(int mapStyle); - - public static native void nativeSetRouter(@RouterType int routerType); - @RouterType - public static native int nativeGetRouter(); - @RouterType - public static native int nativeGetLastUsedRouter(); - @RouterType - public static native int nativeGetBestRouter(double srcLat, double srcLon, - double dstLat, double dstLon); - public static void addRoutePoint(RouteMarkData point) { Framework.nativeAddRoutePoint(point.mTitle, point.mSubtitle, point.mPointType, @@ -340,15 +236,13 @@ public class Framework point.mLat, point.mLon); } - public static native void nativeAddRoutePoint(String title, String subtitle, - @RoutePointInfo.RouteMarkType int markType, + public static native void nativeAddRoutePoint(String title, String subtitle, @NonNull RouteMarkType markType, int intermediateIndex, boolean isMyPosition, double lat, double lon); public static native void nativeRemoveRoutePoints(); - public static native void nativeRemoveRoutePoint(@RoutePointInfo.RouteMarkType int markType, - int intermediateIndex); + public static native void nativeRemoveRoutePoint(@NonNull RouteMarkType markType, int intermediateIndex); public static native void nativeRemoveIntermediateRoutePoints(); @@ -404,23 +298,6 @@ public class Framework public static native void nativeZoomToPoint(double lat, double lon, int zoom, boolean animate); - @Retention(RetentionPolicy.SOURCE) - @IntDef({ChoosePositionMode.NONE, ChoosePositionMode.EDITOR, ChoosePositionMode.API}) - public @interface ChoosePositionMode - { - // Keep in sync with `enum ChoosePositionMode` in Framework.hpp. - public static final int NONE = 0; - public static final int EDITOR = 1; - public static final int API = 2; - } - /** - * @param mode - see ChoosePositionMode values. - * @param isBusiness selection area will be bounded by building borders, if its true (eg. true for businesses in buildings). - * @param applyPosition if true, map'll be animated to currently selected object. - */ - public static native void nativeSetChoosePositionMode(@ChoosePositionMode int mode, boolean isBusiness, - boolean applyPosition); - public static native @ChoosePositionMode int nativeGetChoosePositionMode(); public static native boolean nativeIsDownloadedMapAtScreenCenter(); public static native String nativeGetActiveObjectFormattedCuisine(); @@ -446,7 +323,7 @@ public class Framework public static native void nativeMakeCrash(); - public static native void nativeSetPowerManagerFacility(int facilityType, boolean state); + public static native void nativeSetPowerManagerFacility(int facilityType, boolean state); public static native int nativeGetPowerManagerScheme(); public static native void nativeSetPowerManagerScheme(int schemeType); public static native void nativeSetViewportCenter(double lat, double lon, int zoom); diff --git a/android/app/src/main/java/app/organicmaps/MwmActivity.java b/android/app/src/main/java/app/organicmaps/MwmActivity.java index ac3f498b48..f1fd6450e6 100644 --- a/android/app/src/main/java/app/organicmaps/MwmActivity.java +++ b/android/app/src/main/java/app/organicmaps/MwmActivity.java @@ -40,7 +40,6 @@ import androidx.fragment.app.FragmentFactory; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.ViewModelProvider; -import app.organicmaps.Framework.PlacePageActivationListener; import app.organicmaps.api.Const; import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.OnBackPressListener; @@ -80,13 +79,17 @@ import app.organicmaps.maplayer.isolines.IsolinesState; import app.organicmaps.routing.ManageRouteBottomSheet; import app.organicmaps.routing.NavigationController; import app.organicmaps.routing.NavigationService; -import app.organicmaps.routing.RoutePointInfo; +import app.organicmaps.sdk.routing.RouteMarkType; +import app.organicmaps.sdk.routing.RoutePointInfo; import app.organicmaps.routing.RoutingBottomMenuListener; import app.organicmaps.routing.RoutingController; import app.organicmaps.routing.RoutingErrorDialogFragment; -import app.organicmaps.routing.RoutingOptions; +import app.organicmaps.sdk.routing.RoutingOptions; import app.organicmaps.routing.RoutingPlanFragment; import app.organicmaps.routing.RoutingPlanInplaceController; +import app.organicmaps.sdk.ChoosePositionMode; +import app.organicmaps.sdk.PlacePageActivationListener; +import app.organicmaps.sdk.Router; import app.organicmaps.search.FloatingSearchToolbarController; import app.organicmaps.search.SearchActivity; import app.organicmaps.sdk.search.SearchEngine; @@ -584,7 +587,7 @@ public class MwmActivity extends BaseMwmFragmentActivity UiUtils.setLightStatusBar(this, !( ThemeUtils.isNightTheme(this) || RoutingController.get().isPlanning() - || Framework.nativeGetChoosePositionMode() != Framework.ChoosePositionMode.NONE + || ChoosePositionMode.get() != ChoosePositionMode.None )); } @@ -645,9 +648,9 @@ public class MwmActivity extends BaseMwmFragmentActivity mPointChooser.findViewById(R.id.done).setOnClickListener( v -> { - switch (Framework.nativeGetChoosePositionMode()) + switch (ChoosePositionMode.get()) { - case Framework.ChoosePositionMode.API: + case Api: final Intent apiResult = new Intent(); final double[] center = Framework.nativeGetScreenRectCenter(); apiResult.putExtra(Const.EXTRA_POINT_LAT, center[0]); @@ -656,7 +659,7 @@ public class MwmActivity extends BaseMwmFragmentActivity setResult(Activity.RESULT_OK, apiResult); finish(); break; - case Framework.ChoosePositionMode.EDITOR: + case Editor: if (Framework.nativeIsDownloadedMapAtScreenCenter()) startActivity(new Intent(MwmActivity.this, FeatureCategoryActivity.class)); else @@ -669,7 +672,7 @@ public class MwmActivity extends BaseMwmFragmentActivity .show(); } break; - case Framework.ChoosePositionMode.NONE: + case None: throw new IllegalStateException("Unexpected Framework.nativeGetChoosePositionMode()"); } closePositionChooser(); @@ -715,7 +718,7 @@ public class MwmActivity extends BaseMwmFragmentActivity public void showPositionChooserForAPI(@Nullable String appName) { - showPositionChooser(Framework.ChoosePositionMode.API, false, false); + showPositionChooser(ChoosePositionMode.Api, false, false); if (!TextUtils.isEmpty(appName)) { setTitle(appName); @@ -725,26 +728,26 @@ public class MwmActivity extends BaseMwmFragmentActivity public void showPositionChooserForEditor(boolean isBusiness, boolean applyPosition) { - showPositionChooser(Framework.ChoosePositionMode.EDITOR, isBusiness, applyPosition); + showPositionChooser(ChoosePositionMode.Editor, isBusiness, applyPosition); } - private void showPositionChooser(@Framework.ChoosePositionMode int mode, boolean isBusiness, boolean applyPosition) + private void showPositionChooser(ChoosePositionMode mode, boolean isBusiness, boolean applyPosition) { closeFloatingToolbarsAndPanels(false); UiUtils.show(mPointChooser); mMapButtonsViewModel.setButtonsHidden(true); - Framework.nativeSetChoosePositionMode(mode, isBusiness, applyPosition); + ChoosePositionMode.set(mode, isBusiness, applyPosition); refreshLightStatusBar(); } private void hidePositionChooser() { UiUtils.hide(mPointChooser); - @Framework.ChoosePositionMode int mode = Framework.nativeGetChoosePositionMode(); - Framework.nativeSetChoosePositionMode(Framework.ChoosePositionMode.NONE, false, false); + ChoosePositionMode mode = ChoosePositionMode.get(); + ChoosePositionMode.set(ChoosePositionMode.None, false, false); mMapButtonsViewModel.setButtonsHidden(false); refreshLightStatusBar(); - if (mode == Framework.ChoosePositionMode.API) + if (mode == ChoosePositionMode.Api) finish(); } @@ -1100,7 +1103,7 @@ public class MwmActivity extends BaseMwmFragmentActivity ThemeSwitcher.INSTANCE.restart(isMapRendererActive()); refreshSearchToolbar(); setFullscreen(isFullscreen()); - if (Framework.nativeGetChoosePositionMode() != Framework.ChoosePositionMode.NONE) + if (ChoosePositionMode.get() != ChoosePositionMode.None) { UiUtils.show(mPointChooser); mMapButtonsViewModel.setButtonsHidden(true); @@ -1314,7 +1317,7 @@ public class MwmActivity extends BaseMwmFragmentActivity { // Buttons are hidden in position chooser mode but we are not in fullscreen return Boolean.TRUE.equals(mMapButtonsViewModel.getButtonsHidden().getValue()) && - Framework.nativeGetChoosePositionMode() == Framework.ChoosePositionMode.NONE; + ChoosePositionMode.get() == ChoosePositionMode.None; } @Override @@ -1578,7 +1581,7 @@ public class MwmActivity extends BaseMwmFragmentActivity } @Override - public void updateBuildProgress(int progress, @Framework.RouterType int router) + public void updateBuildProgress(int progress, Router router) { if (mIsTabletLayout) { @@ -2133,7 +2136,7 @@ public class MwmActivity extends BaseMwmFragmentActivity } @Override - public void onSearchRoutePoint(@RoutePointInfo.RouteMarkType int pointType) + public void onSearchRoutePoint(@NonNull RouteMarkType pointType) { RoutingController.get().waitForPoiPick(pointType); closeSearchToolbar(true, true); diff --git a/android/app/src/main/java/app/organicmaps/MwmApplication.java b/android/app/src/main/java/app/organicmaps/MwmApplication.java index fc06fdb9fe..a3623632c4 100644 --- a/android/app/src/main/java/app/organicmaps/MwmApplication.java +++ b/android/app/src/main/java/app/organicmaps/MwmApplication.java @@ -20,10 +20,9 @@ import java.io.IOException; import java.lang.ref.WeakReference; import app.organicmaps.background.OsmUploadWork; -import app.organicmaps.bookmarks.data.BookmarkManager; -import app.organicmaps.display.DisplayManager; import app.organicmaps.downloader.Android7RootCertificateWorkaround; import app.organicmaps.downloader.DownloaderNotifier; +import app.organicmaps.display.DisplayManager; import app.organicmaps.location.LocationHelper; import app.organicmaps.location.LocationState; import app.organicmaps.location.SensorHelper; @@ -31,18 +30,11 @@ import app.organicmaps.location.TrackRecorder; import app.organicmaps.location.TrackRecordingService; import app.organicmaps.maplayer.isolines.IsolinesManager; import app.organicmaps.maplayer.subway.SubwayManager; -import app.organicmaps.maplayer.traffic.TrafficManager; import app.organicmaps.routing.NavigationService; import app.organicmaps.routing.RoutingController; -import app.organicmaps.sdk.search.SearchEngine; -import app.organicmaps.settings.StoragePathManager; -import app.organicmaps.sound.TtsPlayer; +import app.organicmaps.sdk.OrganicMaps; import app.organicmaps.util.Config; import app.organicmaps.util.ConnectionState; -import app.organicmaps.util.SharedPropertiesUtils; -import app.organicmaps.util.StorageUtils; -import app.organicmaps.util.ThemeSwitcher; -import app.organicmaps.util.UiUtils; import app.organicmaps.util.Utils; import app.organicmaps.util.log.Logger; import app.organicmaps.util.log.LogsManager; @@ -52,6 +44,10 @@ public class MwmApplication extends Application implements Application.ActivityL @NonNull private static final String TAG = MwmApplication.class.getSimpleName(); + @SuppressWarnings("NotNullFieldNotInitialized") + @NonNull + private OrganicMaps mOrganicMaps; + @SuppressWarnings("NotNullFieldNotInitialized") @NonNull private SubwayManager mSubwayManager; @@ -72,9 +68,6 @@ public class MwmApplication extends Application implements Application.ActivityL @NonNull private DisplayManager mDisplayManager; - private volatile boolean mFrameworkInitialized; - private volatile boolean mPlatformInitialized; - @Nullable private WeakReference mTopActivity; @@ -115,6 +108,12 @@ public class MwmApplication extends Application implements Application.ActivityL return mDisplayManager; } + @NonNull + public OrganicMaps getOrganicMaps() + { + return mOrganicMaps; + } + @NonNull public static MwmApplication from(@NonNull Context context) { @@ -138,20 +137,12 @@ public class MwmApplication extends Application implements Application.ActivityL sInstance = this; + mOrganicMaps = new OrganicMaps(getApplicationContext()); + LogsManager.INSTANCE.initFileLogging(this); Android7RootCertificateWorkaround.initializeIfNeeded(this); - // Set configuration directory as early as possible. - // Other methods may explicitly use Config, which requires settingsDir to be set. - final String settingsPath = StorageUtils.getSettingsPath(this); - if (!StorageUtils.createDirectory(settingsPath)) - throw new AssertionError("Can't create settingsDir " + settingsPath); - Logger.d(TAG, "Settings path = " + settingsPath); - nativeSetSettingsDir(settingsPath); - - Config.init(this); - ConnectionState.INSTANCE.initialize(this); DownloaderNotifier.createNotificationChannel(this); @@ -166,117 +157,16 @@ public class MwmApplication extends Application implements Application.ActivityL mDisplayManager = new DisplayManager(); } - /** - * Initialize native core of application: platform and framework. - * - * @throws IOException - if failed to create directories. Caller must handle - * the exception and do nothing with native code if initialization is failed. - */ - public boolean init(@NonNull Runnable onComplete) throws IOException + public boolean initOrganicMaps(@NonNull Runnable onComplete) throws IOException { - initNativePlatform(); - return initNativeFramework(onComplete); + return mOrganicMaps.init(() -> { + ProcessLifecycleOwner.get().getLifecycle().addObserver(mProcessLifecycleObserver); + onComplete.run(); + }); } - private void initNativePlatform() throws IOException + private final LifecycleObserver mProcessLifecycleObserver = new DefaultLifecycleObserver() { - if (mPlatformInitialized) - return; - - final String apkPath = StorageUtils.getApkPath(this); - Logger.d(TAG, "Apk path = " + apkPath); - // Note: StoragePathManager uses Config, which requires SettingsDir to be set. - final String writablePath = StoragePathManager.findMapsStorage(this); - Logger.d(TAG, "Writable path = " + writablePath); - final String privatePath = StorageUtils.getPrivatePath(this); - Logger.d(TAG, "Private path = " + privatePath); - final String tempPath = StorageUtils.getTempPath(this); - Logger.d(TAG, "Temp path = " + tempPath); - - // If platform directories are not created it means that native part of app will not be able - // to work at all. So, we just ignore native part initialization in this case, e.g. when the - // external storage is damaged or not available (read-only). - createPlatformDirectories(writablePath, privatePath, tempPath); - - nativeInitPlatform(getApplicationContext(), - apkPath, - writablePath, - privatePath, - tempPath, - app.organicmaps.BuildConfig.FLAVOR, - app.organicmaps.BuildConfig.BUILD_TYPE, UiUtils.isTablet(this)); - Config.setStoragePath(writablePath); - Config.setStatisticsEnabled(SharedPropertiesUtils.isStatisticsEnabled(this)); - - mPlatformInitialized = true; - Logger.i(TAG, "Platform initialized"); - } - - private void createPlatformDirectories(@NonNull String writablePath, - @NonNull String privatePath, - @NonNull String tempPath) throws IOException - { - SharedPropertiesUtils.emulateBadExternalStorage(this); - - StorageUtils.requireDirectory(writablePath); - StorageUtils.requireDirectory(privatePath); - StorageUtils.requireDirectory(tempPath); - } - - private boolean initNativeFramework(@NonNull Runnable onComplete) - { - if (mFrameworkInitialized) - return false; - - nativeInitFramework(onComplete); - - initNativeStrings(); - ThemeSwitcher.INSTANCE.initialize(this); - SearchEngine.INSTANCE.initialize(); - BookmarkManager.loadBookmarks(); - TtsPlayer.INSTANCE.initialize(this); - ThemeSwitcher.INSTANCE.restart(false); - RoutingController.get().initialize(this); - TrafficManager.INSTANCE.initialize(); - SubwayManager.from(this).initialize(); - IsolinesManager.from(this).initialize(); - ProcessLifecycleOwner.get().getLifecycle().addObserver(mProcessLifecycleObserver); - - Logger.i(TAG, "Framework initialized"); - mFrameworkInitialized = true; - return true; - } - - private void initNativeStrings() - { - nativeAddLocalization("core_entrance", getString(R.string.core_entrance)); - nativeAddLocalization("core_exit", getString(R.string.core_exit)); - nativeAddLocalization("core_my_places", getString(R.string.core_my_places)); - nativeAddLocalization("core_my_position", getString(R.string.core_my_position)); - nativeAddLocalization("core_placepage_unknown_place", getString(R.string.core_placepage_unknown_place)); - nativeAddLocalization("postal_code", getString(R.string.postal_code)); - nativeAddLocalization("wifi", getString(R.string.category_wifi)); - } - - public boolean arePlatformAndCoreInitialized() - { - return mFrameworkInitialized && mPlatformInitialized; - } - - static - { - System.loadLibrary("organicmaps"); - } - - private static native void nativeSetSettingsDir(String settingsPath); - private static native void nativeInitPlatform(Context context, String apkPath, String writablePath, - String privatePath, String tmpPath, String flavorName, - String buildType, boolean isTablet); - private static native void nativeInitFramework(@NonNull Runnable onComplete); - private static native void nativeAddLocalization(String name, String value); - private static native void nativeOnTransit(boolean foreground); - - private final LifecycleObserver mProcessLifecycleObserver = new DefaultLifecycleObserver() { @Override public void onStart(@NonNull LifecycleOwner owner) { @@ -334,8 +224,6 @@ public class MwmApplication extends Application implements Application.ActivityL { Logger.d(TAG); - nativeOnTransit(true); - mLocationHelper.resumeLocationInForeground(); } @@ -343,8 +231,6 @@ public class MwmApplication extends Application implements Application.ActivityL { Logger.d(TAG); - nativeOnTransit(false); - OsmUploadWork.startActionUploadOsmChanges(this); if (!mDisplayManager.isDeviceDisplayUsed()) diff --git a/android/app/src/main/java/app/organicmaps/SplashActivity.java b/android/app/src/main/java/app/organicmaps/SplashActivity.java index 37c7cd976b..2089887c83 100644 --- a/android/app/src/main/java/app/organicmaps/SplashActivity.java +++ b/android/app/src/main/java/app/organicmaps/SplashActivity.java @@ -2,7 +2,6 @@ package app.organicmaps; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; -import static app.organicmaps.api.Const.EXTRA_PICK_POINT; import android.content.ComponentName; import android.content.Context; @@ -146,7 +145,7 @@ public class SplashActivity extends AppCompatActivity boolean asyncContinue = false; try { - asyncContinue = app.init(this::processNavigation); + asyncContinue = app.initOrganicMaps(this::processNavigation); } catch (IOException error) { showFatalErrorDialog(R.string.dialog_error_storage_title, R.string.dialog_error_storage_message, error); diff --git a/android/app/src/main/java/app/organicmaps/api/ParsedRoutingData.java b/android/app/src/main/java/app/organicmaps/api/ParsedRoutingData.java index d9240d2406..485ccdb02b 100644 --- a/android/app/src/main/java/app/organicmaps/api/ParsedRoutingData.java +++ b/android/app/src/main/java/app/organicmaps/api/ParsedRoutingData.java @@ -2,7 +2,7 @@ package app.organicmaps.api; import androidx.annotation.Keep; -import app.organicmaps.Framework; +import app.organicmaps.sdk.Router; /** * Represents Framework::ParsedRoutingData from core. @@ -13,11 +13,10 @@ import app.organicmaps.Framework; public class ParsedRoutingData { public final RoutePoint[] mPoints; - @Framework.RouterType - public final int mRouterType; + public final Router mRouterType; public ParsedRoutingData(RoutePoint[] points, int routerType) { this.mPoints = points; - this.mRouterType = routerType; + this.mRouterType = Router.valueOf(routerType); } } diff --git a/android/app/src/main/java/app/organicmaps/background/OsmUploadWork.java b/android/app/src/main/java/app/organicmaps/background/OsmUploadWork.java index 79744a356f..52bc6ad2d5 100644 --- a/android/app/src/main/java/app/organicmaps/background/OsmUploadWork.java +++ b/android/app/src/main/java/app/organicmaps/background/OsmUploadWork.java @@ -47,7 +47,7 @@ public class OsmUploadWork extends Worker public Result doWork() { final MwmApplication app = MwmApplication.from(mContext); - if (!app.arePlatformAndCoreInitialized()) + if (!app.getOrganicMaps().arePlatformAndCoreInitialized()) { Logger.w(TAG, "Application is not initialized, ignoring " + mWorkerParameters); return Result.failure(); diff --git a/android/app/src/main/java/app/organicmaps/base/BaseMwmFragmentActivity.java b/android/app/src/main/java/app/organicmaps/base/BaseMwmFragmentActivity.java index 16cc5397c1..d6dd2184c2 100644 --- a/android/app/src/main/java/app/organicmaps/base/BaseMwmFragmentActivity.java +++ b/android/app/src/main/java/app/organicmaps/base/BaseMwmFragmentActivity.java @@ -69,7 +69,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity setTheme(getThemeResourceId(mThemeName)); EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT)); RtlUtils.manageRtl(this); - if (!MwmApplication.from(this).arePlatformAndCoreInitialized()) + if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized()) { final Intent intent = Objects.requireNonNull(getIntent()); intent.setComponent(new ComponentName(this, SplashActivity.class)); diff --git a/android/app/src/main/java/app/organicmaps/bookmarks/data/Bookmark.java b/android/app/src/main/java/app/organicmaps/bookmarks/data/Bookmark.java index 151dd5a2ee..ddb4b22f81 100644 --- a/android/app/src/main/java/app/organicmaps/bookmarks/data/Bookmark.java +++ b/android/app/src/main/java/app/organicmaps/bookmarks/data/Bookmark.java @@ -10,7 +10,7 @@ import androidx.annotation.Nullable; import androidx.core.os.ParcelCompat; import app.organicmaps.Framework; -import app.organicmaps.routing.RoutePointInfo; +import app.organicmaps.sdk.routing.RoutePointInfo; import app.organicmaps.sdk.search.Popularity; import app.organicmaps.util.Constants; diff --git a/android/app/src/main/java/app/organicmaps/bookmarks/data/MapObject.java b/android/app/src/main/java/app/organicmaps/bookmarks/data/MapObject.java index 75b3d67aa9..f24e56047b 100644 --- a/android/app/src/main/java/app/organicmaps/bookmarks/data/MapObject.java +++ b/android/app/src/main/java/app/organicmaps/bookmarks/data/MapObject.java @@ -11,7 +11,7 @@ import androidx.annotation.Nullable; import androidx.core.os.ParcelCompat; import app.organicmaps.Framework; -import app.organicmaps.routing.RoutePointInfo; +import app.organicmaps.sdk.routing.RoutePointInfo; import app.organicmaps.sdk.search.Popularity; import app.organicmaps.util.Utils; import app.organicmaps.widget.placepage.PlacePageData; diff --git a/android/app/src/main/java/app/organicmaps/car/CarAppSession.java b/android/app/src/main/java/app/organicmaps/car/CarAppSession.java index 781a61b383..7a0f72a0a9 100644 --- a/android/app/src/main/java/app/organicmaps/car/CarAppSession.java +++ b/android/app/src/main/java/app/organicmaps/car/CarAppSession.java @@ -35,6 +35,7 @@ import app.organicmaps.display.DisplayManager; import app.organicmaps.display.DisplayType; import app.organicmaps.location.LocationState; import app.organicmaps.routing.RoutingController; +import app.organicmaps.sdk.PlacePageActivationListener; import app.organicmaps.util.Config; import app.organicmaps.util.LocationUtils; import app.organicmaps.util.log.Logger; @@ -45,7 +46,7 @@ import java.util.ArrayList; import java.util.List; public final class CarAppSession extends Session implements DefaultLifecycleObserver, - LocationState.ModeChangeListener, DisplayChangedListener, Framework.PlacePageActivationListener + LocationState.ModeChangeListener, DisplayChangedListener, PlacePageActivationListener { private static final String TAG = CarAppSession.class.getSimpleName(); @@ -163,7 +164,7 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse mInitFailed = false; try { - MwmApplication.from(getCarContext()).init(() -> { + MwmApplication.from(getCarContext()).initOrganicMaps(() -> { Config.setFirstStartDialogSeen(getCarContext()); if (DownloaderHelpers.isWorldMapsDownloadNeeded()) mScreenManager.push(new DownloadMapsScreenBuilder(getCarContext()).setDownloaderType(DownloadMapsScreenBuilder.DownloaderType.FirstLaunch).build()); diff --git a/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java b/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java index b365a4a520..b43b9fc865 100644 --- a/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java +++ b/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java @@ -30,10 +30,10 @@ import app.organicmaps.car.util.ThemeUtils; import app.organicmaps.car.util.UiHelpers; import app.organicmaps.location.LocationHelper; import app.organicmaps.location.LocationListener; -import app.organicmaps.routing.JunctionInfo; +import app.organicmaps.sdk.routing.JunctionInfo; import app.organicmaps.routing.NavigationService; import app.organicmaps.routing.RoutingController; -import app.organicmaps.routing.RoutingInfo; +import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.sound.TtsPlayer; import app.organicmaps.util.LocationUtils; import app.organicmaps.util.log.Logger; diff --git a/android/app/src/main/java/app/organicmaps/car/screens/PlaceScreen.java b/android/app/src/main/java/app/organicmaps/car/screens/PlaceScreen.java index a1223dcaa1..7f0312453a 100644 --- a/android/app/src/main/java/app/organicmaps/car/screens/PlaceScreen.java +++ b/android/app/src/main/java/app/organicmaps/car/screens/PlaceScreen.java @@ -41,14 +41,15 @@ import app.organicmaps.car.util.UiHelpers; import app.organicmaps.location.LocationHelper; import app.organicmaps.routing.ResultCodesHelper; import app.organicmaps.routing.RoutingController; -import app.organicmaps.routing.RoutingInfo; +import app.organicmaps.sdk.routing.RoutingInfo; +import app.organicmaps.sdk.Router; import app.organicmaps.util.Config; import java.util.Objects; public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.Callback, RoutingController.Container { - private static final int ROUTER_TYPE = Framework.ROUTER_TYPE_VEHICLE; + private static final Router ROUTER = Router.Vehicle; @Nullable private MapObject mMapObject; @@ -83,7 +84,7 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback. public void onCreate(@NonNull LifecycleOwner owner) { mRoutingController.restore(); - if (mRoutingController.isNavigating() && mRoutingController.getLastRouterType() == ROUTER_TYPE) + if (mRoutingController.isNavigating() && mRoutingController.getLastRouterType() == ROUTER) { showNavigation(true); return; @@ -95,11 +96,11 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback. else { final boolean hasIncorrectEndPoint = mRoutingController.isPlanning() && (!MapObject.same(mMapObject, mRoutingController.getEndPoint())); - final boolean hasIncorrectRouterType = mRoutingController.getLastRouterType() != ROUTER_TYPE; + final boolean hasIncorrectRouterType = mRoutingController.getLastRouterType() != ROUTER; final boolean isNotPlanningMode = !mRoutingController.isPlanning(); if (hasIncorrectRouterType) { - mRoutingController.setRouterType(ROUTER_TYPE); + mRoutingController.setRouterType(ROUTER); mRoutingController.rebuildLastRoute(); } else if (hasIncorrectEndPoint || isNotPlanningMode) diff --git a/android/app/src/main/java/app/organicmaps/car/screens/settings/DrivingOptionsScreen.java b/android/app/src/main/java/app/organicmaps/car/screens/settings/DrivingOptionsScreen.java index 9316ee5bb9..0143983da7 100644 --- a/android/app/src/main/java/app/organicmaps/car/screens/settings/DrivingOptionsScreen.java +++ b/android/app/src/main/java/app/organicmaps/car/screens/settings/DrivingOptionsScreen.java @@ -18,7 +18,7 @@ import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.util.Toggle; import app.organicmaps.car.util.UiHelpers; -import app.organicmaps.routing.RoutingOptions; +import app.organicmaps.sdk.routing.RoutingOptions; import app.organicmaps.settings.RoadType; import java.util.HashMap; diff --git a/android/app/src/main/java/app/organicmaps/car/util/RoutingHelpers.java b/android/app/src/main/java/app/organicmaps/car/util/RoutingHelpers.java index 23f41f1751..d6829617ca 100644 --- a/android/app/src/main/java/app/organicmaps/car/util/RoutingHelpers.java +++ b/android/app/src/main/java/app/organicmaps/car/util/RoutingHelpers.java @@ -8,8 +8,8 @@ import androidx.car.app.navigation.model.LaneDirection; import androidx.car.app.navigation.model.Maneuver; import androidx.core.graphics.drawable.IconCompat; -import app.organicmaps.routing.RoutingInfo; -import app.organicmaps.routing.SingleLaneInfo; +import app.organicmaps.sdk.routing.CarDirection; +import app.organicmaps.sdk.routing.LaneWay; public final class RoutingHelpers { @@ -30,7 +30,7 @@ public final class RoutingHelpers } @NonNull - public static LaneDirection createLaneDirection(@NonNull SingleLaneInfo.LaneWay laneWay, boolean isRecommended) + public static LaneDirection createLaneDirection(@NonNull LaneWay laneWay, boolean isRecommended) { int shape = LaneDirection.SHAPE_UNKNOWN; switch (laneWay) @@ -67,7 +67,7 @@ public final class RoutingHelpers } @NonNull - public static Maneuver createManeuver(@NonNull final CarContext context, @NonNull RoutingInfo.CarDirection carDirection, int roundaboutExitNum) + public static Maneuver createManeuver(@NonNull final CarContext context, @NonNull CarDirection carDirection, int roundaboutExitNum) { int maneuverType = switch (carDirection) { diff --git a/android/app/src/main/java/app/organicmaps/car/util/RoutingUtils.java b/android/app/src/main/java/app/organicmaps/car/util/RoutingUtils.java index 95a7379897..ff88b958e2 100644 --- a/android/app/src/main/java/app/organicmaps/car/util/RoutingUtils.java +++ b/android/app/src/main/java/app/organicmaps/car/util/RoutingUtils.java @@ -15,8 +15,9 @@ import androidx.car.app.navigation.model.Trip; import androidx.core.graphics.drawable.IconCompat; import app.organicmaps.bookmarks.data.MapObject; -import app.organicmaps.routing.RoutingInfo; -import app.organicmaps.routing.SingleLaneInfo; +import app.organicmaps.sdk.routing.LaneWay; +import app.organicmaps.sdk.routing.RoutingInfo; +import app.organicmaps.sdk.routing.SingleLaneInfo; import app.organicmaps.util.Graphics; import app.organicmaps.widget.LanesDrawable; @@ -71,7 +72,7 @@ public final class RoutingUtils for (final SingleLaneInfo laneInfo : info.lanes) { final Lane.Builder laneBuilder = new Lane.Builder(); - for (final SingleLaneInfo.LaneWay laneWay : laneInfo.mLane) + for (final LaneWay laneWay : laneInfo.mLane) laneBuilder.addDirection(RoutingHelpers.createLaneDirection(laneWay, laneInfo.mIsActive)); builder.addLane(laneBuilder.build()); } diff --git a/android/app/src/main/java/app/organicmaps/car/util/ThemeUtils.java b/android/app/src/main/java/app/organicmaps/car/util/ThemeUtils.java index cb6806cfd5..957c73cd51 100644 --- a/android/app/src/main/java/app/organicmaps/car/util/ThemeUtils.java +++ b/android/app/src/main/java/app/organicmaps/car/util/ThemeUtils.java @@ -12,6 +12,7 @@ import androidx.car.app.CarContext; import app.organicmaps.Framework; import app.organicmaps.R; import app.organicmaps.routing.RoutingController; +import app.organicmaps.sdk.MapStyle; public final class ThemeUtils { @@ -60,15 +61,14 @@ public final class ThemeUtils { final ThemeMode newThemeMode = oldThemeMode == ThemeMode.AUTO ? (context.isDarkMode() ? ThemeMode.NIGHT : ThemeMode.LIGHT) : oldThemeMode; - @Framework.MapStyle - int newMapStyle; + MapStyle newMapStyle; if (newThemeMode == ThemeMode.NIGHT) - newMapStyle = RoutingController.get().isVehicleNavigation() ? Framework.MAP_STYLE_VEHICLE_DARK : Framework.MAP_STYLE_DARK; + newMapStyle = RoutingController.get().isVehicleNavigation() ? MapStyle.VehicleDark : MapStyle.Dark; else - newMapStyle = RoutingController.get().isVehicleNavigation() ? Framework.MAP_STYLE_VEHICLE_CLEAR : Framework.MAP_STYLE_CLEAR; + newMapStyle = RoutingController.get().isVehicleNavigation() ? MapStyle.VehicleClear : MapStyle.Clear; - if (Framework.nativeGetMapStyle() != newMapStyle) - Framework.nativeSetMapStyle(newMapStyle); + if (MapStyle.get() != newMapStyle) + MapStyle.set(newMapStyle); } public static boolean isNightMode(@NonNull CarContext context) diff --git a/android/app/src/main/java/app/organicmaps/location/LocationHelper.java b/android/app/src/main/java/app/organicmaps/location/LocationHelper.java index 92ab5e13c1..9c0fbac835 100644 --- a/android/app/src/main/java/app/organicmaps/location/LocationHelper.java +++ b/android/app/src/main/java/app/organicmaps/location/LocationHelper.java @@ -25,7 +25,7 @@ import app.organicmaps.Map; import app.organicmaps.MwmApplication; import app.organicmaps.bookmarks.data.FeatureId; import app.organicmaps.bookmarks.data.MapObject; -import app.organicmaps.routing.JunctionInfo; +import app.organicmaps.sdk.routing.JunctionInfo; import app.organicmaps.routing.RoutingController; import app.organicmaps.util.Config; import app.organicmaps.util.LocationUtils; diff --git a/android/app/src/main/java/app/organicmaps/location/RouteSimulationProvider.java b/android/app/src/main/java/app/organicmaps/location/RouteSimulationProvider.java index c44e355e63..2c47224f5d 100644 --- a/android/app/src/main/java/app/organicmaps/location/RouteSimulationProvider.java +++ b/android/app/src/main/java/app/organicmaps/location/RouteSimulationProvider.java @@ -5,7 +5,7 @@ import android.location.Location; import androidx.annotation.NonNull; -import app.organicmaps.routing.JunctionInfo; +import app.organicmaps.sdk.routing.JunctionInfo; import app.organicmaps.util.LocationUtils; import app.organicmaps.util.concurrency.UiThread; import app.organicmaps.util.log.Logger; diff --git a/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java b/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java index a217f355d8..eced8098d0 100644 --- a/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java +++ b/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java @@ -135,7 +135,7 @@ public class TrackRecordingService extends Service implements LocationListener @Override public int onStartCommand(@NonNull Intent intent, int flags, int startId) { - if (!MwmApplication.from(this).arePlatformAndCoreInitialized()) + if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized()) { Logger.w(TAG, "Application is not initialized"); stopSelf(); diff --git a/android/app/src/main/java/app/organicmaps/routing/ManageRouteAdapter.java b/android/app/src/main/java/app/organicmaps/routing/ManageRouteAdapter.java index 4e6fa6c5a6..b874a22253 100644 --- a/android/app/src/main/java/app/organicmaps/routing/ManageRouteAdapter.java +++ b/android/app/src/main/java/app/organicmaps/routing/ManageRouteAdapter.java @@ -17,6 +17,9 @@ import androidx.recyclerview.widget.RecyclerView; import app.organicmaps.R; import app.organicmaps.bookmarks.data.MapObject; +import app.organicmaps.sdk.routing.RouteMarkData; +import app.organicmaps.sdk.routing.RouteMarkType; +import app.organicmaps.sdk.routing.RoutePointInfo; import app.organicmaps.util.StringUtils; import app.organicmaps.util.UiUtils; @@ -65,21 +68,21 @@ public class ManageRouteAdapter extends RecyclerView.Adapter= 2); // Set starting point. - mRoutePoints.get(0).mPointType = RoutePointInfo.ROUTE_MARK_START; + mRoutePoints.get(0).mPointType = RouteMarkType.Start; // Set finish point. - mRoutePoints.get(mRoutePoints.size() - 1).mPointType = RoutePointInfo.ROUTE_MARK_FINISH; + mRoutePoints.get(mRoutePoints.size() - 1).mPointType = RouteMarkType.Finish; // Set intermediate point(s). for (int pos = 1; pos < mRoutePoints.size() - 1; pos++) { - mRoutePoints.get(pos).mPointType = RoutePointInfo.ROUTE_MARK_INTERMEDIATE; + mRoutePoints.get(pos).mPointType = RouteMarkType.Intermediate; mRoutePoints.get(pos).mIntermediateIndex = pos - 1; } } diff --git a/android/app/src/main/java/app/organicmaps/routing/ManageRouteBottomSheet.java b/android/app/src/main/java/app/organicmaps/routing/ManageRouteBottomSheet.java index 0ca75f3c1d..2929e9f3cc 100644 --- a/android/app/src/main/java/app/organicmaps/routing/ManageRouteBottomSheet.java +++ b/android/app/src/main/java/app/organicmaps/routing/ManageRouteBottomSheet.java @@ -20,6 +20,7 @@ import app.organicmaps.Framework; import app.organicmaps.MwmApplication; import app.organicmaps.R; import app.organicmaps.bookmarks.data.MapObject; +import app.organicmaps.sdk.routing.RouteMarkData; import app.organicmaps.util.UiUtils; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; diff --git a/android/app/src/main/java/app/organicmaps/routing/NavigationController.java b/android/app/src/main/java/app/organicmaps/routing/NavigationController.java index fe78c86a10..2ab23e006e 100644 --- a/android/app/src/main/java/app/organicmaps/routing/NavigationController.java +++ b/android/app/src/main/java/app/organicmaps/routing/NavigationController.java @@ -18,6 +18,9 @@ import app.organicmaps.R; import app.organicmaps.location.LocationHelper; import app.organicmaps.maplayer.MapButtonsViewModel; import app.organicmaps.maplayer.traffic.TrafficManager; +import app.organicmaps.sdk.Router; +import app.organicmaps.sdk.routing.CarDirection; +import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.util.StringUtils; import app.organicmaps.util.UiUtils; import app.organicmaps.util.Utils; @@ -112,7 +115,7 @@ public class NavigationController implements TrafficManager.TrafficCallback, mNextTurnDistance.setText(Utils.formatDistance(mFrame.getContext(), info.distToTurn)); info.carDirection.setTurnDrawable(mNextTurnImage); - if (RoutingInfo.CarDirection.isRoundAbout(info.carDirection)) + if (CarDirection.isRoundAbout(info.carDirection)) UiUtils.setTextAndShow(mCircleExit, String.valueOf(info.exitNum)); else UiUtils.hide(mCircleExit); @@ -146,7 +149,7 @@ public class NavigationController implements TrafficManager.TrafficCallback, if (info == null) return; - if (Framework.nativeGetRouter() == Framework.ROUTER_TYPE_PEDESTRIAN) + if (Router.get() == Router.Pedestrian) updatePedestrian(info); else updateVehicle(info); diff --git a/android/app/src/main/java/app/organicmaps/routing/NavigationService.java b/android/app/src/main/java/app/organicmaps/routing/NavigationService.java index 8e492dbbde..1b74eb3a58 100644 --- a/android/app/src/main/java/app/organicmaps/routing/NavigationService.java +++ b/android/app/src/main/java/app/organicmaps/routing/NavigationService.java @@ -33,6 +33,7 @@ import app.organicmaps.Framework; import app.organicmaps.MwmActivity; import app.organicmaps.MwmApplication; import app.organicmaps.R; +import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.sound.MediaPlayerWrapper; import app.organicmaps.location.LocationHelper; import app.organicmaps.location.LocationListener; @@ -201,7 +202,7 @@ public class NavigationService extends Service implements LocationListener return START_NOT_STICKY; } - if (!MwmApplication.from(this).arePlatformAndCoreInitialized()) + if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized()) { // The system restarts the service if the app's process has crashed or been stopped. It would be nice to // automatically restore the last route and resume navigation. Unfortunately, the current implementation of diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuController.java b/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuController.java index e9745a52b5..b322ccbb60 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuController.java +++ b/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuController.java @@ -32,6 +32,12 @@ import app.organicmaps.Framework; import app.organicmaps.R; import app.organicmaps.bookmarks.data.DistanceAndAzimut; import app.organicmaps.location.LocationHelper; +import app.organicmaps.sdk.routing.RouteMarkData; +import app.organicmaps.sdk.routing.RouteMarkType; +import app.organicmaps.sdk.routing.RoutePointInfo; +import app.organicmaps.sdk.routing.RoutingInfo; +import app.organicmaps.sdk.routing.TransitRouteInfo; +import app.organicmaps.sdk.routing.TransitStepInfo; import app.organicmaps.util.Distance; import app.organicmaps.util.Graphics; import app.organicmaps.util.ThemeUtils; @@ -251,7 +257,7 @@ final class RoutingBottomMenuController implements View.OnClickListener UiUtils.hide(mError, mTransitFrame); UiUtils.show(mActionFrame); mActionMessage.setText(R.string.routing_add_start_point); - mActionMessage.setTag(RoutePointInfo.ROUTE_MARK_START); + mActionMessage.setTag(RouteMarkType.Start); if (LocationHelper.from(mContext).getMyPosition() != null) { UiUtils.show(mActionButton); @@ -271,7 +277,7 @@ final class RoutingBottomMenuController implements View.OnClickListener UiUtils.hide(mError, mTransitFrame); UiUtils.show(mActionFrame); mActionMessage.setText(R.string.routing_add_finish_point); - mActionMessage.setTag(RoutePointInfo.ROUTE_MARK_FINISH); + mActionMessage.setTag(RouteMarkType.Finish); UiUtils.hide(mActionButton); } @@ -483,8 +489,7 @@ final class RoutingBottomMenuController implements View.OnClickListener mListener.onUseMyPositionAsStart(); else if (id == R.id.btn__search_point && mListener != null) { - @RoutePointInfo.RouteMarkType - int pointType = (Integer) mActionMessage.getTag(); + final RouteMarkType pointType = (RouteMarkType) mActionMessage.getTag(); mListener.onSearchRoutePoint(pointType); } else if (id == R.id.btn__manage_route && mListener != null) diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuListener.java b/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuListener.java index 135f6b3213..cdbb78c686 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuListener.java +++ b/android/app/src/main/java/app/organicmaps/routing/RoutingBottomMenuListener.java @@ -1,9 +1,13 @@ package app.organicmaps.routing; +import androidx.annotation.NonNull; + +import app.organicmaps.sdk.routing.RouteMarkType; + public interface RoutingBottomMenuListener { void onUseMyPositionAsStart(); - void onSearchRoutePoint(@RoutePointInfo.RouteMarkType int type); + void onSearchRoutePoint(@NonNull RouteMarkType type); void onRoutingStart(); void onManageRouteOpen(); } diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingController.java b/android/app/src/main/java/app/organicmaps/routing/RoutingController.java index 1abbf6fc4c..79d937aded 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingController.java +++ b/android/app/src/main/java/app/organicmaps/routing/RoutingController.java @@ -16,6 +16,17 @@ import app.organicmaps.R; import app.organicmaps.bookmarks.data.FeatureId; import app.organicmaps.bookmarks.data.MapObject; import app.organicmaps.location.LocationHelper; +import app.organicmaps.sdk.Router; +import app.organicmaps.sdk.routing.RouteMarkData; +import app.organicmaps.sdk.routing.RouteMarkType; +import app.organicmaps.sdk.routing.RoutePointInfo; +import app.organicmaps.sdk.routing.RouteRecommendationType; +import app.organicmaps.sdk.routing.RoutingInfo; +import app.organicmaps.sdk.routing.RoutingListener; +import app.organicmaps.sdk.routing.RoutingLoadPointsListener; +import app.organicmaps.sdk.routing.RoutingOptions; +import app.organicmaps.sdk.routing.RoutingProgressListener; +import app.organicmaps.sdk.routing.TransitRouteInfo; import app.organicmaps.widget.placepage.CoordinatesFormat; import app.organicmaps.util.StringUtils; import app.organicmaps.util.Utils; @@ -67,11 +78,10 @@ public class RoutingController /** * @param progress progress to be displayed. * */ - default void updateBuildProgress(@IntRange(from = 0, to = 100) int progress, @Framework.RouterType int router) {} + default void updateBuildProgress(@IntRange(from = 0, to = 100) int progress, Router router) {} default void onStartRouteBuilding() {} } - private static final int NO_WAITING_POI_PICK = -1; private static final RoutingController sInstance = new RoutingController(); @Nullable @@ -79,11 +89,10 @@ public class RoutingController private BuildState mBuildState = BuildState.NONE; private State mState = State.NONE; - //@RoutePointInfo.RouteMarkType - private int mWaitingPoiPickType = NO_WAITING_POI_PICK; + @Nullable + private RouteMarkType mWaitingPoiPickType = null; private int mLastBuildProgress; - @Framework.RouterType - private int mLastRouterType; + private Router mLastRouterType; private boolean mHasContainerSavedState; private boolean mContainsCachedResult; @@ -98,7 +107,7 @@ public class RoutingController private int mRemovingIntermediatePointsTransactionId; @SuppressWarnings("FieldCanBeLocal") - private final Framework.RoutingListener mRoutingListener = new Framework.RoutingListener() + private final RoutingListener mRoutingListener = new RoutingListener() { @MainThread @Override @@ -124,10 +133,11 @@ public class RoutingController processRoutingEvent(); } }; + private void onBuiltRoute() { mCachedRoutingInfo = Framework.nativeGetRouteFollowingInfo(); - if (mLastRouterType == Framework.ROUTER_TYPE_TRANSIT) + if (mLastRouterType == Router.Transit) mCachedTransitRouteInfo = Framework.nativeGetTransitRouteInfo(); setBuildState(BuildState.BUILT); mLastBuildProgress = 100; @@ -135,23 +145,15 @@ public class RoutingController mContainer.onBuiltRoute(); } - private final Framework.RoutingProgressListener mRoutingProgressListener = new Framework.RoutingProgressListener() - { - @MainThread - @Override - public void onRouteBuildingProgress(float progress) - { - mLastBuildProgress = (int) progress; - updateProgress(); - } + private final RoutingProgressListener mRoutingProgressListener = progress -> { + mLastBuildProgress = (int) progress; + updateProgress(); }; - @SuppressWarnings("FieldCanBeLocal") - private final Framework.RoutingLoadPointsListener mRoutingLoadPointsListener = - success -> { - if (success) - prepare(getStartPoint(), getEndPoint()); - }; + private final RoutingLoadPointsListener mRoutingLoadPointsListener = success -> { + if (success) + prepare(getStartPoint(), getEndPoint()); + }; public static RoutingController get() { @@ -254,14 +256,14 @@ public class RoutingController public void initialize(@NonNull Context context) { - mLastRouterType = Framework.nativeGetLastUsedRouter(); + mLastRouterType = Router.getLastUsed(); mInvalidRoutePointsTransactionId = Framework.nativeInvalidRoutePointsTransactionId(); mRemovingIntermediatePointsTransactionId = mInvalidRoutePointsTransactionId; Framework.nativeSetRoutingListener(mRoutingListener); Framework.nativeSetRouteProgressListener(mRoutingProgressListener); Framework.nativeSetRoutingRecommendationListener(recommendation -> UiThread.run(() -> { - if (recommendation == Framework.ROUTE_REBUILD_AFTER_POINTS_LOADING) + if (recommendation == RouteRecommendationType.RebuildAfterPointsLoading) setStartPoint(LocationHelper.from(context).getMyPosition()); })); Framework.nativeSetRoutingLoadPointsListener(mRoutingLoadPointsListener); @@ -346,18 +348,18 @@ public class RoutingController private void initLastRouteType(@Nullable MapObject startPoint, @Nullable MapObject endPoint) { if (startPoint != null && endPoint != null) - mLastRouterType = Framework.nativeGetBestRouter(startPoint.getLat(), startPoint.getLon(), - endPoint.getLat(), endPoint.getLon()); + mLastRouterType = Router.getBest(startPoint.getLat(), startPoint.getLon(), + endPoint.getLat(), endPoint.getLon()); } public void prepare(final @Nullable MapObject startPoint, final @Nullable MapObject endPoint, - @Framework.RouterType int routerType) + Router routerType) { cancel(); setState(State.PREPARE); mLastRouterType = routerType; - Framework.nativeSetRouter(mLastRouterType); + Router.set(mLastRouterType); if (startPoint != null || endPoint != null) setPointsInternal(startPoint, endPoint); @@ -383,7 +385,7 @@ public class RoutingController public void addStop(@NonNull MapObject mapObject) { - addRoutePoint(RoutePointInfo.ROUTE_MARK_INTERMEDIATE, mapObject); + addRoutePoint(RouteMarkType.Intermediate, mapObject); build(); if (mContainer != null) mContainer.onAddedStop(); @@ -462,8 +464,7 @@ public class RoutingController { Logger.d(TAG, "cancelInternal"); - //noinspection WrongConstant - mWaitingPoiPickType = NO_WAITING_POI_PICK; + mWaitingPoiPickType = null; setBuildState(BuildState.NONE); setState(State.NONE); @@ -554,17 +555,17 @@ public class RoutingController public boolean isTransitType() { - return mLastRouterType == Framework.ROUTER_TYPE_TRANSIT; + return mLastRouterType == Router.Transit; } public boolean isVehicleRouterType() { - return mLastRouterType == Framework.ROUTER_TYPE_VEHICLE; + return mLastRouterType == Router.Vehicle; } boolean isRulerRouterType() { - return mLastRouterType == Framework.ROUTER_TYPE_RULER; + return mLastRouterType == Router.Ruler; } public boolean isNavigating() @@ -592,13 +593,13 @@ public class RoutingController return mBuildState == BuildState.BUILT; } - public void waitForPoiPick(@RoutePointInfo.RouteMarkType int pointType){ + public void waitForPoiPick(@NonNull RouteMarkType pointType){ mWaitingPoiPickType = pointType; } public boolean isWaitingPoiPick() { - return mWaitingPoiPickType != NO_WAITING_POI_PICK; + return mWaitingPoiPickType != null; } public BuildState getBuildState() @@ -609,17 +610,17 @@ public class RoutingController @Nullable public MapObject getStartPoint() { - return getStartOrEndPointByType(RoutePointInfo.ROUTE_MARK_START); + return getStartOrEndPointByType(RouteMarkType.Start); } @Nullable public MapObject getEndPoint() { - return getStartOrEndPointByType(RoutePointInfo.ROUTE_MARK_FINISH); + return getStartOrEndPointByType(RouteMarkType.Finish); } @Nullable - private MapObject getStartOrEndPointByType(@RoutePointInfo.RouteMarkType int type) + private MapObject getStartOrEndPointByType(@NonNull RouteMarkType type) { RouteMarkData[] points = Framework.nativeGetRoutePoints(); int size = points.length; @@ -633,9 +634,9 @@ public class RoutingController return point.mPointType == type ? toMapObject(point) : null; } - if (type == RoutePointInfo.ROUTE_MARK_START) + if (type == RouteMarkType.Start) return toMapObject(points[0]); - if (type == RoutePointInfo.ROUTE_MARK_FINISH) + if (type == RouteMarkType.Finish) return toMapObject(points[size - 1]); return null; @@ -663,10 +664,10 @@ public class RoutingController applyRemovingIntermediatePointsTransaction(); if (hasStart) - addRoutePoint(RoutePointInfo.ROUTE_MARK_START , startPoint); + addRoutePoint(RouteMarkType.Start, startPoint); if (hasEnd) - addRoutePoint(RoutePointInfo.ROUTE_MARK_FINISH , endPoint); + addRoutePoint(RouteMarkType.Finish, endPoint); if (hasOnePointAtLeast && mContainer != null) mContainer.updateMenu(); @@ -701,7 +702,7 @@ public class RoutingController if (point != null) { applyRemovingIntermediatePointsTransaction(); - addRoutePoint(RoutePointInfo.ROUTE_MARK_START, point); + addRoutePoint(RouteMarkType.Start, point); startPoint = getStartPoint(); } @@ -750,7 +751,7 @@ public class RoutingController { applyRemovingIntermediatePointsTransaction(); - addRoutePoint(RoutePointInfo.ROUTE_MARK_FINISH, point); + addRoutePoint(RouteMarkType.Finish, point); endPoint = getEndPoint(); } @@ -771,7 +772,7 @@ public class RoutingController return true; } - private static void addRoutePoint(@RoutePointInfo.RouteMarkType int type, @NonNull MapObject point) + private static void addRoutePoint(@NonNull RouteMarkType type, @NonNull MapObject point) { Pair description = getDescriptionForPoint(point); Framework.nativeAddRoutePoint(description.first /* title */, description.second /* subtitle */, @@ -823,7 +824,7 @@ public class RoutingController mContainer.updateMenu(); } - public void setRouterType(@Framework.RouterType int router) + public void setRouterType(Router router) { Logger.d(TAG, "setRouterType: " + mLastRouterType + " -> " + router); @@ -833,7 +834,7 @@ public class RoutingController return; mLastRouterType = router; - Framework.nativeSetRouter(router); + Router.set(router); cancelRemovingIntermediatePointsTransaction(); @@ -841,8 +842,7 @@ public class RoutingController build(); } - @Framework.RouterType - public int getLastRouterType() + public Router getLastRouterType() { return mLastRouterType; } @@ -870,15 +870,12 @@ public class RoutingController if (!isWaitingPoiPick()) return; - if (mWaitingPoiPickType != RoutePointInfo.ROUTE_MARK_FINISH - && mWaitingPoiPickType != RoutePointInfo.ROUTE_MARK_START) - { + if (mWaitingPoiPickType != RouteMarkType.Start && mWaitingPoiPickType != RouteMarkType.Finish) throw new AssertionError("Only start and finish points can be added through search!"); - } if (point != null) { - if (mWaitingPoiPickType == RoutePointInfo.ROUTE_MARK_FINISH) + if (mWaitingPoiPickType == RouteMarkType.Finish) setEndPoint(point); else setStartPoint(point); @@ -890,8 +887,7 @@ public class RoutingController showRoutePlan(); } - //noinspection WrongConstant - mWaitingPoiPickType = NO_WAITING_POI_PICK; + mWaitingPoiPickType = null; } public static CharSequence formatRoutingTime(Context context, int seconds, @DimenRes int unitsSize) { diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingInfo.java b/android/app/src/main/java/app/organicmaps/routing/RoutingInfo.java deleted file mode 100644 index 6b0a393783..0000000000 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingInfo.java +++ /dev/null @@ -1,175 +0,0 @@ -package app.organicmaps.routing; - -import android.widget.ImageView; - -import androidx.annotation.DrawableRes; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; - -import app.organicmaps.R; -import app.organicmaps.util.Distance; - -// Called from JNI. -@Keep -@SuppressWarnings("unused") -public class RoutingInfo -{ - // Target (end point of route). - public final Distance distToTarget; - // Next turn. - public final Distance distToTurn; - - public final int totalTimeInSeconds; - // Current street name. - public final String currentStreet; - // The next street name. - public final String nextStreet; - // The next next street name. - public final String nextNextStreet; - public final double completionPercent; - // For vehicle routing. - public final CarDirection carDirection; - public final CarDirection nextCarDirection; - public final int exitNum; - public final SingleLaneInfo[] lanes; - // For pedestrian routing. - public final PedestrianTurnDirection pedestrianTurnDirection; - // Current speed limit in meters per second. - // If no info about speed limit then speedLimitMps < 0. - public final double speedLimitMps; - private final boolean speedCamLimitExceeded; - private final boolean shouldPlayWarningSignal; - - /** - * IMPORTANT : Order of enum values MUST BE the same as native CarDirection enum. - */ - public enum CarDirection - { - NO_TURN(R.drawable.ic_turn_straight, 0), - GO_STRAIGHT(R.drawable.ic_turn_straight, 0), - - TURN_RIGHT(R.drawable.ic_turn_right, R.drawable.ic_then_right), - TURN_SHARP_RIGHT(R.drawable.ic_turn_right_sharp, R.drawable.ic_then_right_sharp), - TURN_SLIGHT_RIGHT(R.drawable.ic_turn_right_slight, R.drawable.ic_then_right_slight), - - TURN_LEFT(R.drawable.ic_turn_left, R.drawable.ic_then_left), - TURN_SHARP_LEFT(R.drawable.ic_turn_left_sharp, R.drawable.ic_then_left_sharp), - TURN_SLIGHT_LEFT(R.drawable.ic_turn_left_slight, R.drawable.ic_then_left_slight), - - U_TURN_LEFT(R.drawable.ic_turn_uleft, R.drawable.ic_then_uleft), - U_TURN_RIGHT(R.drawable.ic_turn_uright, R.drawable.ic_then_uright), - - ENTER_ROUND_ABOUT(R.drawable.ic_turn_round, R.drawable.ic_then_round), - LEAVE_ROUND_ABOUT(R.drawable.ic_turn_round, R.drawable.ic_then_round), - STAY_ON_ROUND_ABOUT(R.drawable.ic_turn_round, R.drawable.ic_then_round), - - START_AT_THE_END_OF_STREET(0, 0), - REACHED_YOUR_DESTINATION(R.drawable.ic_turn_finish, R.drawable.ic_then_finish), - - EXIT_HIGHWAY_TO_LEFT(R.drawable.ic_exit_highway_to_left, R.drawable.ic_then_exit_highway_to_left), - EXIT_HIGHWAY_TO_RIGHT(R.drawable.ic_exit_highway_to_right, R.drawable.ic_then_exit_highway_to_right); - - private final int mTurnRes; - private final int mNextTurnRes; - - CarDirection(@DrawableRes int mainResId, @DrawableRes int nextResId) - { - mTurnRes = mainResId; - mNextTurnRes = nextResId; - } - - public int getTurnRes() - { - return mTurnRes; - } - - public void setTurnDrawable(@NonNull ImageView imageView) - { - imageView.setImageResource(mTurnRes); - imageView.setRotation(0.0f); - } - - public void setNextTurnDrawable(@NonNull ImageView imageView) - { - imageView.setImageResource(mNextTurnRes); - } - - public boolean containsNextTurn() - { - return mNextTurnRes != 0; - } - - public static boolean isRoundAbout(CarDirection turn) - { - return turn == ENTER_ROUND_ABOUT || turn == LEAVE_ROUND_ABOUT || turn == STAY_ON_ROUND_ABOUT; - } - } - - enum PedestrianTurnDirection - { - NO_TURN(R.drawable.ic_turn_straight, 0), - GO_STRAIGHT(R.drawable.ic_turn_straight, 0), - - TURN_RIGHT(R.drawable.ic_turn_right, R.drawable.ic_then_right), - TURN_LEFT(R.drawable.ic_turn_left, R.drawable.ic_then_left), - - REACHED_YOUR_DESTINATION(R.drawable.ic_turn_finish, R.drawable.ic_then_finish); - - private final int mTurnRes; - private final int mNextTurnRes; - - PedestrianTurnDirection(@DrawableRes int mainResId, @DrawableRes int nextResId) - { - mTurnRes = mainResId; - mNextTurnRes = nextResId; - } - - public void setTurnDrawable(@NonNull ImageView imageView) - { - imageView.setImageResource(mTurnRes); - imageView.setRotation(0.0f); - } - - public void setNextTurnDrawable(@NonNull ImageView imageView) - { - imageView.setImageResource(mNextTurnRes); - } - - public boolean containsNextTurn() - { - return mNextTurnRes != 0; - } - } - - public RoutingInfo(Distance distToTarget, Distance distToTurn, String currentStreet, String nextStreet, String nextNextStreet, double completionPercent, - int vehicleTurnOrdinal, int vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum, - int totalTime, SingleLaneInfo[] lanes, double speedLimitMps, boolean speedLimitExceeded, - boolean shouldPlayWarningSignal) - { - this.distToTarget = distToTarget; - this.distToTurn = distToTurn; - this.currentStreet = currentStreet; - this.nextStreet = nextStreet; - this.nextNextStreet = nextNextStreet; - this.totalTimeInSeconds = totalTime; - this.completionPercent = completionPercent; - this.carDirection = CarDirection.values()[vehicleTurnOrdinal]; - this.nextCarDirection = CarDirection.values()[vehicleNextTurnOrdinal]; - this.lanes = lanes; - this.exitNum = exitNum; - this.pedestrianTurnDirection = PedestrianTurnDirection.values()[pedestrianTurnOrdinal]; - this.speedLimitMps = speedLimitMps; - this.speedCamLimitExceeded = speedLimitExceeded; - this.shouldPlayWarningSignal = shouldPlayWarningSignal; - } - - public boolean isSpeedCamLimitExceeded() - { - return speedCamLimitExceeded; - } - - public boolean shouldPlayWarningSignal() - { - return shouldPlayWarningSignal; - } -} diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingPlanController.java b/android/app/src/main/java/app/organicmaps/routing/RoutingPlanController.java index fe46c03661..de22cff865 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingPlanController.java +++ b/android/app/src/main/java/app/organicmaps/routing/RoutingPlanController.java @@ -18,6 +18,10 @@ import androidx.core.view.WindowInsetsCompat; import app.organicmaps.Framework; import app.organicmaps.MwmApplication; import app.organicmaps.R; +import app.organicmaps.sdk.Router; +import app.organicmaps.sdk.routing.RoutingInfo; +import app.organicmaps.sdk.routing.RoutingOptions; +import app.organicmaps.sdk.routing.TransitRouteInfo; import app.organicmaps.settings.DrivingOptionsActivity; import app.organicmaps.util.UiUtils; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; @@ -143,27 +147,27 @@ public class RoutingPlanController extends ToolbarController private void onTransitModeSelected(@NonNull View v) { - RoutingController.get().setRouterType(Framework.ROUTER_TYPE_TRANSIT); + RoutingController.get().setRouterType(Router.Transit); } private void onBicycleModeSelected(@NonNull View v) { - RoutingController.get().setRouterType(Framework.ROUTER_TYPE_BICYCLE); + RoutingController.get().setRouterType(Router.Bicycle); } private void onRulerModeSelected(@NonNull View v) { - RoutingController.get().setRouterType(Framework.ROUTER_TYPE_RULER); + RoutingController.get().setRouterType(Router.Ruler); } private void onPedestrianModeSelected(@NonNull View v) { - RoutingController.get().setRouterType(Framework.ROUTER_TYPE_PEDESTRIAN); + RoutingController.get().setRouterType(Router.Pedestrian); } private void onVehicleModeSelected(@NonNull View v) { - RoutingController.get().setRouterType(Framework.ROUTER_TYPE_VEHICLE); + RoutingController.get().setRouterType(Router.Vehicle); } @Override @@ -218,35 +222,35 @@ public class RoutingPlanController extends ToolbarController mRoutingBottomMenuController.showAltitudeChartAndRoutingDetails(); } - public void updateBuildProgress(int progress, @Framework.RouterType int router) + public void updateBuildProgress(int progress, @NonNull Router router) { UiUtils.invisible(mProgressVehicle, mProgressPedestrian, mProgressTransit, mProgressBicycle, mProgressRuler); WheelProgressView progressView; switch (router) { - case Framework.ROUTER_TYPE_VEHICLE: + case Vehicle: mRouterTypes.check(R.id.vehicle); progressView = mProgressVehicle; break; - case Framework.ROUTER_TYPE_PEDESTRIAN: + case Pedestrian: mRouterTypes.check(R.id.pedestrian); progressView = mProgressPedestrian; break; - //case Framework.ROUTER_TYPE_TAXI: + //case Taxi: // { // mRouterTypes.check(R.id.taxi); // progressView = mProgressTaxi; // } - case Framework.ROUTER_TYPE_TRANSIT: + case Transit: mRouterTypes.check(R.id.transit); progressView = mProgressTransit; break; - case Framework.ROUTER_TYPE_BICYCLE: + case Bicycle: mRouterTypes.check(R.id.bicycle); progressView = mProgressBicycle; break; - case Framework.ROUTER_TYPE_RULER: + case Ruler: mRouterTypes.check(R.id.ruler); progressView = mProgressRuler; break; diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingPlanFragment.java b/android/app/src/main/java/app/organicmaps/routing/RoutingPlanFragment.java index 4a54c0f3c1..0976a4bb0b 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingPlanFragment.java +++ b/android/app/src/main/java/app/organicmaps/routing/RoutingPlanFragment.java @@ -8,10 +8,10 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.organicmaps.Framework; import app.organicmaps.MwmActivity; import app.organicmaps.R; import app.organicmaps.base.BaseMwmFragment; +import app.organicmaps.sdk.Router; public class RoutingPlanFragment extends BaseMwmFragment { @@ -27,7 +27,7 @@ public class RoutingPlanFragment extends BaseMwmFragment return res; } - public void updateBuildProgress(int progress, @Framework.RouterType int router) + public void updateBuildProgress(int progress, Router router) { mPlanController.updateBuildProgress(progress, router); } diff --git a/android/app/src/main/java/app/organicmaps/routing/SingleLaneInfo.java b/android/app/src/main/java/app/organicmaps/routing/SingleLaneInfo.java deleted file mode 100644 index 96595ad21b..0000000000 --- a/android/app/src/main/java/app/organicmaps/routing/SingleLaneInfo.java +++ /dev/null @@ -1,62 +0,0 @@ -package app.organicmaps.routing; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; - -import app.organicmaps.R; - -public class SingleLaneInfo -{ - public LaneWay[] mLane; - public boolean mIsActive; - - /** - * IMPORTANT : Order of enum values MUST BE the same - * with native LaneWay enum (see routing/turns.hpp for details). - * Information for every lane is composed of some number values below. - * For example, a lane may have THROUGH and RIGHT values. - */ - public enum LaneWay - { - NONE(R.drawable.ic_turn_straight), - REVERSE(R.drawable.ic_turn_uleft), - SHARP_LEFT(R.drawable.ic_turn_left_sharp), - LEFT(R.drawable.ic_turn_left), - SLIGHT_LEFT(R.drawable.ic_turn_left_slight), - MERGE_TO_RIGHT(R.drawable.ic_turn_right_slight), - THROUGH(R.drawable.ic_turn_straight), - MERGE_TO_LEFT(R.drawable.ic_turn_left_slight), - SLIGHT_RIGHT(R.drawable.ic_turn_right_slight), - RIGHT(R.drawable.ic_turn_right), - SHARP_RIGHT(R.drawable.ic_turn_right_sharp); - - public final int mTurnRes; - - LaneWay(@DrawableRes int turnRes) - { - mTurnRes = turnRes; - } - } - - public SingleLaneInfo(@NonNull byte[] laneOrdinals, boolean isActive) - { - mLane = new LaneWay[laneOrdinals.length]; - final LaneWay[] values = LaneWay.values(); - for (int i = 0; i < mLane.length; i++) - mLane[i] = values[laneOrdinals[i]]; - - mIsActive = isActive; - } - - @NonNull - @Override - public String toString() - { - final int initialCapacity = 32; - StringBuilder sb = new StringBuilder(initialCapacity); - sb.append("Is the lane active? ").append(mIsActive).append(". The lane directions IDs are"); - for (LaneWay i : mLane) - sb.append(" ").append(i.ordinal()); - return sb.toString(); - } -} diff --git a/android/app/src/main/java/app/organicmaps/routing/TransitStepAdapter.java b/android/app/src/main/java/app/organicmaps/routing/TransitStepAdapter.java index c57d12f148..e5b032fd27 100644 --- a/android/app/src/main/java/app/organicmaps/routing/TransitStepAdapter.java +++ b/android/app/src/main/java/app/organicmaps/routing/TransitStepAdapter.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import app.organicmaps.R; +import app.organicmaps.sdk.routing.TransitStepInfo; import java.util.ArrayList; import java.util.List; diff --git a/android/app/src/main/java/app/organicmaps/routing/TransitStepView.java b/android/app/src/main/java/app/organicmaps/routing/TransitStepView.java index 9f4a965c10..9e43a17d19 100644 --- a/android/app/src/main/java/app/organicmaps/routing/TransitStepView.java +++ b/android/app/src/main/java/app/organicmaps/routing/TransitStepView.java @@ -20,6 +20,8 @@ import androidx.annotation.Nullable; import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.drawable.DrawableCompat; import app.organicmaps.R; +import app.organicmaps.sdk.routing.TransitStepInfo; +import app.organicmaps.sdk.routing.TransitStepType; import app.organicmaps.widget.recycler.MultilineLayoutManager; import app.organicmaps.util.ThemeUtils; diff --git a/android/app/src/main/java/app/organicmaps/sdk/ChoosePositionMode.java b/android/app/src/main/java/app/organicmaps/sdk/ChoosePositionMode.java new file mode 100644 index 0000000000..62aaa7da2e --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/ChoosePositionMode.java @@ -0,0 +1,37 @@ +package app.organicmaps.sdk; + +import androidx.annotation.NonNull; + +public enum ChoosePositionMode +{ + None(0), + Editor(1), + Api(2); + + ChoosePositionMode(int mode) + { + this.mode = mode; + } + + /** + * @param isBusiness selection area will be bounded by building borders, if its true (eg. true for businesses in buildings). + * @param applyPosition if true, map will be animated to currently selected object. + */ + public static void set(@NonNull ChoosePositionMode mode, boolean isBusiness, boolean applyPosition) + { + nativeSet(mode.mode, isBusiness, applyPosition); + } + + public static ChoosePositionMode get() + { + return ChoosePositionMode.values()[nativeGet()]; + } + + private final int mode; + + + private static native void nativeSet(int mode, boolean isBusiness, + boolean applyPosition); + + private static native int nativeGet(); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/MapStyle.java b/android/app/src/main/java/app/organicmaps/sdk/MapStyle.java new file mode 100644 index 0000000000..94e4fd4613 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/MapStyle.java @@ -0,0 +1,59 @@ +package app.organicmaps.sdk; + +import androidx.annotation.NonNull; + +public enum MapStyle +{ + Clear(0), + Dark(1), + VehicleClear(3), + VehicleDark(4), + OutdoorsClear(5), + OutdoorsDark(6); + + MapStyle(int value) + { + this.value = value; + } + + @NonNull + public static MapStyle get() + { + return valueOf(nativeGet()); + } + + public static void set(@NonNull MapStyle mapStyle) + { + nativeSet(mapStyle.value); + } + + /** + * This method allows to set new map style without immediate applying. It can be used before + * engine recreation instead of nativeSetMapStyle to avoid huge flow of OpenGL invocations. + * + * @param mapStyle style index + */ + public static void mark(@NonNull MapStyle mapStyle) + { + nativeMark(mapStyle.value); + } + + @NonNull + public static MapStyle valueOf(int value) + { + for (MapStyle mapStyle : MapStyle.values()) + { + if (mapStyle.value == value) + return mapStyle; + } + throw new IllegalArgumentException("Unknown map style value: " + value); + } + + private final int value; + + private static native void nativeSet(int mapStyle); + + private static native int nativeGet(); + + private static native void nativeMark(int mapStyle); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/OrganicMaps.java b/android/app/src/main/java/app/organicmaps/sdk/OrganicMaps.java new file mode 100644 index 0000000000..a4fdf61b2a --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/OrganicMaps.java @@ -0,0 +1,178 @@ +package app.organicmaps.sdk; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.lifecycle.DefaultLifecycleObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ProcessLifecycleOwner; + +import app.organicmaps.R; +import app.organicmaps.bookmarks.data.BookmarkManager; +import app.organicmaps.maplayer.isolines.IsolinesManager; +import app.organicmaps.maplayer.subway.SubwayManager; +import app.organicmaps.maplayer.traffic.TrafficManager; +import app.organicmaps.routing.RoutingController; +import app.organicmaps.sdk.search.SearchEngine; +import app.organicmaps.settings.StoragePathManager; +import app.organicmaps.sound.TtsPlayer; +import app.organicmaps.util.Config; +import app.organicmaps.util.SharedPropertiesUtils; +import app.organicmaps.util.StorageUtils; +import app.organicmaps.util.ThemeSwitcher; +import app.organicmaps.util.UiUtils; +import app.organicmaps.util.log.Logger; + +import java.io.IOException; + +public final class OrganicMaps implements DefaultLifecycleObserver +{ + private static final String TAG = OrganicMaps.class.getSimpleName(); + + @NonNull + private final Context mContext; + + private volatile boolean mFrameworkInitialized; + private volatile boolean mPlatformInitialized; + + public OrganicMaps(@NonNull Context context) + { + mContext = context.getApplicationContext(); + + // Set configuration directory as early as possible. + // Other methods may explicitly use Config, which requires settingsDir to be set. + final String settingsPath = StorageUtils.getSettingsPath(mContext); + if (!StorageUtils.createDirectory(settingsPath)) + throw new AssertionError("Can't create settingsDir " + settingsPath); + Logger.d(TAG, "Settings path = " + settingsPath); + nativeSetSettingsDir(settingsPath); + + Config.init(mContext); + } + + /** + * Initialize native core of application: platform and framework. + * + * @throws IOException - if failed to create directories. Caller must handle + * the exception and do nothing with native code if initialization is failed. + */ + public boolean init(@NonNull Runnable onComplete) throws IOException + { + initNativePlatform(); + return initNativeFramework(onComplete); + } + + public boolean arePlatformAndCoreInitialized() + { + return mFrameworkInitialized && mPlatformInitialized; + } + + @Override + public void onStart(@NonNull LifecycleOwner owner) + { + nativeOnTransit(true); + } + + @Override + public void onStop(@NonNull LifecycleOwner owner) + { + nativeOnTransit(false); + } + + private void initNativePlatform() throws IOException + { + if (mPlatformInitialized) + return; + + final String apkPath = StorageUtils.getApkPath(mContext); + Logger.d(TAG, "Apk path = " + apkPath); + // Note: StoragePathManager uses Config, which requires SettingsDir to be set. + final String writablePath = StoragePathManager.findMapsStorage(mContext); + Logger.d(TAG, "Writable path = " + writablePath); + final String privatePath = StorageUtils.getPrivatePath(mContext); + Logger.d(TAG, "Private path = " + privatePath); + final String tempPath = StorageUtils.getTempPath(mContext); + Logger.d(TAG, "Temp path = " + tempPath); + + // If platform directories are not created it means that native part of app will not be able + // to work at all. So, we just ignore native part initialization in this case, e.g. when the + // external storage is damaged or not available (read-only). + createPlatformDirectories(writablePath, privatePath, tempPath); + + nativeInitPlatform(mContext, + apkPath, + writablePath, + privatePath, + tempPath, + app.organicmaps.BuildConfig.FLAVOR, + app.organicmaps.BuildConfig.BUILD_TYPE, UiUtils.isTablet(mContext)); + Config.setStoragePath(writablePath); + Config.setStatisticsEnabled(SharedPropertiesUtils.isStatisticsEnabled(mContext)); + + mPlatformInitialized = true; + Logger.i(TAG, "Platform initialized"); + } + + private boolean initNativeFramework(@NonNull Runnable onComplete) + { + if (mFrameworkInitialized) + return false; + + nativeInitFramework(onComplete); + + initNativeStrings(); + ThemeSwitcher.INSTANCE.initialize(mContext); + SearchEngine.INSTANCE.initialize(); + BookmarkManager.loadBookmarks(); + TtsPlayer.INSTANCE.initialize(mContext); + ThemeSwitcher.INSTANCE.restart(false); + RoutingController.get().initialize(mContext); + TrafficManager.INSTANCE.initialize(); + SubwayManager.from(mContext).initialize(); + IsolinesManager.from(mContext).initialize(); + ProcessLifecycleOwner.get().getLifecycle().addObserver(this); + + Logger.i(TAG, "Framework initialized"); + mFrameworkInitialized = true; + return true; + } + + private void createPlatformDirectories(@NonNull String writablePath, + @NonNull String privatePath, + @NonNull String tempPath) throws IOException + { + SharedPropertiesUtils.emulateBadExternalStorage(mContext); + + StorageUtils.requireDirectory(writablePath); + StorageUtils.requireDirectory(privatePath); + StorageUtils.requireDirectory(tempPath); + } + + private void initNativeStrings() + { + nativeAddLocalization("core_entrance", mContext.getString(R.string.core_entrance)); + nativeAddLocalization("core_exit", mContext.getString(R.string.core_exit)); + nativeAddLocalization("core_my_places", mContext.getString(R.string.core_my_places)); + nativeAddLocalization("core_my_position", mContext.getString(R.string.core_my_position)); + nativeAddLocalization("core_placepage_unknown_place", mContext.getString(R.string.core_placepage_unknown_place)); + nativeAddLocalization("postal_code", mContext.getString(R.string.postal_code)); + nativeAddLocalization("wifi", mContext.getString(R.string.category_wifi)); + } + + private static native void nativeSetSettingsDir(String settingsPath); + + private static native void nativeInitPlatform(Context context, String apkPath, String writablePath, + String privatePath, String tmpPath, String flavorName, + String buildType, boolean isTablet); + + private static native void nativeInitFramework(@NonNull Runnable onComplete); + + private static native void nativeAddLocalization(String name, String value); + + private static native void nativeOnTransit(boolean foreground); + + static + { + System.loadLibrary("organicmaps"); + } +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/PlacePageActivationListener.java b/android/app/src/main/java/app/organicmaps/sdk/PlacePageActivationListener.java new file mode 100644 index 0000000000..0d7779d184 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/PlacePageActivationListener.java @@ -0,0 +1,24 @@ +package app.organicmaps.sdk; + +import androidx.annotation.Keep; +import androidx.annotation.NonNull; + +import app.organicmaps.widget.placepage.PlacePageData; + +public interface PlacePageActivationListener +{ + // Called from JNI. + @Keep + @SuppressWarnings("unused") + void onPlacePageActivated(@NonNull PlacePageData data); + + // Called from JNI + @Keep + @SuppressWarnings("unused") + void onPlacePageDeactivated(); + + // Called from JNI + @Keep + @SuppressWarnings("unused") + void onSwitchFullScreenMode(); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/Router.java b/android/app/src/main/java/app/organicmaps/sdk/Router.java new file mode 100644 index 0000000000..dcaf1d44fa --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/Router.java @@ -0,0 +1,53 @@ +package app.organicmaps.sdk; + +import androidx.annotation.NonNull; + +public enum Router +{ + Vehicle(0), + Pedestrian(1), + Bicycle(2), + Transit(3), + Ruler(4); + + Router(int type) + { + this.type = type; + } + + public static void set(@NonNull Router routerType) + { + nativeSet(routerType.type); + } + + public static Router get() + { + return valueOf(nativeGet()); + } + + public static Router getLastUsed() + { + return valueOf(nativeGetLastUsed()); + } + + public static Router getBest(double srcLat, double srcLon, double dstLat, double dstLon) + { + return Router.values()[nativeGetBest(srcLat, srcLon, dstLat, dstLon)]; + } + + public static Router valueOf(int type) + { + return Router.values()[type]; + } + + private final int type; + + private static native void nativeSet(int routerType); + + private static native int nativeGet(); + + private static native int nativeGetLastUsed(); + + private static native int nativeGetBest(double srcLat, double srcLon, + double dstLat, double dstLon); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/CarDirection.java b/android/app/src/main/java/app/organicmaps/sdk/routing/CarDirection.java new file mode 100644 index 0000000000..50b4f226a0 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/CarDirection.java @@ -0,0 +1,73 @@ +package app.organicmaps.sdk.routing; + +import android.widget.ImageView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; + +import app.organicmaps.R; + +/** + * IMPORTANT : Order of enum values MUST BE the same as native CarDirection enum. + */ +public enum CarDirection +{ + NO_TURN(R.drawable.ic_turn_straight, 0), + GO_STRAIGHT(R.drawable.ic_turn_straight, 0), + + TURN_RIGHT(R.drawable.ic_turn_right, R.drawable.ic_then_right), + TURN_SHARP_RIGHT(R.drawable.ic_turn_right_sharp, R.drawable.ic_then_right_sharp), + TURN_SLIGHT_RIGHT(R.drawable.ic_turn_right_slight, R.drawable.ic_then_right_slight), + + TURN_LEFT(R.drawable.ic_turn_left, R.drawable.ic_then_left), + TURN_SHARP_LEFT(R.drawable.ic_turn_left_sharp, R.drawable.ic_then_left_sharp), + TURN_SLIGHT_LEFT(R.drawable.ic_turn_left_slight, R.drawable.ic_then_left_slight), + + U_TURN_LEFT(R.drawable.ic_turn_uleft, R.drawable.ic_then_uleft), + U_TURN_RIGHT(R.drawable.ic_turn_uright, R.drawable.ic_then_uright), + + ENTER_ROUND_ABOUT(R.drawable.ic_turn_round, R.drawable.ic_then_round), + LEAVE_ROUND_ABOUT(R.drawable.ic_turn_round, R.drawable.ic_then_round), + STAY_ON_ROUND_ABOUT(R.drawable.ic_turn_round, R.drawable.ic_then_round), + + START_AT_THE_END_OF_STREET(0, 0), + REACHED_YOUR_DESTINATION(R.drawable.ic_turn_finish, R.drawable.ic_then_finish), + + EXIT_HIGHWAY_TO_LEFT(R.drawable.ic_exit_highway_to_left, R.drawable.ic_then_exit_highway_to_left), + EXIT_HIGHWAY_TO_RIGHT(R.drawable.ic_exit_highway_to_right, R.drawable.ic_then_exit_highway_to_right); + + private final int mTurnRes; + private final int mNextTurnRes; + + CarDirection(@DrawableRes int mainResId, @DrawableRes int nextResId) + { + mTurnRes = mainResId; + mNextTurnRes = nextResId; + } + + public int getTurnRes() + { + return mTurnRes; + } + + public void setTurnDrawable(@NonNull ImageView imageView) + { + imageView.setImageResource(mTurnRes); + imageView.setRotation(0.0f); + } + + public void setNextTurnDrawable(@NonNull ImageView imageView) + { + imageView.setImageResource(mNextTurnRes); + } + + public boolean containsNextTurn() + { + return mNextTurnRes != 0; + } + + public static boolean isRoundAbout(CarDirection turn) + { + return turn == ENTER_ROUND_ABOUT || turn == LEAVE_ROUND_ABOUT || turn == STAY_ON_ROUND_ABOUT; + } +} diff --git a/android/app/src/main/java/app/organicmaps/routing/JunctionInfo.java b/android/app/src/main/java/app/organicmaps/sdk/routing/JunctionInfo.java similarity index 61% rename from android/app/src/main/java/app/organicmaps/routing/JunctionInfo.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/JunctionInfo.java index c4eeb3b520..376a5e1532 100644 --- a/android/app/src/main/java/app/organicmaps/routing/JunctionInfo.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/JunctionInfo.java @@ -1,16 +1,16 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; import androidx.annotation.Keep; // Used by JNI. @Keep @SuppressWarnings("unused") -public class JunctionInfo +public final class JunctionInfo { public final double mLat; public final double mLon; - public JunctionInfo(double lat, double lon) + private JunctionInfo(double lat, double lon) { mLat = lat; mLon = lon; diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/LaneWay.java b/android/app/src/main/java/app/organicmaps/sdk/routing/LaneWay.java new file mode 100644 index 0000000000..1758bd831d --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/LaneWay.java @@ -0,0 +1,33 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.DrawableRes; + +import app.organicmaps.R; + +/** + * IMPORTANT : Order of enum values MUST BE the same + * with native LaneWay enum (see routing/turns.hpp for details). + * Information for every lane is composed of some number values below. + * For example, a lane may have THROUGH and RIGHT values. + */ +public enum LaneWay +{ + NONE(R.drawable.ic_turn_straight), + REVERSE(R.drawable.ic_turn_uleft), + SHARP_LEFT(R.drawable.ic_turn_left_sharp), + LEFT(R.drawable.ic_turn_left), + SLIGHT_LEFT(R.drawable.ic_turn_left_slight), + MERGE_TO_RIGHT(R.drawable.ic_turn_right_slight), + THROUGH(R.drawable.ic_turn_straight), + MERGE_TO_LEFT(R.drawable.ic_turn_left_slight), + SLIGHT_RIGHT(R.drawable.ic_turn_right_slight), + RIGHT(R.drawable.ic_turn_right), + SHARP_RIGHT(R.drawable.ic_turn_right_sharp); + + public final int mTurnRes; + + LaneWay(@DrawableRes int turnRes) + { + mTurnRes = turnRes; + } +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/PedestrianTurnDirection.java b/android/app/src/main/java/app/organicmaps/sdk/routing/PedestrianTurnDirection.java new file mode 100644 index 0000000000..1f64cd4403 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/PedestrianTurnDirection.java @@ -0,0 +1,44 @@ +package app.organicmaps.sdk.routing; + +import android.widget.ImageView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; + +import app.organicmaps.R; + +public enum PedestrianTurnDirection +{ + NO_TURN(R.drawable.ic_turn_straight, 0), + GO_STRAIGHT(R.drawable.ic_turn_straight, 0), + + TURN_RIGHT(R.drawable.ic_turn_right, R.drawable.ic_then_right), + TURN_LEFT(R.drawable.ic_turn_left, R.drawable.ic_then_left), + + REACHED_YOUR_DESTINATION(R.drawable.ic_turn_finish, R.drawable.ic_then_finish); + + private final int mTurnRes; + private final int mNextTurnRes; + + PedestrianTurnDirection(@DrawableRes int mainResId, @DrawableRes int nextResId) + { + mTurnRes = mainResId; + mNextTurnRes = nextResId; + } + + public void setTurnDrawable(@NonNull ImageView imageView) + { + imageView.setImageResource(mTurnRes); + imageView.setRotation(0.0f); + } + + public void setNextTurnDrawable(@NonNull ImageView imageView) + { + imageView.setImageResource(mNextTurnRes); + } + + public boolean containsNextTurn() + { + return mNextTurnRes != 0; + } +} diff --git a/android/app/src/main/java/app/organicmaps/routing/RouteMarkData.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RouteMarkData.java similarity index 61% rename from android/app/src/main/java/app/organicmaps/routing/RouteMarkData.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/RouteMarkData.java index 33b1300e04..e9ebb3cb39 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RouteMarkData.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RouteMarkData.java @@ -1,4 +1,4 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; import androidx.annotation.Keep; import androidx.annotation.Nullable; @@ -9,14 +9,13 @@ import androidx.annotation.Nullable; // Called from JNI. @Keep @SuppressWarnings("unused") -public class RouteMarkData +public final class RouteMarkData { @Nullable public final String mTitle; @Nullable public final String mSubtitle; - @RoutePointInfo.RouteMarkType - public int mPointType; + public RouteMarkType mPointType; public int mIntermediateIndex; public final boolean mIsVisible; public final boolean mIsMyPosition; @@ -24,10 +23,16 @@ public class RouteMarkData public final double mLat; public final double mLon; + private RouteMarkData(@Nullable String title, @Nullable String subtitle, + int pointType, int intermediateIndex, boolean isVisible, + boolean isMyPosition, boolean isPassed, double lat, double lon) + { + this(title, subtitle, RouteMarkType.values()[pointType], intermediateIndex, isVisible, isMyPosition, isPassed, lat, lon); + } + public RouteMarkData(@Nullable String title, @Nullable String subtitle, - @RoutePointInfo.RouteMarkType int pointType, - int intermediateIndex, boolean isVisible, boolean isMyPosition, - boolean isPassed, double lat, double lon) + RouteMarkType pointType, int intermediateIndex, boolean isVisible, + boolean isMyPosition, boolean isPassed, double lat, double lon) { mTitle = title; mSubtitle = subtitle; diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RouteMarkType.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RouteMarkType.java new file mode 100644 index 0000000000..9fdc5be6d5 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RouteMarkType.java @@ -0,0 +1,8 @@ +package app.organicmaps.sdk.routing; + +public enum RouteMarkType +{ + Start, + Intermediate, + Finish +} diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutePointInfo.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutePointInfo.java similarity index 50% rename from android/app/src/main/java/app/organicmaps/routing/RoutePointInfo.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/RoutePointInfo.java index e04b0da5cc..184bdfb545 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutePointInfo.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutePointInfo.java @@ -1,18 +1,15 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.IntDef; import androidx.annotation.Keep; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import androidx.annotation.NonNull; // Called from JNI. @Keep @SuppressWarnings("unused") -public class RoutePointInfo implements Parcelable +public final class RoutePointInfo implements Parcelable { public static final Creator CREATOR = new Creator<>() { @@ -29,44 +26,35 @@ public class RoutePointInfo implements Parcelable } }; - public static final int ROUTE_MARK_START = 0; - public static final int ROUTE_MARK_INTERMEDIATE = 1; - public static final int ROUTE_MARK_FINISH = 2; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ ROUTE_MARK_START, ROUTE_MARK_INTERMEDIATE, ROUTE_MARK_FINISH }) - public @interface RouteMarkType {} - - @RouteMarkType - public final int mMarkType; + public final RouteMarkType mMarkType; public final int mIntermediateIndex; - public RoutePointInfo(@RouteMarkType int markType, int intermediateIndex) + private RoutePointInfo(@NonNull RouteMarkType markType, int intermediateIndex) { mMarkType = markType; mIntermediateIndex = intermediateIndex; } - private RoutePointInfo(Parcel in) + private RoutePointInfo(@NonNull Parcel in) { //noinspection WrongConstant - this(in.readInt() /* mMarkType */, in.readInt() /* mIntermediateIndex */); + this(RouteMarkType.values()[in.readInt()] /* mMarkType */, in.readInt() /* mIntermediateIndex */); } boolean isIntermediatePoint() { - return mMarkType == ROUTE_MARK_INTERMEDIATE; + return mMarkType == RouteMarkType.Intermediate; } boolean isFinishPoint() { - return mMarkType == ROUTE_MARK_FINISH; + return mMarkType == RouteMarkType.Finish; } boolean isStartPoint() { - return mMarkType == ROUTE_MARK_START; + return mMarkType == RouteMarkType.Start; } @Override @@ -78,7 +66,7 @@ public class RoutePointInfo implements Parcelable @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mMarkType); + dest.writeInt(mMarkType.ordinal()); dest.writeInt(mIntermediateIndex); } } diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RouteRecommendationType.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RouteRecommendationType.java new file mode 100644 index 0000000000..11d440f5ce --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RouteRecommendationType.java @@ -0,0 +1,6 @@ +package app.organicmaps.sdk.routing; + +public enum RouteRecommendationType +{ + RebuildAfterPointsLoading +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingInfo.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingInfo.java new file mode 100644 index 0000000000..842c1c4215 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingInfo.java @@ -0,0 +1,69 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.Keep; + +import app.organicmaps.util.Distance; + +// Called from JNI. +@Keep +@SuppressWarnings("unused") +public final class RoutingInfo +{ + // Target (end point of route). + public final Distance distToTarget; + // Next turn. + public final Distance distToTurn; + + public final int totalTimeInSeconds; + // Current street name. + public final String currentStreet; + // The next street name. + public final String nextStreet; + // The next next street name. + public final String nextNextStreet; + public final double completionPercent; + // For vehicle routing. + public final CarDirection carDirection; + public final CarDirection nextCarDirection; + public final int exitNum; + public final SingleLaneInfo[] lanes; + // For pedestrian routing. + public final PedestrianTurnDirection pedestrianTurnDirection; + // Current speed limit in meters per second. + // If no info about speed limit then speedLimitMps < 0. + public final double speedLimitMps; + private final boolean speedCamLimitExceeded; + private final boolean shouldPlayWarningSignal; + + private RoutingInfo(Distance distToTarget, Distance distToTurn, String currentStreet, String nextStreet, String nextNextStreet, double completionPercent, + int vehicleTurnOrdinal, int vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum, + int totalTime, SingleLaneInfo[] lanes, double speedLimitMps, boolean speedLimitExceeded, + boolean shouldPlayWarningSignal) + { + this.distToTarget = distToTarget; + this.distToTurn = distToTurn; + this.currentStreet = currentStreet; + this.nextStreet = nextStreet; + this.nextNextStreet = nextNextStreet; + this.totalTimeInSeconds = totalTime; + this.completionPercent = completionPercent; + this.carDirection = CarDirection.values()[vehicleTurnOrdinal]; + this.nextCarDirection = CarDirection.values()[vehicleNextTurnOrdinal]; + this.lanes = lanes; + this.exitNum = exitNum; + this.pedestrianTurnDirection = PedestrianTurnDirection.values()[pedestrianTurnOrdinal]; + this.speedLimitMps = speedLimitMps; + this.speedCamLimitExceeded = speedLimitExceeded; + this.shouldPlayWarningSignal = shouldPlayWarningSignal; + } + + public boolean isSpeedCamLimitExceeded() + { + return speedCamLimitExceeded; + } + + public boolean shouldPlayWarningSignal() + { + return shouldPlayWarningSignal; + } +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingListener.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingListener.java new file mode 100644 index 0000000000..0470ed83d4 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingListener.java @@ -0,0 +1,13 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.Keep; +import androidx.annotation.MainThread; + +public interface RoutingListener +{ + // Called from JNI + @Keep + @SuppressWarnings("unused") + @MainThread + void onRoutingEvent(int resultCode, String[] missingMaps); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingLoadPointsListener.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingLoadPointsListener.java new file mode 100644 index 0000000000..ccf075df7b --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingLoadPointsListener.java @@ -0,0 +1,11 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.Keep; + +public interface RoutingLoadPointsListener +{ + // Called from JNI. + @Keep + @SuppressWarnings("unused") + void onRoutePointsLoaded(boolean success); +} diff --git a/android/app/src/main/java/app/organicmaps/routing/RoutingOptions.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingOptions.java similarity index 81% rename from android/app/src/main/java/app/organicmaps/routing/RoutingOptions.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/RoutingOptions.java index 67cd892308..57d58a97b0 100644 --- a/android/app/src/main/java/app/organicmaps/routing/RoutingOptions.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingOptions.java @@ -1,4 +1,4 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; import androidx.annotation.NonNull; @@ -7,7 +7,7 @@ import app.organicmaps.settings.RoadType; import java.util.HashSet; import java.util.Set; -public class RoutingOptions +public final class RoutingOptions { public static void addOption(@NonNull RoadType roadType) { @@ -24,10 +24,6 @@ public class RoutingOptions return nativeHasOption(roadType.ordinal()); } - private static native void nativeAddOption(int option); - private static native void nativeRemoveOption(int option); - private static native boolean nativeHasOption(int option); - public static boolean hasAnyOptions() { for (RoadType each : RoadType.values()) @@ -49,4 +45,14 @@ public class RoutingOptions } return roadTypes; } + + private RoutingOptions() throws IllegalAccessException + { + throw new IllegalAccessException("RoutingOptions is a utility class and should not be instantiated"); + } + private static native void nativeAddOption(int option); + + private static native void nativeRemoveOption(int option); + + private static native boolean nativeHasOption(int option); } diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingProgressListener.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingProgressListener.java new file mode 100644 index 0000000000..7e03b7d33f --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingProgressListener.java @@ -0,0 +1,13 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.Keep; +import androidx.annotation.MainThread; + +public interface RoutingProgressListener +{ + // Called from JNI. + @Keep + @SuppressWarnings("unused") + @MainThread + void onRouteBuildingProgress(float progress); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingRecommendationListener.java b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingRecommendationListener.java new file mode 100644 index 0000000000..352b9ba7f6 --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/RoutingRecommendationListener.java @@ -0,0 +1,11 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.Keep; + +public interface RoutingRecommendationListener +{ + // Called from JNI. + @Keep + @SuppressWarnings("unused") + void onRecommend(RouteRecommendationType recommendation); +} diff --git a/android/app/src/main/java/app/organicmaps/sdk/routing/SingleLaneInfo.java b/android/app/src/main/java/app/organicmaps/sdk/routing/SingleLaneInfo.java new file mode 100644 index 0000000000..ef53087f5d --- /dev/null +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/SingleLaneInfo.java @@ -0,0 +1,31 @@ +package app.organicmaps.sdk.routing; + +import androidx.annotation.NonNull; + +public final class SingleLaneInfo +{ + public LaneWay[] mLane; + public boolean mIsActive; + + public SingleLaneInfo(@NonNull byte[] laneOrdinals, boolean isActive) + { + mLane = new LaneWay[laneOrdinals.length]; + final LaneWay[] values = LaneWay.values(); + for (int i = 0; i < mLane.length; i++) + mLane[i] = values[laneOrdinals[i]]; + + mIsActive = isActive; + } + + @NonNull + @Override + public String toString() + { + final int initialCapacity = 32; + StringBuilder sb = new StringBuilder(initialCapacity); + sb.append("Is the lane active? ").append(mIsActive).append(". The lane directions IDs are"); + for (LaneWay i : mLane) + sb.append(" ").append(i.ordinal()); + return sb.toString(); + } +} diff --git a/android/app/src/main/java/app/organicmaps/routing/TransitRouteInfo.java b/android/app/src/main/java/app/organicmaps/sdk/routing/TransitRouteInfo.java similarity index 77% rename from android/app/src/main/java/app/organicmaps/routing/TransitRouteInfo.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/TransitRouteInfo.java index 949f95720e..12174518f4 100644 --- a/android/app/src/main/java/app/organicmaps/routing/TransitRouteInfo.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/TransitRouteInfo.java @@ -1,4 +1,4 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; import androidx.annotation.Keep; import androidx.annotation.NonNull; @@ -13,7 +13,7 @@ import java.util.List; // Used by JNI. @Keep @SuppressWarnings("unused") -public class TransitRouteInfo +public final class TransitRouteInfo { @NonNull private final String mTotalDistance; @@ -28,7 +28,7 @@ public class TransitRouteInfo @NonNull private final TransitStepInfo[] mSteps; - public TransitRouteInfo(@NonNull String totalDistance, @NonNull String totalDistanceUnits, int totalTimeInSec, + private TransitRouteInfo(@NonNull String totalDistance, @NonNull String totalDistanceUnits, int totalTimeInSec, @NonNull String totalPedestrianDistance, @NonNull String totalPedestrianDistanceUnits, int totalPedestrianTimeInSec, @NonNull TransitStepInfo[] steps) { @@ -42,29 +42,29 @@ public class TransitRouteInfo } @NonNull - String getTotalPedestrianDistance() + public String getTotalPedestrianDistance() { return mTotalPedestrianDistance; } - int getTotalPedestrianTimeInSec() + public int getTotalPedestrianTimeInSec() { return mTotalPedestrianTimeInSec; } @NonNull - String getTotalPedestrianDistanceUnits() + public String getTotalPedestrianDistanceUnits() { return mTotalPedestrianDistanceUnits; } - int getTotalTime() + public int getTotalTime() { return mTotalTimeInSec; } @NonNull - List getTransitSteps() + public List getTransitSteps() { return new ArrayList<>(Arrays.asList(mSteps)); } diff --git a/android/app/src/main/java/app/organicmaps/routing/TransitStepInfo.java b/android/app/src/main/java/app/organicmaps/sdk/routing/TransitStepInfo.java similarity index 53% rename from android/app/src/main/java/app/organicmaps/routing/TransitStepInfo.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/TransitStepInfo.java index 905ccdfd60..38f1746547 100644 --- a/android/app/src/main/java/app/organicmaps/routing/TransitStepInfo.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/TransitStepInfo.java @@ -1,34 +1,17 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; -import androidx.annotation.IntDef; import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** * Represents TransitStepInfo from core. */ // Used by JNI. @Keep @SuppressWarnings("unused") -public class TransitStepInfo +public final class TransitStepInfo { - private static final int TRANSIT_TYPE_INTERMEDIATE_POINT = 0; - private static final int TRANSIT_TYPE_PEDESTRIAN = 1; - private static final int TRANSIT_TYPE_SUBWAY = 2; - private static final int TRANSIT_TYPE_TRAIN = 3; - private static final int TRANSIT_TYPE_LIGHT_RAIL = 4; - private static final int TRANSIT_TYPE_MONORAIL = 5; - private static final int TRANSIT_TYPE_RULER = 6; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ TRANSIT_TYPE_INTERMEDIATE_POINT, TRANSIT_TYPE_PEDESTRIAN, TRANSIT_TYPE_SUBWAY, - TRANSIT_TYPE_TRAIN, TRANSIT_TYPE_LIGHT_RAIL, TRANSIT_TYPE_MONORAIL, TRANSIT_TYPE_RULER}) - @interface TransitType {} - @NonNull private final TransitStepType mType; @Nullable @@ -41,8 +24,8 @@ public class TransitStepInfo private final int mColor; private final int mIntermediateIndex; - TransitStepInfo(@TransitType int type, @Nullable String distance, @Nullable String distanceUnits, - int timeInSec, @Nullable String number, int color, int intermediateIndex) + private TransitStepInfo(int type, @Nullable String distance, @Nullable String distanceUnits, + int timeInSec, @Nullable String number, int color, int intermediateIndex) { mType = TransitStepType.values()[type]; mDistance = distance; @@ -56,13 +39,13 @@ public class TransitStepInfo @NonNull public static TransitStepInfo intermediatePoint(int intermediateIndex) { - return new TransitStepInfo(TRANSIT_TYPE_INTERMEDIATE_POINT, null, null, 0, null, 0, intermediateIndex); + return new TransitStepInfo(TransitStepType.INTERMEDIATE_POINT.ordinal(), null, null, 0, null, 0, intermediateIndex); } @NonNull public static TransitStepInfo ruler(@NonNull String distance, @NonNull String distanceUnits) { - return new TransitStepInfo(TRANSIT_TYPE_RULER, distance, distanceUnits, 0, null, 0, -1); + return new TransitStepInfo(TransitStepType.RULER.ordinal(), distance, distanceUnits, 0, null, 0, -1); } @NonNull diff --git a/android/app/src/main/java/app/organicmaps/routing/TransitStepType.java b/android/app/src/main/java/app/organicmaps/sdk/routing/TransitStepType.java similarity index 95% rename from android/app/src/main/java/app/organicmaps/routing/TransitStepType.java rename to android/app/src/main/java/app/organicmaps/sdk/routing/TransitStepType.java index bf1ffd9a6d..5d6cdc9b5f 100644 --- a/android/app/src/main/java/app/organicmaps/routing/TransitStepType.java +++ b/android/app/src/main/java/app/organicmaps/sdk/routing/TransitStepType.java @@ -1,4 +1,4 @@ -package app.organicmaps.routing; +package app.organicmaps.sdk.routing; import androidx.annotation.DrawableRes; diff --git a/android/app/src/main/java/app/organicmaps/settings/DrivingOptionsFragment.java b/android/app/src/main/java/app/organicmaps/settings/DrivingOptionsFragment.java index ec827f45ff..5c5f2f4800 100644 --- a/android/app/src/main/java/app/organicmaps/settings/DrivingOptionsFragment.java +++ b/android/app/src/main/java/app/organicmaps/settings/DrivingOptionsFragment.java @@ -14,7 +14,7 @@ import androidx.appcompat.widget.SwitchCompat; import app.organicmaps.R; import app.organicmaps.base.BaseMwmToolbarFragment; import app.organicmaps.routing.RoutingController; -import app.organicmaps.routing.RoutingOptions; +import app.organicmaps.sdk.routing.RoutingOptions; import java.util.ArrayList; import java.util.Collections; diff --git a/android/app/src/main/java/app/organicmaps/settings/SettingsPrefsFragment.java b/android/app/src/main/java/app/organicmaps/settings/SettingsPrefsFragment.java index 72c07ec630..f0c7fa6e2f 100644 --- a/android/app/src/main/java/app/organicmaps/settings/SettingsPrefsFragment.java +++ b/android/app/src/main/java/app/organicmaps/settings/SettingsPrefsFragment.java @@ -24,7 +24,7 @@ import app.organicmaps.editor.data.Language; import app.organicmaps.help.HelpActivity; import app.organicmaps.location.LocationHelper; import app.organicmaps.location.LocationProviderFactory; -import app.organicmaps.routing.RoutingOptions; +import app.organicmaps.sdk.routing.RoutingOptions; import app.organicmaps.util.Config; import app.organicmaps.util.NetworkPolicy; import app.organicmaps.util.PowerManagment; diff --git a/android/app/src/main/java/app/organicmaps/settings/StoragePathManager.java b/android/app/src/main/java/app/organicmaps/settings/StoragePathManager.java index 749c60dbbb..3cc28453ff 100644 --- a/android/app/src/main/java/app/organicmaps/settings/StoragePathManager.java +++ b/android/app/src/main/java/app/organicmaps/settings/StoragePathManager.java @@ -1,6 +1,5 @@ package app.organicmaps.settings; -import android.app.Application; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -306,9 +305,9 @@ public class StoragePathManager * Checks the currently configured storage first, then scans other storages. * If no map files found uses getDefaultStorage(). */ - public static String findMapsStorage(@NonNull Application application) + public static String findMapsStorage(@NonNull Context context) { - StoragePathManager mgr = new StoragePathManager(application); + StoragePathManager mgr = new StoragePathManager(context); mgr.scanAvailableStorages(); String path; final List storages = mgr.mStorages; diff --git a/android/app/src/main/java/app/organicmaps/util/StorageUtils.java b/android/app/src/main/java/app/organicmaps/util/StorageUtils.java index 5e279c01fd..943eed24ca 100644 --- a/android/app/src/main/java/app/organicmaps/util/StorageUtils.java +++ b/android/app/src/main/java/app/organicmaps/util/StorageUtils.java @@ -1,6 +1,5 @@ package app.organicmaps.util; -import android.app.Application; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; @@ -91,11 +90,11 @@ public class StorageUtils } @NonNull - public static String getApkPath(@NonNull Application application) + public static String getApkPath(@NonNull Context context) { try { - return Utils.getApplicationInfo(application.getPackageManager(), BuildConfig.APPLICATION_ID, 0).sourceDir; + return Utils.getApplicationInfo(context.getPackageManager(), BuildConfig.APPLICATION_ID, 0).sourceDir; } catch (final PackageManager.NameNotFoundException e) { @@ -113,21 +112,21 @@ public class StorageUtils } @NonNull - public static String getSettingsPath(@NonNull Application application) + public static String getSettingsPath(@NonNull Context context) { - return addTrailingSeparator(application.getFilesDir().getAbsolutePath()); + return addTrailingSeparator(context.getFilesDir().getAbsolutePath()); } @NonNull - public static String getPrivatePath(@NonNull Application application) + public static String getPrivatePath(@NonNull Context context) { - return addTrailingSeparator(application.getFilesDir().getAbsolutePath()); + return addTrailingSeparator(context.getFilesDir().getAbsolutePath()); } @NonNull - public static String getTempPath(@NonNull Application application) + public static String getTempPath(@NonNull Context context) { - return addTrailingSeparator(application.getCacheDir().getAbsolutePath()); + return addTrailingSeparator(context.getCacheDir().getAbsolutePath()); } public static boolean createDirectory(@NonNull final String path) diff --git a/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java b/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java index d70055b0f9..1db167f9f6 100644 --- a/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java +++ b/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java @@ -15,6 +15,7 @@ import app.organicmaps.display.DisplayManager; import app.organicmaps.downloader.DownloaderStatusIcon; import app.organicmaps.location.LocationHelper; import app.organicmaps.routing.RoutingController; +import app.organicmaps.sdk.MapStyle; import app.organicmaps.util.concurrency.UiThread; public enum ThemeSwitcher @@ -68,7 +69,7 @@ public enum ThemeSwitcher /** * Changes the UI theme of application and the map style if necessary. If the contract regarding * the input parameter is broken, the UI will be frozen during attempting to change the map style - * through the synchronous method {@link Framework#nativeSetMapStyle(int)}. + * through the synchronous method {@link MapStyle#set(MapStyle)}. * * @param isRendererActive Indicates whether OpenGL renderer is active or not. Must be * true only if the map is rendered and visible on the screen @@ -93,11 +94,8 @@ public enum ThemeSwitcher { UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); String oldTheme = Config.getCurrentUiTheme(mContext); - @Framework.MapStyle - int oldStyle = Framework.nativeGetMapStyle(); - @Framework.MapStyle - int style; + MapStyle style; if (ThemeUtils.isNightTheme(mContext, theme)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) @@ -106,11 +104,11 @@ public enum ThemeSwitcher AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); if (RoutingController.get().isVehicleNavigation()) - style = Framework.MAP_STYLE_VEHICLE_DARK; + style = MapStyle.VehicleDark; else if (Framework.nativeIsOutdoorsLayerEnabled()) - style = Framework.MAP_STYLE_OUTDOORS_DARK; + style = MapStyle.OutdoorsDark; else - style = Framework.MAP_STYLE_DARK; + style = MapStyle.Dark; } else { @@ -120,11 +118,11 @@ public enum ThemeSwitcher AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); if (RoutingController.get().isVehicleNavigation()) - style = Framework.MAP_STYLE_VEHICLE_CLEAR; + style = MapStyle.VehicleClear; else if (Framework.nativeIsOutdoorsLayerEnabled()) - style = Framework.MAP_STYLE_OUTDOORS_CLEAR; + style = MapStyle.OutdoorsClear; else - style = Framework.MAP_STYLE_CLEAR; + style = MapStyle.Clear; } if (!theme.equals(oldTheme)) @@ -139,14 +137,14 @@ public enum ThemeSwitcher else { // If the UI theme is not changed we just need to change the map style if needed. - int currentStyle = Framework.nativeGetMapStyle(); + final MapStyle currentStyle = MapStyle.get(); if (currentStyle == style) return; SetMapStyle(style); } } - private void SetMapStyle(@Framework.MapStyle int style) + private void SetMapStyle(MapStyle style) { // Because of the distinct behavior in auto theme, Android Auto employs its own mechanism for theme switching. // For the Android Auto theme switcher, please consult the app.organicmaps.car.util.ThemeUtils module. @@ -155,8 +153,8 @@ public enum ThemeSwitcher // If rendering is not active we can mark map style, because all graphics // will be recreated after rendering activation. if (mRendererActive) - Framework.nativeSetMapStyle(style); + MapStyle.set(style); else - Framework.nativeMarkMapStyle(style); + MapStyle.mark(style); } } diff --git a/android/app/src/main/java/app/organicmaps/util/Utils.java b/android/app/src/main/java/app/organicmaps/util/Utils.java index a13374805e..a729635b52 100644 --- a/android/app/src/main/java/app/organicmaps/util/Utils.java +++ b/android/app/src/main/java/app/organicmaps/util/Utils.java @@ -583,7 +583,7 @@ public class Utils public static void detachFragmentIfCoreNotInitialized(@NonNull Context context, @NonNull Fragment fragment) { - if (MwmApplication.from(context).arePlatformAndCoreInitialized()) + if (MwmApplication.from(context).getOrganicMaps().arePlatformAndCoreInitialized()) return; FragmentManager manager = fragment.getFragmentManager(); diff --git a/android/app/src/main/java/app/organicmaps/widget/LanesDrawable.java b/android/app/src/main/java/app/organicmaps/widget/LanesDrawable.java index eb01fa560e..c54ba8bb62 100644 --- a/android/app/src/main/java/app/organicmaps/widget/LanesDrawable.java +++ b/android/app/src/main/java/app/organicmaps/widget/LanesDrawable.java @@ -15,7 +15,7 @@ import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; import app.organicmaps.R; -import app.organicmaps.routing.SingleLaneInfo; +import app.organicmaps.sdk.routing.SingleLaneInfo; import java.util.Objects; diff --git a/android/app/src/main/java/app/organicmaps/widget/LanesView.java b/android/app/src/main/java/app/organicmaps/widget/LanesView.java index b1a1a5daa0..0aa0aab4c4 100644 --- a/android/app/src/main/java/app/organicmaps/widget/LanesView.java +++ b/android/app/src/main/java/app/organicmaps/widget/LanesView.java @@ -18,7 +18,7 @@ import androidx.annotation.Nullable; import androidx.annotation.StyleableRes; import app.organicmaps.R; -import app.organicmaps.routing.SingleLaneInfo; +import app.organicmaps.sdk.routing.SingleLaneInfo; public class LanesView extends View { diff --git a/android/app/src/main/java/app/organicmaps/widget/menu/NavMenu.java b/android/app/src/main/java/app/organicmaps/widget/menu/NavMenu.java index 9e2b8612b7..855f364cdc 100644 --- a/android/app/src/main/java/app/organicmaps/widget/menu/NavMenu.java +++ b/android/app/src/main/java/app/organicmaps/widget/menu/NavMenu.java @@ -14,7 +14,7 @@ import androidx.core.content.ContextCompat; import com.google.android.material.bottomsheet.BottomSheetBehavior; import app.organicmaps.R; import app.organicmaps.location.LocationHelper; -import app.organicmaps.routing.RoutingInfo; +import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.sound.TtsPlayer; import app.organicmaps.util.Graphics; import app.organicmaps.util.StringUtils;