diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 58814c95b8..8ee01a164b 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -96,7 +96,7 @@ LOCAL_SRC_FILES := \ com/mapswithme/maps/settings/UnitLocale.cpp \ com/mapswithme/maps/sound/tts.cpp \ com/mapswithme/maps/Sponsored.cpp \ - com/mapswithme/maps/taxi/Taxi.cpp \ + com/mapswithme/maps/taxi/TaxiManager.cpp \ com/mapswithme/maps/TrackRecorder.cpp \ com/mapswithme/maps/TrafficState.cpp \ com/mapswithme/maps/UserMarkHelper.cpp \ diff --git a/android/jni/com/mapswithme/core/jni_helper.cpp b/android/jni/com/mapswithme/core/jni_helper.cpp index 0ef3db0b82..06974dd12d 100644 --- a/android/jni/com/mapswithme/core/jni_helper.cpp +++ b/android/jni/com/mapswithme/core/jni_helper.cpp @@ -104,6 +104,13 @@ jmethodID GetStaticMethodID(JNIEnv * env, jclass clazz, char const * name, char return mid; } +jfieldID GetStaticFieldID(JNIEnv * env, jclass clazz, char const * name, char const * signature) +{ + jfieldID fid = env->GetStaticFieldID(clazz, name, signature); + ASSERT(fid, ("Can't get static field ID", name, signature, DescribeException())); + return fid; +} + jmethodID GetConstructorID(JNIEnv * env, jclass clazz, char const * signature) { jmethodID const ctorID = env->GetMethodID(clazz, "", signature); diff --git a/android/jni/com/mapswithme/core/jni_helper.hpp b/android/jni/com/mapswithme/core/jni_helper.hpp index 4463fd11bd..51e2848965 100644 --- a/android/jni/com/mapswithme/core/jni_helper.hpp +++ b/android/jni/com/mapswithme/core/jni_helper.hpp @@ -30,6 +30,7 @@ JavaVM * GetJVM(); jmethodID GetMethodID(JNIEnv * env, jobject obj, char const * name, char const * signature); jmethodID GetStaticMethodID(JNIEnv * env, jclass clazz, char const * name, char const * signature); jmethodID GetConstructorID(JNIEnv * env, jclass clazz, char const * signature); +jfieldID GetStaticFieldID(JNIEnv * env, jclass clazz, char const * name, char const * signature); // Result value should be DeleteGlobalRef`ed by caller jclass GetGlobalClassRef(JNIEnv * env, char const * s); diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 2b636f004d..6cc7f0813b 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -552,13 +552,11 @@ uint64_t Framework::RequestTaxiProducts(JNIEnv * env, jobject policy, ms::LatLon if (!taxiEngine) return 0; - // TODO Dummy, must be changed by android developer. - // auto const topmostCountryIds = m_work.GetTopmostCountries(from); - // return taxiEngine->GetAvailableProducts(from, to, topmostCountryIds, callback, errorCallback); - return 0; + auto const topmostCountryIds = m_work.GetTopmostCountries(from); + return taxiEngine->GetAvailableProducts(from, to, topmostCountryIds, onSuccess, onError); } -taxi::RideRequestLinks Framework::GetTaxiLinks(JNIEnv * env, jobject policy, +taxi::RideRequestLinks Framework::GetTaxiLinks(JNIEnv * env, jobject policy, taxi::Provider::Type type, string const & productId, ms::LatLon const & from, ms::LatLon const & to) { @@ -566,9 +564,7 @@ taxi::RideRequestLinks Framework::GetTaxiLinks(JNIEnv * env, jobject policy, if (!taxiEngine) return {}; - // TODO Dummy, must be changed by android developer. - // return taxiEngine->GetRideRequestLinks(productId, from, to); - return {}; + return taxiEngine->GetRideRequestLinks(type, productId, from, to); } void Framework::RequestViatorProducts(JNIEnv * env, jobject policy, std::string const & destId, diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index 13b1f30714..129948c51f 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -186,8 +186,9 @@ namespace android uint64_t RequestTaxiProducts(JNIEnv * env, jobject policy, ms::LatLon const & from, ms::LatLon const & to, taxi::SuccessCallback const & onSuccess, taxi::ErrorCallback const & onError); - taxi::RideRequestLinks GetTaxiLinks(JNIEnv * env, jobject policy, std::string const & productId, - ms::LatLon const & from, ms::LatLon const & to); + taxi::RideRequestLinks GetTaxiLinks(JNIEnv * env, jobject policy, taxi::Provider::Type type, + std::string const & productId, ms::LatLon const & from, + ms::LatLon const & to); void RequestViatorProducts(JNIEnv * env, jobject policy, std::string const & destId, std::string const & currency, diff --git a/android/jni/com/mapswithme/maps/taxi/Taxi.cpp b/android/jni/com/mapswithme/maps/taxi/Taxi.cpp deleted file mode 100644 index 840115a86a..0000000000 --- a/android/jni/com/mapswithme/maps/taxi/Taxi.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "../Framework.hpp" - -#include "../../core/jni_helper.hpp" -#include "partners_api/taxi_provider.hpp" - -namespace -{ -jclass g_taxiClass; -jclass g_productClass; -jclass g_routingControllerClass; -jclass g_taxiInfoClass; -jmethodID g_taxiInfoConstructor; -jobject g_routingControllerInstance; -jmethodID g_productConstructor; -jmethodID g_routingControllerGetMethod; -jmethodID g_taxiInfoCallbackMethod; -jmethodID g_taxiErrorCallbackMethod; -jclass g_taxiLinksClass; -jmethodID g_taxiLinksConstructor; -uint64_t g_lastRequestId; - -void PrepareClassRefs(JNIEnv * env) -{ - if (g_taxiClass) - return; - - g_taxiClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiInfo"); - g_productClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiInfo$Product"); - g_routingControllerClass = - jni::GetGlobalClassRef(env, "com/mapswithme/maps/routing/RoutingController"); - g_productConstructor = jni::GetConstructorID( - env, g_productClass, - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - g_taxiInfoClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiInfo"); - g_routingControllerGetMethod = jni::GetStaticMethodID( - env, g_routingControllerClass, "get", "()Lcom/mapswithme/maps/routing/RoutingController;"); - g_routingControllerInstance = - env->CallStaticObjectMethod(g_routingControllerClass, g_routingControllerGetMethod); - g_taxiInfoCallbackMethod = - jni::GetMethodID(env, g_routingControllerInstance, "onTaxiInfoReceived", - "(Lcom/mapswithme/maps/taxi/TaxiInfo;)V"); - g_taxiErrorCallbackMethod = jni::GetMethodID(env, g_routingControllerInstance, - "onTaxiError", "(Ljava/lang/String;)V"); - g_taxiInfoConstructor = jni::GetConstructorID(env, g_taxiInfoClass, - "([Lcom/mapswithme/maps/taxi/TaxiInfo$Product;)V"); - g_taxiLinksClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiLinks"); - g_taxiLinksConstructor = - jni::GetConstructorID(env, g_taxiLinksClass, "(Ljava/lang/String;Ljava/lang/String;)V"); -} - -void OnTaxiInfoReceived(taxi::ProvidersContainer const & products, uint64_t const requestId) -{ - GetPlatform().RunOnGuiThread([=]() { - if (g_lastRequestId != requestId) - return; - // TODO Dummy, must be changed by android developer. - /* - CHECK(!products.empty(), ("List of the products cannot be empty")); - - JNIEnv * env = jni::GetEnv(); - - auto const uberProducts = jni::ToJavaArray( - env, g_productClass, products[0].GetProducts(), - [](JNIEnv * env, taxi::Product const & item) { - return env->NewObject( - g_productClass, g_productConstructor, jni::ToJavaString(env, item.m_productId), - jni::ToJavaString(env, item.m_name), jni::ToJavaString(env, item.m_time), - jni::ToJavaString(env, item.m_price)); - }); - jobject const routingControllerInstance = - env->CallStaticObjectMethod(g_routingControllerClass, g_routingControllerGetMethod); - env->CallVoidMethod(routingControllerInstance, g_uberInfoCallbackMethod, - env->NewObject(g_uberInfoClass, g_uberInfoConstructor, uberProducts)); - */ - }); -} - -void OnTaxiError(taxi::ErrorsContainer const & errors, uint64_t const requestId) -{ - GetPlatform().RunOnGuiThread([=]() { - if (g_lastRequestId != requestId) - return; - // TODO Dummy, must be changed by android developer. - /* - JNIEnv * env = jni::GetEnv(); - - static jclass const errCodeClass = - env->FindClass("com/mapswithme/maps/uber/Uber$ErrorCode"); ASSERT(errCodeClass, ()); - - jobject const routingControllerInstance = - env->CallStaticObjectMethod(g_routingControllerClass, g_routingControllerGetMethod); - - env->CallVoidMethod(routingControllerInstance, g_uberErrorCallbackMethod, - jni::ToJavaString(env, taxi::DebugPrint(code))); - */ - }); -} -} // namespace - -extern "C" { - -JNIEXPORT void JNICALL Java_com_mapswithme_maps_taxi_Taxi_nativeRequestTaxiProducts( - JNIEnv * env, jclass clazz, jobject policy, jdouble srcLat, jdouble srcLon, jdouble dstLat, - jdouble dstLon) -{ - PrepareClassRefs(env); - - ms::LatLon const from(srcLat, srcLon); - ms::LatLon const to(dstLat, dstLon); - - g_lastRequestId = - g_framework->RequestTaxiProducts(env, policy, from, to, &OnTaxiInfoReceived, &OnTaxiError); -} - -JNIEXPORT jobject JNICALL Java_com_mapswithme_maps_taxi_Taxi_nativeGetUberLinks( - JNIEnv * env, jclass clazz, jobject policy, jstring productId, jdouble srcLat, jdouble srcLon, - jdouble dstLat, jdouble dstLon) -{ - PrepareClassRefs(env); - - ms::LatLon const from(srcLat, srcLon); - ms::LatLon const to(dstLat, dstLon); - - taxi::RideRequestLinks const links = - g_framework->GetTaxiLinks(env, policy, jni::ToNativeString(env, productId), from, to); - return env->NewObject(g_taxiLinksClass, g_taxiLinksConstructor, - jni::ToJavaString(env, links.m_deepLink), - jni::ToJavaString(env, links.m_universalLink)); -} -} // extern "C" diff --git a/android/jni/com/mapswithme/maps/taxi/TaxiManager.cpp b/android/jni/com/mapswithme/maps/taxi/TaxiManager.cpp new file mode 100644 index 0000000000..50adbc8102 --- /dev/null +++ b/android/jni/com/mapswithme/maps/taxi/TaxiManager.cpp @@ -0,0 +1,150 @@ +#include "../Framework.hpp" + +#include "com/mapswithme/core/jni_helper.hpp" +#include "com/mapswithme/maps/Framework.hpp" +#include "partners_api/taxi_provider.hpp" + +namespace +{ +jclass g_productClass; +jclass g_taxiManagerClass; +jclass g_taxiInfoClass; +jclass g_taxiInfoErrorClass; +jmethodID g_taxiInfoConstructor; +jmethodID g_taxiInfoErrorConstructor; +jobject g_taxiManagerInstance; +jmethodID g_productConstructor; +jfieldID g_taxiManagerInstanceField; +jmethodID g_taxiInfoCallbackMethod; +jmethodID g_taxiErrorCallbackMethod; +jclass g_taxiLinksClass; +jmethodID g_taxiLinksConstructor; +uint64_t g_lastRequestId; + +void PrepareClassRefs(JNIEnv * env) +{ + if (g_taxiManagerClass) + return; + + g_taxiManagerClass = + jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiManager"); + g_productClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiInfo$Product"); + g_productConstructor = jni::GetConstructorID( + env, g_productClass, + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + g_taxiInfoClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiInfo"); + g_taxiInfoErrorClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiInfoError"); + g_taxiManagerInstanceField = jni::GetStaticFieldID( + env, g_taxiManagerClass, "INSTANCE", "Lcom/mapswithme/maps/taxi/TaxiManager;"); + g_taxiManagerInstance = + env->GetStaticObjectField(g_taxiManagerClass, g_taxiManagerInstanceField); + g_taxiInfoCallbackMethod = + jni::GetMethodID(env, g_taxiManagerInstance, "onTaxiProvidersReceived", + "([Lcom/mapswithme/maps/taxi/TaxiInfo;)V"); + g_taxiErrorCallbackMethod = jni::GetMethodID(env, g_taxiManagerInstance, + "onTaxiErrorsReceived", "([Lcom/mapswithme/maps/taxi/TaxiInfoError;)V"); + g_taxiInfoConstructor = jni::GetConstructorID(env, g_taxiInfoClass, + "(I[Lcom/mapswithme/maps/taxi/TaxiInfo$Product;)V"); + g_taxiInfoErrorConstructor = jni::GetConstructorID(env, g_taxiInfoErrorClass, + "(ILjava/lang/String;)V"); + g_taxiLinksClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/taxi/TaxiLinks"); + g_taxiLinksConstructor = + jni::GetConstructorID(env, g_taxiLinksClass, "(Ljava/lang/String;Ljava/lang/String;)V"); +} + +void OnTaxiInfoReceived(taxi::ProvidersContainer const & providers, uint64_t const requestId) +{ + GetPlatform().RunOnGuiThread([=]() { + if (g_lastRequestId != requestId) + return; + + JNIEnv * env = jni::GetEnv(); + + auto const productBuilder = [](JNIEnv * env, taxi::Product const & item) + { + jni::TScopedLocalRef jProductId(env, jni::ToJavaString(env, item.m_productId)); + jni::TScopedLocalRef jName(env, jni::ToJavaString(env, item.m_name)); + jni::TScopedLocalRef jTime(env, jni::ToJavaString(env, item.m_time)); + jni::TScopedLocalRef jPrice(env, jni::ToJavaString(env, item.m_price)); + return env->NewObject(g_productClass, g_productConstructor, jProductId.get(), jName.get(), + jTime.get(), jPrice.get()); + }; + + auto const providerBuilder = [productBuilder](JNIEnv * env, taxi::Provider const & item) + { + return env->NewObject(g_taxiInfoClass, g_taxiInfoConstructor, item.GetType(), + jni::ToJavaArray(env, g_productClass, item.GetProducts(), productBuilder)); + }; + + jni::TScopedLocalObjectArrayRef jProviders(env, jni::ToJavaArray(env, g_taxiInfoClass, providers, + providerBuilder)); + + jobject const taxiManagerInstance = env->GetStaticObjectField(g_taxiManagerClass, + g_taxiManagerInstanceField); + env->CallVoidMethod(taxiManagerInstance, g_taxiInfoCallbackMethod, jProviders.get()); + + jni::HandleJavaException(env); + }); +} + +void OnTaxiError(taxi::ErrorsContainer const & errors, uint64_t const requestId) +{ + GetPlatform().RunOnGuiThread([=]() { + if (g_lastRequestId != requestId) + return; + + JNIEnv * env = jni::GetEnv(); + + jobject const taxiManagerInstance = env->GetStaticObjectField(g_taxiManagerClass, + g_taxiManagerInstanceField); + + auto const errorBuilder = [](JNIEnv * env, taxi::ProviderError const & error) + { + jni::TScopedLocalRef jErrorCode(env, jni::ToJavaString(env, taxi::DebugPrint(error.m_code))); + return env->NewObject(g_taxiInfoErrorClass, g_taxiInfoConstructor, error.m_type, + jErrorCode.get()); + }; + + + jni::TScopedLocalObjectArrayRef jErrors(env, jni::ToJavaArray(env, g_taxiInfoErrorClass, errors, errorBuilder)); + + env->CallVoidMethod(taxiManagerInstance, g_taxiErrorCallbackMethod, jErrors.get()); + + jni::HandleJavaException(env); + }); +} +} // namespace + +extern "C" { + +JNIEXPORT void JNICALL Java_com_mapswithme_maps_taxi_TaxiManager_nativeRequestTaxiProducts( + JNIEnv * env, jclass clazz, jobject policy, jdouble srcLat, jdouble srcLon, jdouble dstLat, + jdouble dstLon) +{ + PrepareClassRefs(env); + + ms::LatLon const from(srcLat, srcLon); + ms::LatLon const to(dstLat, dstLon); + + g_lastRequestId = + g_framework->RequestTaxiProducts(env, policy, from, to, &OnTaxiInfoReceived, &OnTaxiError); +} + +JNIEXPORT jobject JNICALL Java_com_mapswithme_maps_taxi_TaxiManager_nativeGetTaxiLinks( + JNIEnv * env, jclass clazz, jobject policy, jint providerType, jstring productId, jdouble srcLat, + jdouble srcLon, jdouble dstLat, jdouble dstLon) +{ + PrepareClassRefs(env); + + ms::LatLon const from(srcLat, srcLon); + ms::LatLon const to(dstLat, dstLon); + + taxi::Provider::Type type = static_cast(providerType); + taxi::RideRequestLinks const links = + g_framework->GetTaxiLinks(env, policy, type, jni::ToNativeString(env, productId), from, to); + + return env->NewObject(g_taxiLinksClass, g_taxiLinksConstructor, + jni::ToJavaString(env, links.m_deepLink), + jni::ToJavaString(env, links.m_universalLink)); +} +} // extern "C" diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index 1d7153adec..5674fcab8b 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -72,8 +72,8 @@ import com.mapswithme.maps.settings.SettingsActivity; import com.mapswithme.maps.settings.StoragePathManager; import com.mapswithme.maps.settings.UnitLocale; import com.mapswithme.maps.sound.TtsPlayer; -import com.mapswithme.maps.taxi.Taxi; import com.mapswithme.maps.taxi.TaxiInfo; +import com.mapswithme.maps.taxi.TaxiManager; import com.mapswithme.maps.traffic.TrafficManager; import com.mapswithme.maps.traffic.widget.TrafficButton; import com.mapswithme.maps.traffic.widget.TrafficButtonController; @@ -1898,7 +1898,7 @@ public class MwmActivity extends BaseMwmFragmentActivity } @Override - public void onTaxiError(@NonNull Taxi.ErrorCode code) + public void onTaxiError(@NonNull TaxiManager.ErrorCode code) { if (mIsFragmentContainer) { diff --git a/android/src/com/mapswithme/maps/routing/RoutingBottomMenuController.java b/android/src/com/mapswithme/maps/routing/RoutingBottomMenuController.java index e874d1fd8a..2ee5a8f985 100644 --- a/android/src/com/mapswithme/maps/routing/RoutingBottomMenuController.java +++ b/android/src/com/mapswithme/maps/routing/RoutingBottomMenuController.java @@ -220,6 +220,7 @@ final class RoutingBottomMenuController implements View.OnClickListener if (mTaxiProduct != null) { TaxiLinks links = RoutingController.get().getTaxiLink(mTaxiProduct.getProductId()); + //TODO: check product type and launch corresponding application if (links != null) { Utils.launchUber(mContext, links); diff --git a/android/src/com/mapswithme/maps/routing/RoutingController.java b/android/src/com/mapswithme/maps/routing/RoutingController.java index cf0ddf1bd5..78857e4881 100644 --- a/android/src/com/mapswithme/maps/routing/RoutingController.java +++ b/android/src/com/mapswithme/maps/routing/RoutingController.java @@ -21,9 +21,10 @@ import com.mapswithme.maps.R; import com.mapswithme.maps.bookmarks.data.MapObject; import com.mapswithme.maps.downloader.MapManager; import com.mapswithme.maps.location.LocationHelper; -import com.mapswithme.maps.taxi.Taxi; import com.mapswithme.maps.taxi.TaxiInfo; +import com.mapswithme.maps.taxi.TaxiInfoError; import com.mapswithme.maps.taxi.TaxiLinks; +import com.mapswithme.maps.taxi.TaxiManager; import com.mapswithme.util.Config; import com.mapswithme.util.ConnectionState; import com.mapswithme.util.NetworkPolicy; @@ -39,7 +40,7 @@ import java.util.Calendar; import java.util.concurrent.TimeUnit; @android.support.annotation.UiThread -public class RoutingController +public class RoutingController implements TaxiManager.TaxiListener { private static final String TAG = RoutingController.class.getSimpleName(); @@ -67,7 +68,7 @@ public class RoutingController void showDownloader(boolean openDownloaded); void updateMenu(); void onTaxiInfoReceived(@NonNull TaxiInfo info); - void onTaxiError(@NonNull Taxi.ErrorCode code); + void onTaxiError(@NonNull TaxiManager.ErrorCode code); void onNavigationCancelled(); void onNavigationStarted(); void onAddedStop(); @@ -249,6 +250,7 @@ public class RoutingController { Framework.nativeSetRoutingListener(mRoutingListener); Framework.nativeSetRouteProgressListener(mRoutingProgressListener); + TaxiManager.INSTANCE.setTaxiListener(this); } public void detach() @@ -903,7 +905,7 @@ public class RoutingController mTaxiPlanning = true; - Taxi.nativeRequestTaxiProducts(NetworkPolicy.newInstance(true /* canUse */), + TaxiManager.INSTANCE.nativeRequestTaxiProducts(NetworkPolicy.newInstance(true /* canUse */), mStartPoint.getLat(), mStartPoint.getLon(), mEndPoint.getLat(), mEndPoint.getLon()); if (mContainer != null) @@ -916,40 +918,33 @@ public class RoutingController if (mStartPoint == null || mEndPoint == null) return null; - return Taxi.nativeGetTaxiLinks(NetworkPolicy.newInstance(true /* canUse */), productId, - mStartPoint.getLat(), mStartPoint.getLon(), mEndPoint.getLat(), - mEndPoint.getLon()); + //TODO: implement getting provider type by product id. + return TaxiManager.INSTANCE.nativeGetTaxiLinks(NetworkPolicy.newInstance(true /* canUse */), + TaxiManager.PROVIDER_YANDEX, productId, + mStartPoint.getLat(), mStartPoint.getLon(), + mEndPoint.getLat(), mEndPoint.getLon()); } - /** - * Called from the native code - * @param info this object contains information about Taxi products - */ - @MainThread - private void onTaxiInfoReceived(@NonNull TaxiInfo info) + @Override + public void onTaxiProviderReceived(@NonNull TaxiInfo provider) { mTaxiPlanning = false; - mLogger.d(TAG, "onTaxiInfoReceived uberInfo = " + info); + mLogger.d(TAG, "onTaxiInfoReceived provider = " + provider); if (isTaxiRouterType() && mContainer != null) { - mContainer.onTaxiInfoReceived(info); + mContainer.onTaxiInfoReceived(provider); completeTaxiRequest(); } } - /** - * Called from the native code - * @param errorCode must match the one of the values in {@link Taxi.ErrorCode} - */ - @MainThread - private void onTaxiError(@NonNull String errorCode) + @Override + public void onTaxiErrorReceived(@NonNull TaxiInfoError error) { mTaxiPlanning = false; - Taxi.ErrorCode code = Taxi.ErrorCode.valueOf(errorCode); - mLogger.e(TAG, "onTaxiError error = " + code); + mLogger.e(TAG, "onTaxiError error = " + error); if (isTaxiRouterType() && mContainer != null) { - mContainer.onTaxiError(code); + mContainer.onTaxiError(error.getCode()); completeTaxiRequest(); } } diff --git a/android/src/com/mapswithme/maps/routing/RoutingPlanController.java b/android/src/com/mapswithme/maps/routing/RoutingPlanController.java index ee5f032a7c..3ae0bdb01e 100644 --- a/android/src/com/mapswithme/maps/routing/RoutingPlanController.java +++ b/android/src/com/mapswithme/maps/routing/RoutingPlanController.java @@ -14,8 +14,8 @@ import android.widget.RadioGroup; import com.mapswithme.maps.Framework; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; -import com.mapswithme.maps.taxi.Taxi; import com.mapswithme.maps.taxi.TaxiInfo; +import com.mapswithme.maps.taxi.TaxiManager; import com.mapswithme.maps.widget.RoutingToolbarButton; import com.mapswithme.maps.widget.ToolbarController; import com.mapswithme.maps.widget.WheelProgressView; @@ -222,7 +222,7 @@ public class RoutingPlanController extends ToolbarController mRoutingBottomMenuController.showTaxiInfo(info); } - public void showTaxiError(@NonNull Taxi.ErrorCode code) + public void showTaxiError(@NonNull TaxiManager.ErrorCode code) { switch (code) { diff --git a/android/src/com/mapswithme/maps/routing/RoutingPlanFragment.java b/android/src/com/mapswithme/maps/routing/RoutingPlanFragment.java index a42d29e5d2..f7e0c3c8e5 100644 --- a/android/src/com/mapswithme/maps/routing/RoutingPlanFragment.java +++ b/android/src/com/mapswithme/maps/routing/RoutingPlanFragment.java @@ -9,10 +9,10 @@ import android.view.ViewGroup; import com.mapswithme.maps.Framework; import com.mapswithme.maps.R; -import com.mapswithme.maps.taxi.Taxi; -import com.mapswithme.maps.taxi.TaxiInfo; import com.mapswithme.maps.base.BaseMwmFragment; import com.mapswithme.maps.base.OnBackPressListener; +import com.mapswithme.maps.taxi.TaxiInfo; +import com.mapswithme.maps.taxi.TaxiManager; public class RoutingPlanFragment extends BaseMwmFragment implements OnBackPressListener @@ -40,7 +40,7 @@ public class RoutingPlanFragment extends BaseMwmFragment mPlanController.showTaxiInfo(info); } - public void showTaxiError(@NonNull Taxi.ErrorCode code) + public void showTaxiError(@NonNull TaxiManager.ErrorCode code) { mPlanController.showTaxiError(code); } diff --git a/android/src/com/mapswithme/maps/taxi/Taxi.java b/android/src/com/mapswithme/maps/taxi/Taxi.java deleted file mode 100644 index a00f36ce9f..0000000000 --- a/android/src/com/mapswithme/maps/taxi/Taxi.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.mapswithme.maps.taxi; - -import android.support.annotation.NonNull; - -import com.mapswithme.util.NetworkPolicy; - -public class Taxi -{ - public static native void nativeRequestTaxiProducts(@NonNull NetworkPolicy policy, double srcLat, - double srcLon, double dstLat, double dstLon); - - @NonNull - public static native TaxiLinks nativeGetTaxiLinks(@NonNull NetworkPolicy policy, - @NonNull String productId, double srcLon, - double srcLat, double dstLat, double dstLon); - - public enum ErrorCode - { - NoProducts, RemoteError - } -} diff --git a/android/src/com/mapswithme/maps/taxi/TaxiInfo.java b/android/src/com/mapswithme/maps/taxi/TaxiInfo.java index da9d5652a3..df1318e03d 100644 --- a/android/src/com/mapswithme/maps/taxi/TaxiInfo.java +++ b/android/src/com/mapswithme/maps/taxi/TaxiInfo.java @@ -25,16 +25,21 @@ public class TaxiInfo implements Parcelable } }; + @TaxiManager.TaxiType + private final int mType; @NonNull private final List mProducts; - private TaxiInfo(@NonNull Product[] products) + private TaxiInfo(@TaxiManager.TaxiType int type, @NonNull Product[] products) { + mType = type; mProducts = new ArrayList<>(Arrays.asList(products)); } private TaxiInfo(@NonNull Parcel parcel) { + //noinspection WrongConstant + mType = parcel.readInt(); List products = new ArrayList<>(); parcel.readTypedList(products, Product.CREATOR); mProducts = products; @@ -50,7 +55,8 @@ public class TaxiInfo implements Parcelable public String toString() { return "TaxiInfo{" + - "mProducts=" + mProducts + + "mType=" + mType + + ", mProducts=" + mProducts + '}'; } @@ -63,6 +69,7 @@ public class TaxiInfo implements Parcelable @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mType); dest.writeTypedList(mProducts); } diff --git a/android/src/com/mapswithme/maps/taxi/TaxiInfoError.java b/android/src/com/mapswithme/maps/taxi/TaxiInfoError.java new file mode 100644 index 0000000000..7a29fe2c82 --- /dev/null +++ b/android/src/com/mapswithme/maps/taxi/TaxiInfoError.java @@ -0,0 +1,32 @@ +package com.mapswithme.maps.taxi; + +import android.support.annotation.NonNull; + +public class TaxiInfoError +{ + @TaxiManager.TaxiType + private final int mType; + @NonNull + private final TaxiManager.ErrorCode mCode; + + public TaxiInfoError(int type, @NonNull String errorCode) + { + mType = type; + mCode = TaxiManager.ErrorCode.valueOf(errorCode); + } + + @NonNull + public TaxiManager.ErrorCode getCode() + { + return mCode; + } + + @Override + public String toString() + { + return "TaxiInfoError{" + + "mType=" + mType + + ", mCode=" + mCode + + '}'; + } +} diff --git a/android/src/com/mapswithme/maps/taxi/TaxiManager.java b/android/src/com/mapswithme/maps/taxi/TaxiManager.java new file mode 100644 index 0000000000..b7671762ed --- /dev/null +++ b/android/src/com/mapswithme/maps/taxi/TaxiManager.java @@ -0,0 +1,105 @@ +package com.mapswithme.maps.taxi; + +import android.support.annotation.IntDef; +import android.support.annotation.MainThread; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.mapswithme.util.NetworkPolicy; +import com.mapswithme.util.concurrency.UiThread; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +@MainThread +public class TaxiManager +{ + static final int PROVIDER_UBER = 0; + public static final int PROVIDER_YANDEX = 1; + + public static final TaxiManager INSTANCE = new TaxiManager(); + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ PROVIDER_UBER, PROVIDER_YANDEX }) + @interface TaxiType {} + + @NonNull + private final List mProviders = new ArrayList<>(); + @NonNull + private final List mErrors = new ArrayList<>(); + @Nullable + private TaxiListener mListener; + + private TaxiManager() + { + + } + + // Called from JNI. + @MainThread + void onTaxiProvidersReceived(@NonNull TaxiInfo[] providers) + { + if (!UiThread.currentThreadIsUi()) + throw new AssertionError("Must be called from UI thread!"); + + if (providers.length == 0) + throw new AssertionError("Taxi provider array must be non-empty!"); + + mProviders.clear(); + mProviders.addAll(Arrays.asList(providers)); + + if (mListener != null) + { + // Taxi provider list must contain only one element until we implement taxi aggregator feature. + mListener.onTaxiProviderReceived(mProviders.get(0)); + } + } + + // Called from JNI. + @MainThread + void onTaxiErrorsReceived(@NonNull TaxiInfoError[] errors) + { + if (!UiThread.currentThreadIsUi()) + throw new AssertionError("Must be called from UI thread!"); + + if (errors.length == 0) + throw new AssertionError("Taxi error array must be non-empty!"); + + mErrors.clear(); + mErrors.addAll(Arrays.asList(errors)); + + if (mListener != null) + { + // Taxi error list must contain only one element until we implement taxi aggregator feature. + mListener.onTaxiErrorReceived(mErrors.get(0)); + } + } + + public void setTaxiListener(@Nullable TaxiListener listener) + { + mListener = listener; + } + + public native void nativeRequestTaxiProducts(@NonNull NetworkPolicy policy, double srcLat, + double srcLon, double dstLat, double dstLon); + + @NonNull + public native TaxiLinks nativeGetTaxiLinks(@NonNull NetworkPolicy policy, @TaxiType int type, + @NonNull String productId, double srcLon, + double srcLat, double dstLat, double dstLon); + + public enum ErrorCode + { + NoProducts, RemoteError + } + + public interface TaxiListener + { + void onTaxiProviderReceived(@NonNull TaxiInfo provider); + void onTaxiErrorReceived(@NonNull TaxiInfoError error); + } +} diff --git a/android/src/com/mapswithme/util/Utils.java b/android/src/com/mapswithme/util/Utils.java index eff5ae2553..6fa7234a1e 100644 --- a/android/src/com/mapswithme/util/Utils.java +++ b/android/src/com/mapswithme/util/Utils.java @@ -299,17 +299,18 @@ public class Utils public static void launchUber(@NonNull Activity context, @NonNull TaxiLinks links) { + //TODO: handle type of taxi merely final Intent intent = new Intent(Intent.ACTION_VIEW); - if (isUberInstalled(context)) +/* if (isUberInstalled(context)) { - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);*/ intent.setData(Uri.parse(links.getDeepLink())); - } else +/* } else { // No Taxi app! Open mobile website. intent.setData(Uri.parse(links.getUniversalLink())); - } + }*/ context.startActivity(intent); }