diff --git a/OsmAnd/res/layout/bottom_sheet_item_with_descr_64dp.xml b/OsmAnd/res/layout/bottom_sheet_item_with_descr_64dp.xml
index 2ff6a1bf58..95091e1086 100644
--- a/OsmAnd/res/layout/bottom_sheet_item_with_descr_64dp.xml
+++ b/OsmAnd/res/layout/bottom_sheet_item_with_descr_64dp.xml
@@ -27,6 +27,8 @@
android:layout_weight="1"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
+ android:paddingTop="@dimen/content_padding_small"
+ android:paddingBottom="@dimen/content_padding_small"
android:orientation="vertical">
+
+
قدم
دراجة هوائية
سيارة
- خطأ، أعد التحقق من المعايير
نسخ العنوان
محرك التوجيه عبر الإنترنت
محركات التوجيه عبر الإنترنت
diff --git a/OsmAnd/res/values-cs/strings.xml b/OsmAnd/res/values-cs/strings.xml
index 38af3fcceb..6d6b906b06 100644
--- a/OsmAnd/res/values-cs/strings.xml
+++ b/OsmAnd/res/values-cs/strings.xml
@@ -3960,7 +3960,6 @@
Chůze
Kolo
Auto
- Chyba, zkontrolujte parametry
Kopírovat adresu
Online navigační služba
Online navigační služby
diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml
index e66df6bcd7..b216a47c7c 100644
--- a/OsmAnd/res/values-de/strings.xml
+++ b/OsmAnd/res/values-de/strings.xml
@@ -3962,7 +3962,6 @@
Zu Fuß
Fahrrad
Auto
- Fehler, Parameter erneut prüfen
Subtyp
Leer lassen, wenn kein API-Schlüssel vorhanden
Adresse kopieren
diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml
index 391e96ba42..9671d14e5f 100644
--- a/OsmAnd/res/values-eo/strings.xml
+++ b/OsmAnd/res/values-eo/strings.xml
@@ -3960,7 +3960,6 @@
Piediranto
Biciklo
Aŭtomobilo
- Eraro, rekontrolu parametrojn
Kopii adreson
Enreta navigilo
Enretaj navigiloj
diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml
index fd54cd500f..83700ce7cd 100644
--- a/OsmAnd/res/values-es-rAR/strings.xml
+++ b/OsmAnd/res/values-es-rAR/strings.xml
@@ -3963,7 +3963,6 @@
Peatón
Bicicleta
Automóvil
- Error, vuelve a comprobar los parámetros
Copiar dirección
Motor de navegación en línea
Motores de navegación en línea
diff --git a/OsmAnd/res/values-eu/strings.xml b/OsmAnd/res/values-eu/strings.xml
index ee2a825985..dced5cf049 100644
--- a/OsmAnd/res/values-eu/strings.xml
+++ b/OsmAnd/res/values-eu/strings.xml
@@ -3933,6 +3933,5 @@ Area honi dagokio: %1$s x %2$s
Oinez
Bizikleta
Kotxea
- Errorea, egiaztatu parametroak berriro
Kopiatu helbidea
\ No newline at end of file
diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml
index 3cb0760eac..226a00cc5c 100644
--- a/OsmAnd/res/values-fa/strings.xml
+++ b/OsmAnd/res/values-fa/strings.xml
@@ -3953,5 +3953,4 @@
پا
دوچرخه
خودرو
- خطا، پارامترها را بازبینی کنید
\ No newline at end of file
diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml
index 0b7dc82b1c..e5f41539c2 100644
--- a/OsmAnd/res/values-fr/strings.xml
+++ b/OsmAnd/res/values-fr/strings.xml
@@ -3947,7 +3947,6 @@
A pieds
Vélo
Automobile
- Erreur, vérifiez les paramètres
Ajouter un moteur de routage en ligne
Modifier le moteur de routage en ligne
L\'URL avec tous les paramètres sera de la forme :
diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml
index 2e0c0053d3..5570577760 100644
--- a/OsmAnd/res/values-gl/strings.xml
+++ b/OsmAnd/res/values-gl/strings.xml
@@ -3968,7 +3968,6 @@ Lon %2$s
Pé
Bicicleta
Coche
- Erro, verifica novamente os parámetros
Copiar enderezo
Horarios dos avisos por voz
Motor de navegación en liña
diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml
index d893dcf47e..64d40e287c 100644
--- a/OsmAnd/res/values-hu/strings.xml
+++ b/OsmAnd/res/values-hu/strings.xml
@@ -3954,7 +3954,6 @@
Hagyja üresen, ha nem
Az összes paraméterrel rendelkező URL így néz ki:
Útvonaltervezés kipróbálása
- Hiba, ellenőrizze újra a paramétereket
Cím másolása
Online útvonaltervező
Online útvonaltervezők
diff --git a/OsmAnd/res/values-is/strings.xml b/OsmAnd/res/values-is/strings.xml
index 3449458457..0b94e361f7 100644
--- a/OsmAnd/res/values-is/strings.xml
+++ b/OsmAnd/res/values-is/strings.xml
@@ -3965,6 +3965,5 @@
Gangandi
Hjólandi
Bíll
- Villa, yfirfarðu breytur
Afrita heimilisfang
\ No newline at end of file
diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml
index 44f2c8c034..7ca3bcdb8d 100644
--- a/OsmAnd/res/values-iw/strings.xml
+++ b/OsmAnd/res/values-iw/strings.xml
@@ -3963,7 +3963,6 @@
ברגל
אופנוע
מכונית
- שגיאה, נא לבדוק את המשתנים מחדש
העתקת כתובת
מנוע ניווט מקוון
מנועי ניווט מקוונים
diff --git a/OsmAnd/res/values-ka/strings.xml b/OsmAnd/res/values-ka/strings.xml
index 770916e3b3..330d43d2c4 100644
--- a/OsmAnd/res/values-ka/strings.xml
+++ b/OsmAnd/res/values-ka/strings.xml
@@ -2449,7 +2449,6 @@
OsmAndის გამოწერა დაპაუზებულია
OsmAndის გამოწერა შეჩერებულია
URL ყველა პარამეტრით აი ასეთი იქნება:
- შეცდომა, გადაამოწმეთ პარამეტრები
Mapillary-ის გამოსახულება
Mapillary-ის ღილაკი
ფერთა გამა
diff --git a/OsmAnd/res/values-lt/strings.xml b/OsmAnd/res/values-lt/strings.xml
index 65c711462f..09ee2a83fd 100644
--- a/OsmAnd/res/values-lt/strings.xml
+++ b/OsmAnd/res/values-lt/strings.xml
@@ -2770,7 +2770,6 @@ Tai yra puikus būdas paremti OsmAnd ir OSM, jei jie jums patinka.
Patikrinti maršruto apskaičiavimą
Dviratis
Automobilis
- Įvyko klaida, patikrinkite paametrus
Kopijuoti adresą
Folderiai
Pasirinkite folderį
diff --git a/OsmAnd/res/values-nl/strings.xml b/OsmAnd/res/values-nl/strings.xml
index 04da6132ce..4420cd6987 100644
--- a/OsmAnd/res/values-nl/strings.xml
+++ b/OsmAnd/res/values-nl/strings.xml
@@ -3916,7 +3916,6 @@
Te voet
Fiets
Auto
- Fout, controleer parameters opnieuw
Kopieer adres
Online routeplanningssysteem
Online routeplanningssystemen
diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml
index cf4852f488..840fa52189 100644
--- a/OsmAnd/res/values-pl/strings.xml
+++ b/OsmAnd/res/values-pl/strings.xml
@@ -3956,7 +3956,6 @@
Obliczanie trasy testowej
Rower
Samochód
- Błąd, ponownie sprawdź parametry
Skopiuj adres
Jazda
Stopa
diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml
index da70b09ce8..52d578c035 100644
--- a/OsmAnd/res/values-pt-rBR/strings.xml
+++ b/OsmAnd/res/values-pt-rBR/strings.xml
@@ -3955,7 +3955,6 @@
Pé
Bicicleta
Carro
- Erro, verifique novamente os parâmetros
Copiar endereço
Motor de encaminhamento online
Mecanismos de roteamento online
diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml
index f5ff13cd8b..aa05e82d25 100644
--- a/OsmAnd/res/values-sc/strings.xml
+++ b/OsmAnd/res/values-sc/strings.xml
@@ -3957,7 +3957,6 @@
A pee
Bitzicleta
Màchina
- Errore, torra a verificare sos paràmetros
Còpia s\'indiritzu
Motore de càrculu in lìnia
Motores de càrculu in lìnia
diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml
index 6d8fb45d93..81a9d73353 100644
--- a/OsmAnd/res/values-sk/strings.xml
+++ b/OsmAnd/res/values-sk/strings.xml
@@ -3955,7 +3955,6 @@
Chôdza
Bicykel
Auto
- Chyba, skontrolujte parametre
Kopírovať adresu
Online navigačná služba
Online navigačné služby
diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml
index ee5e25124a..344183c102 100644
--- a/OsmAnd/res/values-tr/strings.xml
+++ b/OsmAnd/res/values-tr/strings.xml
@@ -3961,7 +3961,6 @@
Yürüme
Bisiklet
Araba
- Hata, parametreleri tekrar gözden geçirin
Adresi kopyala
Çevrim içi yönlendirme motoru
Çevrim içi yönlendirme motorları
diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml
index 2738eda283..6910c9a902 100644
--- a/OsmAnd/res/values-uk/strings.xml
+++ b/OsmAnd/res/values-uk/strings.xml
@@ -3959,7 +3959,6 @@
Пішки
Велосипед
Автомобіль
- Помилка, повторно перевірте параметри
Копіювати адресу
Мережний рушій маршрутизації
Мережні рушії маршрутизації
diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml
index 738ede85e2..0f19668c01 100644
--- a/OsmAnd/res/values-zh-rTW/strings.xml
+++ b/OsmAnd/res/values-zh-rTW/strings.xml
@@ -3953,7 +3953,6 @@
步行
自行車
汽車
- 錯誤,重新檢查參數
複製地址
線上路線計算引擎
線上路線計算引擎
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index 299e7aa5b2..8605ea2189 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -12,6 +12,21 @@
-->
+ The name is already exists
+ Server error: %1$s
+ MTB
+ Racing bike
+ Scooter
+ Truck
+ Small truck
+ HGV
+ Regular cycling
+ Road cycling
+ Mountain cycling
+ Electric cycling
+ Walking
+ Hiking
+ Wheelchair
Show track on map
Start recording
Announcement time
@@ -37,7 +52,6 @@
Online routing engines
Online routing engine
Copy address
- Error, recheck parameters
Car
Bike
Foot
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/EngineParameter.java b/OsmAnd/src/net/osmand/plus/onlinerouting/EngineParameter.java
new file mode 100644
index 0000000000..fa3ccd81c7
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/EngineParameter.java
@@ -0,0 +1,10 @@
+package net.osmand.plus.onlinerouting;
+
+public enum EngineParameter {
+ KEY,
+ VEHICLE_KEY,
+ CUSTOM_NAME,
+ NAME_INDEX,
+ CUSTOM_URL,
+ API_KEY
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/EngineType.java b/OsmAnd/src/net/osmand/plus/onlinerouting/EngineType.java
deleted file mode 100644
index fe5080f14c..0000000000
--- a/OsmAnd/src/net/osmand/plus/onlinerouting/EngineType.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.osmand.plus.onlinerouting;
-
-public enum EngineType {
-
- GRAPHHOPPER("Graphhopper", "https://graphhopper.com/api/1/route"),
- OSRM("OSRM", "https://router.project-osrm.org/route/v1/"),
- ORS("Openroute Service", "https://api.openrouteservice.org/v2/directions/");
-
- private String title;
- private String standardUrl;
-
- EngineType(String title, String standardUrl) {
- this.title = title;
- this.standardUrl = standardUrl;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getStandardUrl() {
- return standardUrl;
- }
-}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngine.java
deleted file mode 100644
index 3193d86d09..0000000000
--- a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngine.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package net.osmand.plus.onlinerouting;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import net.osmand.plus.R;
-import net.osmand.util.Algorithms;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class OnlineRoutingEngine {
-
- public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
-
- public enum EngineParameter {
- CUSTOM_NAME,
- CUSTOM_URL,
- API_KEY
- }
-
- private String stringKey;
- private EngineType type;
- private String vehicleKey;
- private Map params = new HashMap<>();
-
- public OnlineRoutingEngine(@NonNull String stringKey,
- @NonNull EngineType type,
- @NonNull String vehicleKey,
- @Nullable Map params) {
- this(stringKey, type, vehicleKey);
- if (!Algorithms.isEmpty(params)) {
- this.params.putAll(params);
- }
- }
-
- public OnlineRoutingEngine(@NonNull String stringKey,
- @NonNull EngineType type,
- @NonNull String vehicleKey) {
- this.stringKey = stringKey;
- this.type = type;
- this.vehicleKey = vehicleKey;
- }
-
- public String getStringKey() {
- return stringKey;
- }
-
- public EngineType getType() {
- return type;
- }
-
- public String getBaseUrl() {
- String customUrl = getParameter(EngineParameter.CUSTOM_URL);
- if (Algorithms.isEmpty(customUrl)) {
- return type.getStandardUrl();
- }
- return customUrl;
- }
-
- public String getVehicleKey() {
- return vehicleKey;
- }
-
- public Map getParams() {
- return params;
- }
-
- public String getParameter(EngineParameter paramKey) {
- return params.get(paramKey.name());
- }
-
- public void putParameter(EngineParameter paramKey, String paramValue) {
- params.put(paramKey.name(), paramValue);
- }
-
- public String getName(@NonNull Context ctx) {
- String customName = getParameter(EngineParameter.CUSTOM_NAME);
- if (customName != null) {
- return customName;
- } else {
- return getStandardName(ctx);
- }
- }
-
- private String getStandardName(@NonNull Context ctx) {
- return getStandardName(ctx, type, vehicleKey);
- }
-
- public static String getStandardName(@NonNull Context ctx,
- @NonNull EngineType type,
- @NonNull String vehicleKey) {
- String vehicleTitle = VehicleType.toHumanString(ctx, vehicleKey);
- String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_dash);
- return String.format(pattern, type.getTitle(), vehicleTitle);
- }
-
- public static OnlineRoutingEngine createNewEngine(@NonNull EngineType type,
- @NonNull String vehicleKey,
- @Nullable Map params) {
- return new OnlineRoutingEngine(generateKey(), type, vehicleKey, params);
- }
-
- private static String generateKey() {
- return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
- }
-}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingFactory.java b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingFactory.java
new file mode 100644
index 0000000000..4b92000847
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingFactory.java
@@ -0,0 +1,36 @@
+package net.osmand.plus.onlinerouting;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.plus.onlinerouting.engine.EngineType;
+import net.osmand.plus.onlinerouting.engine.GraphhopperEngine;
+import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
+import net.osmand.plus.onlinerouting.engine.OrsEngine;
+import net.osmand.plus.onlinerouting.engine.OsrmEngine;
+
+import java.util.Map;
+
+public class OnlineRoutingFactory {
+
+ public static OnlineRoutingEngine createEngine(@NonNull EngineType type) {
+ return createEngine(type, null);
+ }
+
+ @NonNull
+ public static OnlineRoutingEngine createEngine(@NonNull EngineType type,
+ @Nullable Map params) {
+ switch (type) {
+ case GRAPHHOPPER:
+ return new GraphhopperEngine(params);
+ case OSRM:
+ return new OsrmEngine(params);
+ case ORS:
+ return new OrsEngine(params);
+ default:
+ throw new IllegalArgumentException(
+ "Online routing type {" + type.name() + "} not supported");
+ }
+ }
+
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java
index b54746ddd6..b28d98d55f 100644
--- a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java
@@ -1,6 +1,7 @@
package net.osmand.plus.onlinerouting;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
@@ -10,10 +11,10 @@ import net.osmand.data.LatLon;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.Version;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameter;
+import net.osmand.plus.onlinerouting.engine.EngineType;
+import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
-import net.osmand.util.GeoPolylineParserUtil;
import org.apache.commons.logging.Log;
import org.json.JSONArray;
@@ -24,7 +25,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
-import java.net.URLConnection;
+import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -35,14 +36,18 @@ public class OnlineRoutingHelper {
private static final Log LOG = PlatformUtil.getLog(OnlineRoutingHelper.class);
+ private static final String ITEMS = "items";
+ private static final String TYPE = "type";
+ private static final String PARAMS = "params";
+
private OsmandApplication app;
private OsmandSettings settings;
private Map cachedEngines;
- public OnlineRoutingHelper(OsmandApplication app) {
+ public OnlineRoutingHelper(@NonNull OsmandApplication app) {
this.app = app;
this.settings = app.getSettings();
- loadFromSettings();
+ this.cachedEngines = loadSavedEngines();
}
@NonNull
@@ -50,104 +55,42 @@ public class OnlineRoutingHelper {
return new ArrayList<>(cachedEngines.values());
}
- public OnlineRoutingEngine getEngineByKey(String stringKey) {
+ @NonNull
+ public List getEnginesExceptMentioned(@Nullable String ... excludeKeys) {
+ List engines = getEngines();
+ if (excludeKeys != null) {
+ for (String key : excludeKeys) {
+ OnlineRoutingEngine engine = getEngineByKey(key);
+ engines.remove(engine);
+ }
+ }
+ return engines;
+ }
+
+ @Nullable
+ public OnlineRoutingEngine getEngineByKey(@Nullable String stringKey) {
return cachedEngines.get(stringKey);
}
+ @NonNull
public List calculateRouteOnline(@NonNull OnlineRoutingEngine engine,
@NonNull List path) throws IOException, JSONException {
- String fullUrl = createFullUrl(engine, path);
- String content = makeRequest(fullUrl);
- return parseResponse(engine, content);
+ String url = engine.getFullUrl(path);
+ String content = makeRequest(url);
+ return engine.parseServerResponse(content);
}
- public String createFullUrl(OnlineRoutingEngine engine, List path) {
- StringBuilder sb = new StringBuilder(engine.getBaseUrl());
- String vehicle = engine.getVehicleKey();
- String apiKey = engine.getParameter(EngineParameter.API_KEY);
- switch (engine.getType()) {
-
- case GRAPHHOPPER:
- sb.append("?");
- for (LatLon point : path) {
- sb.append("point=")
- .append(point.getLatitude())
- .append(',')
- .append(point.getLongitude())
- .append('&');
- }
- sb.append("vehicle=").append(vehicle);
-
- if (!Algorithms.isEmpty(apiKey)) {
- sb.append('&').append("key=").append(apiKey);
- }
- break;
-
- case OSRM:
- sb.append(vehicle).append('/');
- for (int i = 0; i < path.size(); i++) {
- LatLon point = path.get(i);
- sb.append(point.getLongitude()).append(',').append(point.getLatitude());
- if (i < path.size() - 1) {
- sb.append(';');
- }
- }
- break;
-
- case ORS:
- if (path.size() > 1) {
- sb.append("driving-car").append('?'); // todo only for testing
- if (!Algorithms.isEmpty(apiKey)) {
- sb.append("api_key=").append(apiKey);
- }
- LatLon start = path.get(0);
- LatLon end = path.get(path.size() - 1);
- sb.append('&').append("start=")
- .append(start.getLatitude()).append(',').append(start.getLongitude());
- sb.append('&').append("end=")
- .append(end.getLatitude()).append(',').append(end.getLongitude());
- }
- break;
-
- }
- return sb.toString();
- }
-
- private List parseResponse(OnlineRoutingEngine engine, String content) throws JSONException {
- JSONObject obj = new JSONObject(content);
-
- switch (engine.getType()) {
-
- case GRAPHHOPPER:
- return GeoPolylineParserUtil.parse(
- obj.getJSONArray("paths").getJSONObject(0).getString("points"),
- GeoPolylineParserUtil.PRECISION_5);
-
- case OSRM:
- return GeoPolylineParserUtil.parse(
- obj.getJSONArray("routes").getJSONObject(0).getString("geometry"),
- GeoPolylineParserUtil.PRECISION_5);
-
- case ORS:
- JSONArray array = obj.getJSONArray("features").getJSONObject(0)
- .getJSONObject("geometry").getJSONArray("coordinates");
- List track = new ArrayList<>();
- for (int i = 0; i < array.length(); i++) {
- JSONArray point = array.getJSONArray(i);
- double lat = Double.parseDouble(point.getString(0));
- double lon = Double.parseDouble(point.getString(1));
- track.add(new LatLon(lat, lon));
- }
- return track;
- }
- return new ArrayList<>();
- }
-
- private String makeRequest(String url) throws IOException {
- URLConnection connection = NetworkUtils.getHttpURLConnection(url);
+ @NonNull
+ public String makeRequest(@NonNull String url) throws IOException {
+ HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url);
connection.setRequestProperty("User-Agent", Version.getFullVersion(app));
StringBuilder content = new StringBuilder();
- BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ BufferedReader reader;
+ if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+ reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ } else {
+ reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
+ }
String s;
while ((s = reader.readLine()) != null) {
content.append(s);
@@ -160,32 +103,49 @@ public class OnlineRoutingHelper {
}
public void saveEngine(@NonNull OnlineRoutingEngine engine) {
- String stringKey = engine.getStringKey();
- cachedEngines.put(stringKey, engine);
- saveToSettings();
- }
-
- public void deleteEngine(@NonNull String stringKey) {
- OnlineRoutingEngine engine = getEngineByKey(stringKey);
- if (engine != null) {
- deleteEngine(engine);
- }
+ deleteInaccessibleParameters(engine);
+ String key = createEngineKeyIfNeeded(engine);
+ cachedEngines.put(key, engine);
+ saveCacheToSettings();
}
public void deleteEngine(@NonNull OnlineRoutingEngine engine) {
String stringKey = engine.getStringKey();
- if (cachedEngines.containsKey(stringKey)) {
+ deleteEngine(stringKey);
+ }
+
+ public void deleteEngine(@Nullable String stringKey) {
+ if (stringKey != null) {
cachedEngines.remove(stringKey);
- saveToSettings();
+ saveCacheToSettings();
}
}
- private void loadFromSettings() {
+ private void deleteInaccessibleParameters(@NonNull OnlineRoutingEngine engine) {
+ for (EngineParameter key : EngineParameter.values()) {
+ if (!engine.isParameterAllowed(key)) {
+ engine.remove(key);
+ }
+ }
+ }
+
+ @NonNull
+ private String createEngineKeyIfNeeded(@NonNull OnlineRoutingEngine engine) {
+ String key = engine.get(EngineParameter.KEY);
+ if (Algorithms.isEmpty(key)) {
+ key = OnlineRoutingEngine.generateKey();
+ engine.put(EngineParameter.KEY, key);
+ }
+ return key;
+ }
+
+ @NonNull
+ private Map loadSavedEngines() {
Map cachedEngines = new LinkedHashMap<>();
for (OnlineRoutingEngine engine : readFromSettings()) {
cachedEngines.put(engine.getStringKey(), engine);
}
- this.cachedEngines = cachedEngines;
+ return cachedEngines;
}
@NonNull
@@ -196,14 +156,14 @@ public class OnlineRoutingHelper {
try {
JSONObject json = new JSONObject(jsonString);
readFromJson(json, engines);
- } catch (JSONException e) {
+ } catch (JSONException | IllegalArgumentException e) {
LOG.debug("Error when reading engines from JSON ", e);
}
}
return engines;
}
- private void saveToSettings() {
+ private void saveCacheToSettings() {
if (!Algorithms.isEmpty(cachedEngines)) {
try {
JSONObject json = new JSONObject();
@@ -217,38 +177,44 @@ public class OnlineRoutingHelper {
}
}
- public static void readFromJson(JSONObject json, List engines) throws JSONException {
+ public static void readFromJson(@NonNull JSONObject json,
+ @NonNull List engines) throws JSONException {
if (!json.has("items")) {
return;
}
Gson gson = new Gson();
- Type type = new TypeToken>() {
+ Type typeToken = new TypeToken>() {
}.getType();
- JSONArray itemsJson = json.getJSONArray("items");
+ JSONArray itemsJson = json.getJSONArray(ITEMS);
for (int i = 0; i < itemsJson.length(); i++) {
JSONObject object = itemsJson.getJSONObject(i);
- String key = object.getString("key");
- String vehicleKey = object.getString("vehicle");
- EngineType engineType = EngineType.valueOf(object.getString("type"));
- String paramsString = object.getString("params");
- HashMap params = gson.fromJson(paramsString, type);
- engines.add(new OnlineRoutingEngine(key, engineType, vehicleKey, params));
+ if (object.has(TYPE) && object.has(PARAMS)) {
+ EngineType type = EngineType.getTypeByName(object.getString(TYPE));
+ String paramsString = object.getString(PARAMS);
+ HashMap params = gson.fromJson(paramsString, typeToken);
+ OnlineRoutingEngine engine = OnlineRoutingFactory.createEngine(type, params);
+ if (!Algorithms.isEmpty(engine.getStringKey())) {
+ engines.add(engine);
+ }
+ }
}
}
- public static void writeToJson(JSONObject json, List engines) throws JSONException {
+ public static void writeToJson(@NonNull JSONObject json,
+ @NonNull List engines) throws JSONException {
JSONArray jsonArray = new JSONArray();
Gson gson = new Gson();
Type type = new TypeToken>() {
}.getType();
for (OnlineRoutingEngine engine : engines) {
+ if (Algorithms.isEmpty(engine.getStringKey())) {
+ continue;
+ }
JSONObject jsonObject = new JSONObject();
- jsonObject.put("key", engine.getStringKey());
- jsonObject.put("type", engine.getType().name());
- jsonObject.put("vehicle", engine.getVehicleKey());
- jsonObject.put("params", gson.toJson(engine.getParams(), type));
+ jsonObject.put(TYPE, engine.getType().name());
+ jsonObject.put(PARAMS, gson.toJson(engine.getParams(), type));
jsonArray.put(jsonObject);
}
- json.put("items", jsonArray);
+ json.put(ITEMS, jsonArray);
}
}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/VehicleType.java b/OsmAnd/src/net/osmand/plus/onlinerouting/VehicleType.java
index 3e3fea6660..9936f8efbf 100644
--- a/OsmAnd/src/net/osmand/plus/onlinerouting/VehicleType.java
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/VehicleType.java
@@ -3,48 +3,26 @@ package net.osmand.plus.onlinerouting;
import android.content.Context;
import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
-import net.osmand.plus.R;
-import net.osmand.util.Algorithms;
+public class VehicleType {
+ private final String key;
+ @StringRes
+ private final int titleId;
-public enum VehicleType {
- CAR("car", R.string.routing_engine_vehicle_type_car),
- BIKE("bike", R.string.routing_engine_vehicle_type_bike),
- FOOT("foot", R.string.routing_engine_vehicle_type_foot),
- DRIVING("driving", R.string.routing_engine_vehicle_type_driving),
- CUSTOM("", R.string.shared_string_custom);
-
- VehicleType(String key, int titleId) {
+ public VehicleType(@NonNull String key,
+ @StringRes int titleId) {
this.key = key;
this.titleId = titleId;
}
- private String key;
- private int titleId;
-
+ @NonNull
public String getKey() {
return key;
}
- public String getTitle(Context ctx) {
+ @NonNull
+ public String getTitle(@NonNull Context ctx) {
return ctx.getString(titleId);
}
-
- public static String toHumanString(@NonNull Context ctx,
- @NonNull String key) {
- VehicleType vehicleType = getVehicleByKey(key);
- if (vehicleType == CUSTOM) {
- return Algorithms.capitalizeFirstLetter(key);
- }
- return vehicleType.getTitle(ctx);
- }
-
- public static VehicleType getVehicleByKey(String key) {
- for (VehicleType v : values()) {
- if (Algorithms.objectEquals(v.getKey(), key)) {
- return v;
- }
- }
- return CUSTOM;
- }
-}
\ No newline at end of file
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/EngineType.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/EngineType.java
new file mode 100644
index 0000000000..431ad33a3d
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/EngineType.java
@@ -0,0 +1,34 @@
+package net.osmand.plus.onlinerouting.engine;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.util.Algorithms;
+
+public enum EngineType {
+ GRAPHHOPPER("Graphhopper"),
+ OSRM("OSRM"),
+ ORS("Openroute Service");
+
+ private final String title;
+
+ EngineType(String title) {
+ this.title = title;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ @NonNull
+ public static EngineType getTypeByName(@Nullable String name) {
+ if (!Algorithms.isEmpty(name)) {
+ for (EngineType type : values()) {
+ if (type.name().equals(name)) {
+ return type;
+ }
+ }
+ }
+ return values()[0];
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java
new file mode 100644
index 0000000000..d676e1e154
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java
@@ -0,0 +1,95 @@
+package net.osmand.plus.onlinerouting.engine;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.data.LatLon;
+import net.osmand.plus.R;
+import net.osmand.plus.onlinerouting.EngineParameter;
+import net.osmand.plus.onlinerouting.VehicleType;
+import net.osmand.util.GeoPolylineParserUtil;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.List;
+import java.util.Map;
+
+import static net.osmand.util.Algorithms.isEmpty;
+
+public class GraphhopperEngine extends OnlineRoutingEngine {
+
+ public GraphhopperEngine(@Nullable Map params) {
+ super(params);
+ }
+
+ @Override
+ public @NonNull EngineType getType() {
+ return EngineType.GRAPHHOPPER;
+ }
+
+ @NonNull
+ @Override
+ public String getStandardUrl() {
+ return "https://graphhopper.com/api/1/route";
+ }
+
+ @Override
+ protected void collectAllowedParameters() {
+ allowParameters(EngineParameter.API_KEY);
+ }
+
+ @Override
+ protected void collectAllowedVehicles(@NonNull List vehicles) {
+ vehicles.add(new VehicleType("car", R.string.routing_engine_vehicle_type_car));
+ vehicles.add(new VehicleType("bike", R.string.routing_engine_vehicle_type_bike));
+ vehicles.add(new VehicleType("foot", R.string.routing_engine_vehicle_type_foot));
+ vehicles.add(new VehicleType("hike", R.string.routing_engine_vehicle_type_hiking));
+ vehicles.add(new VehicleType("mtb", R.string.routing_engine_vehicle_type_mtb));
+ vehicles.add(new VehicleType("racingbike", R.string.routing_engine_vehicle_type_racingbike));
+ vehicles.add(new VehicleType("scooter", R.string.routing_engine_vehicle_type_scooter));
+ vehicles.add(new VehicleType("truck", R.string.routing_engine_vehicle_type_truck));
+ vehicles.add(new VehicleType("small_truck", R.string.routing_engine_vehicle_type_small_truck));
+ }
+
+ @Override
+ protected void makeFullUrl(@NonNull StringBuilder sb,
+ @NonNull List path) {
+ sb.append("?");
+ for (LatLon point : path) {
+ sb.append("point=")
+ .append(point.getLatitude())
+ .append(',')
+ .append(point.getLongitude())
+ .append('&');
+ }
+ String vehicle = get(EngineParameter.VEHICLE_KEY);
+ if (isEmpty(vehicle)) {
+ sb.append("vehicle=").append(vehicle);
+ }
+ String apiKey = get(EngineParameter.API_KEY);
+ if (isEmpty(apiKey)) {
+ sb.append('&').append("key=").append(apiKey);
+ }
+ }
+
+ @NonNull
+ @Override
+ public List parseServerResponse(@NonNull String content) throws JSONException {
+ JSONObject obj = new JSONObject(content);
+ return GeoPolylineParserUtil.parse(
+ obj.getJSONArray("paths").getJSONObject(0).getString("points"),
+ GeoPolylineParserUtil.PRECISION_5);
+ }
+
+ @Override
+ public boolean parseServerMessage(@NonNull StringBuilder sb,
+ @NonNull String content) throws JSONException {
+ JSONObject obj = new JSONObject(content);
+ if (obj.has("message")) {
+ String message = obj.getString("message");
+ sb.append(message);
+ }
+ return obj.has("paths");
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java
new file mode 100644
index 0000000000..e3f2d416ce
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java
@@ -0,0 +1,205 @@
+package net.osmand.plus.onlinerouting.engine;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.data.LatLon;
+import net.osmand.plus.R;
+import net.osmand.plus.onlinerouting.EngineParameter;
+import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
+import net.osmand.plus.onlinerouting.VehicleType;
+import net.osmand.util.Algorithms;
+
+import org.json.JSONException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static net.osmand.util.Algorithms.isEmpty;
+
+public abstract class OnlineRoutingEngine implements Cloneable {
+
+ public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
+ public static final VehicleType CUSTOM_VEHICLE = new VehicleType("", R.string.shared_string_custom);
+
+ private final Map params = new HashMap<>();
+ private final List allowedVehicles = new ArrayList<>();
+ private final Set allowedParameters = new HashSet<>();
+
+ public OnlineRoutingEngine(@Nullable Map params) {
+ if (!isEmpty(params)) {
+ this.params.putAll(params);
+ }
+ collectAllowedVehiclesInternal();
+ collectAllowedParametersInternal();
+ }
+
+ @NonNull
+ public abstract EngineType getType();
+
+ @Nullable
+ public String getStringKey() {
+ return get(EngineParameter.KEY);
+ }
+
+ @NonNull
+ public String getName(@NonNull Context ctx) {
+ String customName = get(EngineParameter.CUSTOM_NAME);
+ if (customName != null) {
+ return customName;
+ } else {
+ return getStandardName(ctx);
+ }
+ }
+
+ @NonNull
+ private String getStandardName(@NonNull Context ctx) {
+ String base = getBaseName(ctx);
+ String index = get(EngineParameter.NAME_INDEX);
+ return !isEmpty(index) ? base + " " + index : base;
+ }
+
+ @NonNull
+ public String getBaseName(@NonNull Context ctx) {
+ String vehicleTitle = getSelectedVehicleName(ctx);
+ if (isEmpty(vehicleTitle)) {
+ return getType().getTitle();
+ } else {
+ String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_dash);
+ return String.format(pattern, getType().getTitle(), vehicleTitle);
+ }
+ }
+
+ @NonNull
+ public String getBaseUrl() {
+ String customUrl = get(EngineParameter.CUSTOM_URL);
+ if (isEmpty(customUrl)) {
+ return getStandardUrl();
+ }
+ return customUrl;
+ }
+
+ @NonNull
+ public String getFullUrl(@NonNull List path) {
+ StringBuilder sb = new StringBuilder(getBaseUrl());
+ makeFullUrl(sb, path);
+ return sb.toString();
+ }
+
+ protected abstract void makeFullUrl(@NonNull StringBuilder sb,
+ @NonNull List path);
+
+ @NonNull
+ public abstract List parseServerResponse(@NonNull String content) throws JSONException;
+
+ @NonNull
+ public abstract String getStandardUrl();
+
+ @NonNull
+ public Map getParams() {
+ return params;
+ }
+
+ @Nullable
+ public String get(@NonNull EngineParameter key) {
+ return params.get(key.name());
+ }
+
+ public void put(@NonNull EngineParameter key, @NonNull String value) {
+ params.put(key.name(), value);
+ }
+
+ public void remove(@NonNull EngineParameter key) {
+ params.remove(key.name());
+ }
+
+ private void collectAllowedVehiclesInternal() {
+ allowedVehicles.clear();
+ collectAllowedVehicles(allowedVehicles);
+ allowedVehicles.add(CUSTOM_VEHICLE);
+ }
+
+ protected abstract void collectAllowedVehicles(@NonNull List vehicles);
+
+ @NonNull
+ public List getAllowedVehicles() {
+ return Collections.unmodifiableList(allowedVehicles);
+ }
+
+ private void collectAllowedParametersInternal() {
+ allowedParameters.clear();
+ allowParameters(EngineParameter.KEY, EngineParameter.VEHICLE_KEY,
+ EngineParameter.CUSTOM_NAME, EngineParameter.NAME_INDEX, EngineParameter.CUSTOM_URL);
+ collectAllowedParameters();
+ }
+
+ protected abstract void collectAllowedParameters();
+
+ public boolean isParameterAllowed(EngineParameter key) {
+ return allowedParameters.contains(key);
+ }
+
+ protected void allowParameters(@NonNull EngineParameter ... allowedParams) {
+ allowedParameters.addAll(Arrays.asList(allowedParams));
+ }
+
+ @Nullable
+ private String getSelectedVehicleName(@NonNull Context ctx) {
+ String key = get(EngineParameter.VEHICLE_KEY);
+ VehicleType vt = getVehicleTypeByKey(key);
+ if (!vt.equals(CUSTOM_VEHICLE)) {
+ return vt.getTitle(ctx);
+ }
+ return key != null ? Algorithms.capitalizeFirstLetter(key) : null;
+ }
+
+ @NonNull
+ public VehicleType getSelectedVehicleType() {
+ String key = get(EngineParameter.VEHICLE_KEY);
+ return getVehicleTypeByKey(key);
+ }
+
+ @NonNull
+ public VehicleType getVehicleTypeByKey(@Nullable String vehicleKey) {
+ if (!isEmpty(vehicleKey)) {
+ for (VehicleType vt : allowedVehicles) {
+ if (Algorithms.objectEquals(vt.getKey(), vehicleKey)) {
+ return vt;
+ }
+ }
+ }
+ return CUSTOM_VEHICLE;
+ }
+
+ public abstract boolean parseServerMessage(@NonNull StringBuilder sb,
+ @NonNull String content) throws JSONException;
+
+ @NonNull
+ @Override
+ public Object clone() {
+ return OnlineRoutingFactory.createEngine(getType(), getParams());
+ }
+
+ @NonNull
+ public static String generateKey() {
+ return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof OnlineRoutingEngine)) return false;
+
+ OnlineRoutingEngine engine = (OnlineRoutingEngine) o;
+ if (getType() != engine.getType()) return false;
+ return Algorithms.objectEquals(getParams(), engine.getParams());
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java
new file mode 100644
index 0000000000..594e7e1b36
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java
@@ -0,0 +1,104 @@
+package net.osmand.plus.onlinerouting.engine;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.data.LatLon;
+import net.osmand.plus.R;
+import net.osmand.plus.onlinerouting.EngineParameter;
+import net.osmand.plus.onlinerouting.VehicleType;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static net.osmand.util.Algorithms.isEmpty;
+
+public class OrsEngine extends OnlineRoutingEngine {
+
+ public OrsEngine(@Nullable Map params) {
+ super(params);
+ }
+
+ @Override
+ public @NonNull EngineType getType() {
+ return EngineType.ORS;
+ }
+
+ @NonNull
+ @Override
+ public String getStandardUrl() {
+ return "https://api.openrouteservice.org/v2/directions/";
+ }
+
+ @Override
+ protected void collectAllowedParameters() {
+ allowParameters(EngineParameter.API_KEY);
+ }
+
+ @Override
+ protected void collectAllowedVehicles(@NonNull List vehicles) {
+ vehicles.add(new VehicleType("driving-car", R.string.routing_engine_vehicle_type_car));
+ vehicles.add(new VehicleType("driving-hgv", R.string.routing_engine_vehicle_type_hgv));
+ vehicles.add(new VehicleType("cycling-regular", R.string.routing_engine_vehicle_type_cycling_regular));
+ vehicles.add(new VehicleType("cycling-road", R.string.routing_engine_vehicle_type_cycling_road));
+ vehicles.add(new VehicleType("cycling-mountain", R.string.routing_engine_vehicle_type_cycling_mountain));
+ vehicles.add(new VehicleType("cycling-electric", R.string.routing_engine_vehicle_type_cycling_electric));
+ vehicles.add(new VehicleType("foot-walking", R.string.routing_engine_vehicle_type_walking));
+ vehicles.add(new VehicleType("foot-hiking", R.string.routing_engine_vehicle_type_hiking));
+ vehicles.add(new VehicleType("wheelchair", R.string.routing_engine_vehicle_type_wheelchair));
+ }
+
+ @Override
+ protected void makeFullUrl(@NonNull StringBuilder sb,
+ @NonNull List path) {
+ if (path.size() > 1) {
+ String vehicleKey = get(EngineParameter.VEHICLE_KEY);
+ if (!isEmpty(vehicleKey)) {
+ sb.append(vehicleKey);
+ }
+ sb.append('?');
+ String apiKey = get(EngineParameter.API_KEY);
+ if (!isEmpty(apiKey)) {
+ sb.append("api_key=").append(apiKey);
+ }
+ LatLon start = path.get(0);
+ LatLon end = path.get(path.size() - 1);
+ sb.append('&').append("start=")
+ .append(start.getLatitude()).append(',').append(start.getLongitude());
+ sb.append('&').append("end=")
+ .append(end.getLatitude()).append(',').append(end.getLongitude());
+ }
+ }
+
+ @NonNull
+ @Override
+ public List parseServerResponse(@NonNull String content) throws JSONException {
+ JSONObject obj = new JSONObject(content);
+ JSONArray array = obj.getJSONArray("features").getJSONObject(0)
+ .getJSONObject("geometry").getJSONArray("coordinates");
+ List track = new ArrayList<>();
+ for (int i = 0; i < array.length(); i++) {
+ JSONArray point = array.getJSONArray(i);
+ double lat = Double.parseDouble(point.getString(0));
+ double lon = Double.parseDouble(point.getString(1));
+ track.add(new LatLon(lat, lon));
+ }
+ return track;
+ }
+
+ @Override
+ public boolean parseServerMessage(@NonNull StringBuilder sb,
+ @NonNull String content) throws JSONException {
+ JSONObject obj = new JSONObject(content);
+ if (obj.has("error")) {
+ String message = obj.getString("error");
+ sb.append(message);
+ }
+ return obj.has("features");
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java
new file mode 100644
index 0000000000..1ef9c1a622
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java
@@ -0,0 +1,84 @@
+package net.osmand.plus.onlinerouting.engine;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.data.LatLon;
+import net.osmand.plus.R;
+import net.osmand.plus.onlinerouting.EngineParameter;
+import net.osmand.plus.onlinerouting.VehicleType;
+import net.osmand.util.GeoPolylineParserUtil;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.List;
+import java.util.Map;
+
+import static net.osmand.util.Algorithms.isEmpty;
+
+public class OsrmEngine extends OnlineRoutingEngine {
+
+ public OsrmEngine(@Nullable Map params) {
+ super(params);
+ }
+
+ @Override
+ public @NonNull EngineType getType() {
+ return EngineType.OSRM;
+ }
+
+ @NonNull
+ @Override
+ public String getStandardUrl() {
+ return "https://router.project-osrm.org/route/v1/";
+ }
+
+ @Override
+ protected void collectAllowedParameters() { }
+
+ @Override
+ protected void collectAllowedVehicles(@NonNull List vehicles) {
+ vehicles.add(new VehicleType("car", R.string.routing_engine_vehicle_type_car));
+ vehicles.add(new VehicleType("bike", R.string.routing_engine_vehicle_type_bike));
+ vehicles.add(new VehicleType("foot", R.string.routing_engine_vehicle_type_foot));
+ }
+
+ @Override
+ protected void makeFullUrl(@NonNull StringBuilder sb,
+ @NonNull List path) {
+ String vehicleKey = get(EngineParameter.VEHICLE_KEY);
+ if (!isEmpty(vehicleKey)) {
+ sb.append(vehicleKey).append('/');
+ }
+ for (int i = 0; i < path.size(); i++) {
+ LatLon point = path.get(i);
+ sb.append(point.getLongitude()).append(',').append(point.getLatitude());
+ if (i < path.size() - 1) {
+ sb.append(';');
+ }
+ }
+ sb.append('?');
+ sb.append("overview=full");
+ }
+
+ @NonNull
+ @Override
+ public List parseServerResponse(@NonNull String content) throws JSONException {
+ JSONObject obj = new JSONObject(content);
+ return GeoPolylineParserUtil.parse(
+ obj.getJSONArray("routes").getJSONObject(0).getString("geometry"),
+ GeoPolylineParserUtil.PRECISION_5);
+ }
+
+ @Override
+ public boolean parseServerMessage(@NonNull StringBuilder sb,
+ @NonNull String content) throws JSONException {
+ JSONObject obj = new JSONObject(content);
+ if (obj.has("message")) {
+ String message = obj.getString("message");
+ sb.append(message);
+ }
+ return obj.has("routes");
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/ui/ExampleLocation.java b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/ExampleLocation.java
new file mode 100644
index 0000000000..0a384002f7
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/ExampleLocation.java
@@ -0,0 +1,52 @@
+package net.osmand.plus.onlinerouting.ui;
+
+import androidx.annotation.NonNull;
+
+import net.osmand.data.LatLon;
+
+public enum ExampleLocation {
+
+ AMSTERDAM("Amsterdam",
+ new LatLon(52.379189, 4.899431),
+ new LatLon(52.308056, 4.764167)),
+
+ BERLIN("Berlin",
+ new LatLon(52.520008, 13.404954),
+ new LatLon(52.3666652, 13.501997992)),
+
+ NEW_YORK("New York",
+ new LatLon(43.000000, -75.000000),
+ new LatLon(40.641766, -73.780968)),
+
+ PARIS("Paris",
+ new LatLon(48.864716, 2.349014),
+ new LatLon(48.948437, 2.434931));
+
+ ExampleLocation(@NonNull String name,
+ @NonNull LatLon cityCenterLatLon,
+ @NonNull LatLon cityAirportLatLon) {
+ this.name = name;
+ this.cityCenterLatLon = cityCenterLatLon;
+ this.cityAirportLatLon = cityAirportLatLon;
+ }
+
+ private String name;
+ private LatLon cityCenterLatLon;
+ private LatLon cityAirportLatLon;
+
+ @NonNull
+ public String getName() {
+ return name;
+ }
+
+ @NonNull
+ public LatLon getCityCenterLatLon() {
+ return cityCenterLatLon;
+ }
+
+ @NonNull
+ public LatLon getCityAirportLatLon() {
+ return cityAirportLatLon;
+ }
+
+}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingCard.java b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java
similarity index 82%
rename from OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingCard.java
rename to OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java
index 888216abb3..cb40a2a192 100644
--- a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingCard.java
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java
@@ -1,4 +1,4 @@
-package net.osmand.plus.onlinerouting;
+package net.osmand.plus.onlinerouting.ui;
import android.text.Editable;
import android.text.TextWatcher;
@@ -10,6 +10,7 @@ import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -42,9 +43,12 @@ public class OnlineRoutingCard extends BaseCard {
private OsmandTextFieldBoxes textFieldBoxes;
private EditText editText;
private TextView tvHelperText;
+ private TextView tvErrorText;
private View bottomDivider;
private View button;
private OnTextChangedListener onTextChangedListener;
+ private boolean fieldBoxHelperTextShowed;
+
private ApplicationMode appMode;
public OnlineRoutingCard(@NonNull MapActivity mapActivity, boolean nightMode, ApplicationMode appMode) {
@@ -69,6 +73,7 @@ public class OnlineRoutingCard extends BaseCard {
textFieldBoxes = view.findViewById(R.id.field_box);
editText = view.findViewById(R.id.edit_text);
tvHelperText = view.findViewById(R.id.helper_text);
+ tvErrorText = view.findViewById(R.id.error_text);
bottomDivider = view.findViewById(R.id.bottom_divider);
button = view.findViewById(R.id.button);
@@ -88,7 +93,7 @@ public class OnlineRoutingCard extends BaseCard {
public void afterTextChanged(Editable s) {
if (onTextChangedListener != null) {
boolean editedByUser = editText.getTag() == null;
- String text = editText.getText().toString();
+ String text = editText.getText().toString().trim();
onTextChangedListener.onTextChanged(editedByUser, text);
}
}
@@ -115,9 +120,9 @@ public class OnlineRoutingCard extends BaseCard {
tvHeaderSubtitle.setText(subtitle);
}
- public void setSelectionMenu(List items,
- String selectedItemTitle,
- final CallbackWithObject callback) {
+ public void setSelectionMenu(@NonNull List items,
+ @NonNull String selectedItemTitle,
+ @NonNull final CallbackWithObject callback) {
showElements(rvSelectionMenu);
rvSelectionMenu.setLayoutManager(
new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
@@ -152,15 +157,31 @@ public class OnlineRoutingCard extends BaseCard {
public void setFieldBoxHelperText(@NonNull String helperText) {
showElements(fieldBoxContainer, tvHelperText);
+ fieldBoxHelperTextShowed = true;
tvHelperText.setText(helperText);
}
+ public void showFieldBoxError(@NonNull String errorText) {
+ showElements(fieldBoxContainer, tvErrorText);
+ hideElements(tvHelperText);
+ tvErrorText.setText(errorText);
+ }
+
+ public void hideFieldBoxError() {
+ hideElements(tvErrorText);
+ if (fieldBoxHelperTextShowed) {
+ showElements(tvHelperText);
+ }
+ }
+
public void setEditedText(@NonNull String text) {
- editText.setTag(""); // needed to indicate that the text was edited programmatically
+ showElements(fieldBoxContainer);
+ editText.setTag(""); // indicate that the text was edited programmatically
editText.setText(text);
editText.setTag(null);
}
+ @NonNull
public String getEditedText() {
return editText.getText().toString();
}
@@ -169,7 +190,8 @@ public class OnlineRoutingCard extends BaseCard {
showElements(bottomDivider);
}
- public void setButton(String title, OnClickListener listener) {
+ public void setButton(@NonNull String title,
+ @NonNull OnClickListener listener) {
showElements(button);
button.setOnClickListener(listener);
UiUtilities.setupDialogButton(nightMode, button, DialogButtonType.PRIMARY, title);
@@ -199,11 +221,11 @@ public class OnlineRoutingCard extends BaseCard {
AndroidUiHelper.setVisibility(View.GONE, views);
}
- public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener) {
+ public void setOnTextChangedListener(@Nullable OnTextChangedListener onTextChangedListener) {
this.onTextChangedListener = onTextChangedListener;
}
public interface OnTextChangedListener {
- void onTextChanged(boolean editedByUser, String text);
+ void onTextChanged(boolean editedByUser, @NonNull String text);
}
}
diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngineFragment.java b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java
similarity index 58%
rename from OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngineFragment.java
rename to OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java
index 997b7fb34c..d362898275 100644
--- a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngineFragment.java
+++ b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java
@@ -1,4 +1,4 @@
-package net.osmand.plus.onlinerouting;
+package net.osmand.plus.onlinerouting.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -27,8 +27,6 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
-import net.osmand.AndroidNetworkUtils;
-import net.osmand.AndroidNetworkUtils.OnRequestResultListener;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
import net.osmand.data.LatLon;
@@ -39,39 +37,37 @@ import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
-import net.osmand.plus.onlinerouting.OnlineRoutingCard.OnTextChangedListener;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameter;
+import net.osmand.plus.onlinerouting.EngineParameter;
+import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
+import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
+import net.osmand.plus.onlinerouting.VehicleType;
+import net.osmand.plus.onlinerouting.ui.OnlineRoutingCard.OnTextChangedListener;
+import net.osmand.plus.onlinerouting.engine.EngineType;
+import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.util.Algorithms;
import org.json.JSONException;
-import org.json.JSONObject;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import static net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.CUSTOM_VEHICLE;
+
public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
public static final String TAG = OnlineRoutingEngineFragment.class.getSimpleName();
- private static final String ENGINE_NAME_KEY = "engine_name";
- private static final String ENGINE_SERVER_KEY = "engine_server";
- private static final String ENGINE_SERVER_URL_KEY = "engine_server_url";
- private static final String ENGINE_VEHICLE_TYPE_KEY = "engine_vehicle_type";
+ private static final String ENGINE_TYPE_KEY = "engine_type";
private static final String ENGINE_CUSTOM_VEHICLE_KEY = "engine_custom_vehicle";
- private static final String ENGINE_API_KEY_KEY = "engine_api_key";
- private static final String INIT_ENGINE_NAME_KEY = "init_engine_name";
- private static final String INIT_ENGINE_SERVER_KEY = "init_engine_server";
- private static final String INIT_ENGINE_SERVER_URL_KEY = "init_engine_server_url";
- private static final String INIT_ENGINE_VEHICLE_TYPE_KEY = "init_engine_vehicle_type";
- private static final String INIT_ENGINE_CUSTOM_VEHICLE_KEY = "init_engine_custom_vehicle";
- private static final String INIT_ENGINE_API_KEY_KEY = "init_engine_api_key";
private static final String EXAMPLE_LOCATION_KEY = "example_location";
private static final String APP_MODE_KEY = "app_mode";
private static final String EDITED_ENGINE_KEY = "edited_engine_key";
private OsmandApplication app;
+ private ApplicationMode appMode;
private MapActivity mapActivity;
private OnlineRoutingHelper helper;
@@ -83,66 +79,23 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
private OnlineRoutingCard apiKeyCard;
private OnlineRoutingCard exampleCard;
private View testResultsContainer;
+ private View saveButton;
private ScrollView scrollView;
private OnGlobalLayoutListener onGlobalLayout;
private boolean isKeyboardShown = false;
- private ApplicationMode appMode;
-
- private OnlineRoutingEngineObject engine;
- private OnlineRoutingEngineObject initEngine;
+ private OnlineRoutingEngine engine;
+ private OnlineRoutingEngine initEngine;
+ private String customVehicleKey;
private ExampleLocation selectedLocation;
private String editedEngineKey;
- private enum ExampleLocation {
-
- AMSTERDAM("Amsterdam",
- new LatLon(52.379189, 4.899431),
- new LatLon(52.308056, 4.764167)),
-
- BERLIN("Berlin",
- new LatLon(52.520008, 13.404954),
- new LatLon(52.3666652, 13.501997992)),
-
- NEW_YORK("New York",
- new LatLon(43.000000, -75.000000),
- new LatLon(40.641766, -73.780968)),
-
- PARIS("Paris",
- new LatLon(48.864716, 2.349014),
- new LatLon(48.948437, 2.434931));
-
- ExampleLocation(String name, LatLon cityCenterLatLon, LatLon cityAirportLatLon) {
- this.name = name;
- this.cityCenterLatLon = cityCenterLatLon;
- this.cityAirportLatLon = cityAirportLatLon;
- }
-
- private String name;
- private LatLon cityCenterLatLon;
- private LatLon cityAirportLatLon;
-
- public String getName() {
- return name;
- }
-
- public LatLon getCityCenterLatLon() {
- return cityCenterLatLon;
- }
-
- public LatLon getCityAirportLatLon() {
- return cityAirportLatLon;
- }
- }
-
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requireMyApplication();
mapActivity = getMapActivity();
helper = app.getOnlineRoutingHelper();
- engine = new OnlineRoutingEngineObject();
- initEngine = new OnlineRoutingEngineObject();
if (savedInstanceState != null) {
restoreState(savedInstanceState);
} else {
@@ -179,10 +132,9 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
setupApiKeyCard();
setupExampleCard();
setupResultsContainer();
- addSpaceSegment();
-
setupButtons();
+ generateUniqueNameIfNeeded();
updateCardViews(nameCard, typeCard, vehicleCard, exampleCard);
scrollView.setOnTouchListener(new View.OnTouchListener() {
@@ -250,13 +202,33 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
return view;
}
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayout);
+ private void setupToolbar(Toolbar toolbar) {
+ ImageView navigationIcon = toolbar.findViewById(R.id.close_button);
+ navigationIcon.setImageResource(R.drawable.ic_action_close);
+ navigationIcon.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showExitDialog();
+ }
+ });
+ TextView title = toolbar.findViewById(R.id.toolbar_title);
+ toolbar.findViewById(R.id.toolbar_subtitle).setVisibility(View.GONE);
+ View actionBtn = toolbar.findViewById(R.id.action_button);
+ if (isEditingMode()) {
+ title.setText(getString(R.string.edit_online_routing_engine));
+ ImageView ivBtn = toolbar.findViewById(R.id.action_button_icon);
+ ivBtn.setImageDrawable(
+ getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
+ actionBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onDeleteEngine();
+ dismiss();
+ }
+ });
} else {
- view.getViewTreeObserver().removeGlobalOnLayoutListener(onGlobalLayout);
+ title.setText(getString(R.string.add_online_routing_engine));
+ actionBtn.setVisibility(View.GONE);
}
}
@@ -268,9 +240,10 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
nameCard.setFieldBoxLabelText(getString(R.string.shared_string_name));
nameCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
- public void onTextChanged(boolean changedByUser, String text) {
+ public void onTextChanged(boolean changedByUser, @NonNull String text) {
if (changedByUser) {
- engine.customName = text;
+ engine.put(EngineParameter.CUSTOM_NAME, text);
+ checkCustomNameUnique(engine);
}
}
});
@@ -286,14 +259,13 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
for (EngineType server : EngineType.values()) {
serverItems.add(new HorizontalSelectionItem(server.getTitle(), server));
}
- typeCard.setSelectionMenu(serverItems, engine.type.getTitle(),
+ typeCard.setSelectionMenu(serverItems, engine.getType().getTitle(),
new CallbackWithObject() {
@Override
public boolean processResult(HorizontalSelectionItem result) {
EngineType type = (EngineType) result.getObject();
- if (engine.type != type) {
- engine.type = type;
- updateCardViews(nameCard, typeCard, exampleCard);
+ if (engine.getType() != type) {
+ changeEngineType(type);
return true;
}
return false;
@@ -301,9 +273,9 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
});
typeCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
- public void onTextChanged(boolean editedByUser, String text) {
+ public void onTextChanged(boolean editedByUser, @NonNull String text) {
if (editedByUser) {
- engine.customServerUrl = text;
+ engine.put(EngineParameter.CUSTOM_URL, text);
updateCardViews(exampleCard);
}
}
@@ -317,37 +289,44 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
vehicleCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
vehicleCard.build(mapActivity);
vehicleCard.setHeaderTitle(getString(R.string.shared_string_vehicle));
+ vehicleCard.setFieldBoxLabelText(getString(R.string.shared_string_custom));
+ vehicleCard.setOnTextChangedListener(new OnTextChangedListener() {
+ @Override
+ public void onTextChanged(boolean editedByUser, @NonNull String text) {
+ if (editedByUser) {
+ customVehicleKey = text;
+ engine.put(EngineParameter.VEHICLE_KEY, customVehicleKey);
+ updateCardViews(nameCard, exampleCard);
+ }
+ }
+ });
+ vehicleCard.setEditedText(customVehicleKey);
+ vehicleCard.setFieldBoxHelperText(getString(R.string.shared_string_enter_param));
+ vehicleCard.showDivider();
+ segmentsContainer.addView(vehicleCard.getView());
+ setupVehicleTypes();
+ }
+
+ private void setupVehicleTypes() {
List vehicleItems = new ArrayList<>();
- for (VehicleType vehicle : VehicleType.values()) {
+ for (VehicleType vehicle : engine.getAllowedVehicles()) {
vehicleItems.add(new HorizontalSelectionItem(vehicle.getTitle(app), vehicle));
}
- vehicleCard.setSelectionMenu(vehicleItems, engine.vehicleType.getTitle(app),
+ vehicleCard.setSelectionMenu(vehicleItems, engine.getSelectedVehicleType().getTitle(app),
new CallbackWithObject() {
@Override
public boolean processResult(HorizontalSelectionItem result) {
VehicleType vehicle = (VehicleType) result.getObject();
- if (engine.vehicleType != vehicle) {
- engine.vehicleType = vehicle;
+ if (!Algorithms.objectEquals(engine.getSelectedVehicleType(), vehicle)) {
+ String vehicleKey = vehicle.equals(CUSTOM_VEHICLE) ? customVehicleKey : vehicle.getKey();
+ engine.put(EngineParameter.VEHICLE_KEY, vehicleKey);
+ generateUniqueNameIfNeeded();
updateCardViews(nameCard, vehicleCard, exampleCard);
return true;
}
return false;
}
});
- vehicleCard.setFieldBoxLabelText(getString(R.string.shared_string_custom));
- vehicleCard.setOnTextChangedListener(new OnTextChangedListener() {
- @Override
- public void onTextChanged(boolean editedByUser, String text) {
- if (editedByUser) {
- engine.customVehicleKey = text;
- updateCardViews(nameCard, exampleCard);
- }
- }
- });
- vehicleCard.setEditedText(engine.customVehicleKey);
- vehicleCard.setFieldBoxHelperText(getString(R.string.shared_string_enter_param));
- vehicleCard.showDivider();
- segmentsContainer.addView(vehicleCard.getView());
}
private void setupApiKeyCard() {
@@ -355,12 +334,15 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
apiKeyCard.build(mapActivity);
apiKeyCard.setHeaderTitle(getString(R.string.shared_string_api_key));
apiKeyCard.setFieldBoxLabelText(getString(R.string.keep_it_empty_if_not));
- apiKeyCard.setEditedText(engine.apiKey);
+ String apiKey = engine.get(EngineParameter.API_KEY);
+ if (apiKey != null) {
+ apiKeyCard.setEditedText(apiKey);
+ }
apiKeyCard.showDivider();
apiKeyCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
- public void onTextChanged(boolean editedByUser, String text) {
- engine.apiKey = text;
+ public void onTextChanged(boolean editedByUser, @NonNull String text) {
+ engine.put(EngineParameter.API_KEY, text);
updateCardViews(exampleCard);
}
});
@@ -402,87 +384,10 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
private void setupResultsContainer() {
testResultsContainer = getInflater().inflate(
R.layout.bottom_sheet_item_with_descr_64dp, segmentsContainer, false);
- testResultsContainer.setVisibility(View.GONE);
+ testResultsContainer.setVisibility(View.INVISIBLE);
segmentsContainer.addView(testResultsContainer);
}
- private void addSpaceSegment() {
- int space = (int) getResources().getDimension(R.dimen.empty_state_text_button_padding_top);
- View bottomSpaceView = new View(app);
- bottomSpaceView.setLayoutParams(
- new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, space));
- segmentsContainer.addView(bottomSpaceView);
- }
-
- private void setupToolbar(Toolbar toolbar) {
- ImageView navigationIcon = toolbar.findViewById(R.id.close_button);
- navigationIcon.setImageResource(R.drawable.ic_action_close);
- navigationIcon.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- showExitDialog();
- }
- });
- TextView title = toolbar.findViewById(R.id.toolbar_title);
- toolbar.findViewById(R.id.toolbar_subtitle).setVisibility(View.GONE);
- View actionBtn = toolbar.findViewById(R.id.action_button);
- if (isEditingMode()) {
- title.setText(getString(R.string.edit_online_routing_engine));
- ImageView ivBtn = toolbar.findViewById(R.id.action_button_icon);
- ivBtn.setImageDrawable(
- getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
- actionBtn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- deleteEngine();
- dismiss();
- }
- });
- } else {
- title.setText(getString(R.string.add_online_routing_engine));
- actionBtn.setVisibility(View.GONE);
- }
- }
-
- private void updateCardViews(BaseCard... cardsToUpdate) {
- for (BaseCard card : cardsToUpdate) {
- if (nameCard.equals(card)) {
- if (Algorithms.isEmpty(engine.customName)) {
- String name;
- if (Algorithms.isEmpty(engine.getVehicleKey())) {
- name = engine.type.getTitle();
- } else {
- name = OnlineRoutingEngine.getStandardName(app, engine.type, engine.getVehicleKey());
- }
- nameCard.setEditedText(name);
- }
-
- } else if (typeCard.equals(card)) {
- typeCard.setHeaderSubtitle(engine.type.getTitle());
- typeCard.setEditedText(engine.getBaseUrl());
- if (engine.type == EngineType.GRAPHHOPPER || engine.type == EngineType.ORS) {
- apiKeyCard.show();
- } else {
- apiKeyCard.hide();
- }
-
- } else if (vehicleCard.equals(card)) {
- VehicleType vt = VehicleType.getVehicleByKey(engine.getVehicleKey());
- vehicleCard.setHeaderSubtitle(vt.getTitle(app));
- if (vt == VehicleType.CUSTOM) {
- vehicleCard.showFieldBox();
- vehicleCard.setEditedText(engine.getVehicleKey());
- } else {
- vehicleCard.hideFieldBox();
- }
- int contentPadding = getResources().getDimensionPixelSize(R.dimen.content_padding);
- vehicleCard.updateBottomMarginSelectionMenu(engine.vehicleType != VehicleType.CUSTOM ? 0 : contentPadding);
- } else if (exampleCard.equals(card)) {
- exampleCard.setEditedText(getTestUrl());
- }
- }
- }
-
private void setupButtons() {
boolean nightMode = isNightMode();
View cancelButton = view.findViewById(R.id.dismiss_button);
@@ -497,172 +402,167 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
view.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
- View saveButton = view.findViewById(R.id.right_bottom_button);
+ saveButton = view.findViewById(R.id.right_bottom_button);
UiUtilities.setupDialogButton(nightMode, saveButton,
UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_save);
saveButton.setVisibility(View.VISIBLE);
saveButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- saveChanges();
+ onSaveEngine();
dismiss();
}
});
}
- private void saveChanges() {
- OnlineRoutingEngine engineToSave;
- if (isEditingMode()) {
- engineToSave = new OnlineRoutingEngine(editedEngineKey, engine.type, engine.getVehicleKey());
+ private void changeEngineType(EngineType type) {
+ OnlineRoutingEngine tmp = (OnlineRoutingEngine) engine.clone();
+ engine = OnlineRoutingFactory.createEngine(type, tmp.getParams());
+
+ // after changing the type, select the vehicle
+ // with the same name that was selected before
+ VehicleType previous = tmp.getSelectedVehicleType();
+ VehicleType next = null;
+ for (VehicleType vt : engine.getAllowedVehicles()) {
+ if (Algorithms.objectEquals(previous.getTitle(app), vt.getTitle(app))) {
+ next = vt;
+ break;
+ }
+ }
+ String vehicleKey;
+ if (next != null) {
+ vehicleKey = next.equals(CUSTOM_VEHICLE) ? customVehicleKey : next.getKey();
} else {
- engineToSave = OnlineRoutingEngine.createNewEngine(engine.type, engine.getVehicleKey(), null);
+ vehicleKey = engine.getAllowedVehicles().get(0).getKey();
}
+ engine.put(EngineParameter.VEHICLE_KEY, vehicleKey);
- engineToSave.putParameter(EngineParameter.CUSTOM_NAME, engine.customName);
- engineToSave.putParameter(EngineParameter.CUSTOM_URL, engine.customServerUrl);
- if (engine.type == EngineType.GRAPHHOPPER || engine.type == EngineType.ORS) {
- engineToSave.putParameter(EngineParameter.API_KEY, engine.apiKey);
+ setupVehicleTypes();
+ generateUniqueNameIfNeeded();
+ updateCardViews(nameCard, typeCard, vehicleCard, exampleCard);
+ }
+
+ private void generateUniqueNameIfNeeded() {
+ if (engine.get(EngineParameter.CUSTOM_NAME) == null) {
+ engine.remove(EngineParameter.NAME_INDEX);
+ if (hasNameDuplicate(engine.getName(app))) {
+ int index = 0;
+ do {
+ engine.put(EngineParameter.NAME_INDEX, String.valueOf(++index));
+ } while (hasNameDuplicate(engine.getName(app)));
+ }
}
-
- helper.saveEngine(engineToSave);
}
- private void deleteEngine() {
- helper.deleteEngine(editedEngineKey);
- }
-
- private String getTestUrl() {
- List path = new ArrayList<>();
- path.add(selectedLocation.getCityCenterLatLon());
- path.add(selectedLocation.getCityAirportLatLon());
- OnlineRoutingEngine tmpEngine =
- OnlineRoutingEngine.createNewEngine(engine.type, engine.getVehicleKey(), null);
- tmpEngine.putParameter(EngineParameter.CUSTOM_URL, engine.customServerUrl);
- tmpEngine.putParameter(EngineParameter.API_KEY, engine.apiKey);
- return helper.createFullUrl(tmpEngine, path);
- }
-
- private void testEngineWork() {
- final EngineType type = engine.type;
- final ExampleLocation location = selectedLocation;
- AndroidNetworkUtils.sendRequestAsync(app, exampleCard.getEditedText(), null,
- null, false, false, new OnRequestResultListener() {
- @Override
- public void onResult(String response) {
- boolean resultOk = false;
- if (response != null) {
- try {
- JSONObject obj = new JSONObject(response);
-
- if (type == EngineType.GRAPHHOPPER) {
- resultOk = obj.has("paths");
- } else if (type == EngineType.OSRM) {
- resultOk = obj.has("routes");
- } else if (type == EngineType.ORS) {
- resultOk = obj.has("features");
- }
- } catch (JSONException e) {
-
- }
- }
- showTestResults(resultOk, location);
- }
- });
- }
-
- private void showTestResults(boolean resultOk, ExampleLocation location) {
- testResultsContainer.setVisibility(View.VISIBLE);
- ImageView ivImage = testResultsContainer.findViewById(R.id.icon);
- TextView tvTitle = testResultsContainer.findViewById(R.id.title);
- TextView tvDescription = testResultsContainer.findViewById(R.id.description);
- if (resultOk) {
- ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_gdirections_dark));
- tvTitle.setText(getString(R.string.shared_string_ok));
+ private void checkCustomNameUnique(@NonNull OnlineRoutingEngine engine) {
+ if (hasNameDuplicate(engine.getName(app))) {
+ nameCard.showFieldBoxError(getString(R.string.message_name_is_already_exists));
+ saveButton.setEnabled(false);
} else {
- ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_alert));
- tvTitle.setText(getString(R.string.message_error_recheck_parameters));
+ nameCard.hideFieldBoxError();
+ saveButton.setEnabled(true);
}
- tvDescription.setText(location.getName());
+ }
+
+ private boolean hasNameDuplicate(@NonNull String name) {
+ for (OnlineRoutingEngine engine : helper.getEnginesExceptMentioned(editedEngineKey)) {
+ if (Algorithms.objectEquals(engine.getName(app), name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void onSaveEngine() {
+ if (engine != null) {
+ helper.saveEngine(engine);
+ }
+ }
+
+ private void onDeleteEngine() {
+ helper.deleteEngine(engine);
}
private boolean isEditingMode() {
return editedEngineKey != null;
}
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
- saveState(outState);
+ private String getTestUrl() {
+ List path = new ArrayList<>();
+ path.add(selectedLocation.getCityCenterLatLon());
+ path.add(selectedLocation.getCityAirportLatLon());
+ return engine.getFullUrl(path);
}
- private void saveState(Bundle outState) {
- outState.putString(ENGINE_NAME_KEY, engine.customName);
- outState.putString(ENGINE_SERVER_KEY, engine.type.name());
- outState.putString(ENGINE_SERVER_URL_KEY, engine.customServerUrl);
- outState.putString(ENGINE_VEHICLE_TYPE_KEY, engine.vehicleType.name());
- outState.putString(ENGINE_CUSTOM_VEHICLE_KEY, engine.customVehicleKey);
- outState.putString(ENGINE_API_KEY_KEY, engine.apiKey);
- outState.putString(INIT_ENGINE_NAME_KEY, initEngine.customName);
- outState.putString(INIT_ENGINE_SERVER_KEY, initEngine.type.name());
- outState.putString(INIT_ENGINE_SERVER_URL_KEY, initEngine.customServerUrl);
- outState.putString(INIT_ENGINE_VEHICLE_TYPE_KEY, initEngine.vehicleType.name());
- outState.putString(INIT_ENGINE_CUSTOM_VEHICLE_KEY, initEngine.customVehicleKey);
- outState.putString(INIT_ENGINE_API_KEY_KEY, initEngine.apiKey);
- outState.putString(EXAMPLE_LOCATION_KEY, selectedLocation.name());
- if (appMode != null) {
- outState.putString(APP_MODE_KEY, appMode.getStringKey());
- }
- outState.putString(EDITED_ENGINE_KEY, editedEngineKey);
- }
-
- private void restoreState(Bundle savedState) {
- engine.customName = savedState.getString(ENGINE_NAME_KEY);
- engine.type = EngineType.valueOf(savedState.getString(ENGINE_SERVER_KEY));
- engine.customServerUrl = savedState.getString(ENGINE_SERVER_URL_KEY);
- engine.vehicleType = VehicleType.valueOf(savedState.getString(ENGINE_VEHICLE_TYPE_KEY));
- engine.customVehicleKey = savedState.getString(ENGINE_CUSTOM_VEHICLE_KEY);
- engine.apiKey = savedState.getString(ENGINE_API_KEY_KEY);
- initEngine.customName = savedState.getString(INIT_ENGINE_NAME_KEY);
- initEngine.type = EngineType.valueOf(savedState.getString(INIT_ENGINE_SERVER_KEY));
- initEngine.customServerUrl = savedState.getString(INIT_ENGINE_SERVER_URL_KEY);
- initEngine.vehicleType = VehicleType.valueOf(savedState.getString(INIT_ENGINE_VEHICLE_TYPE_KEY));
- initEngine.customVehicleKey = savedState.getString(INIT_ENGINE_CUSTOM_VEHICLE_KEY);
- initEngine.apiKey = savedState.getString(INIT_ENGINE_API_KEY_KEY);
- selectedLocation = ExampleLocation.valueOf(savedState.getString(EXAMPLE_LOCATION_KEY));
- appMode = ApplicationMode.valueOfStringKey(savedState.getString(APP_MODE_KEY), null);
- editedEngineKey = savedState.getString(EDITED_ENGINE_KEY);
- }
-
- private void initState() {
- engine.type = EngineType.values()[0];
- engine.vehicleType = VehicleType.values()[0];
- selectedLocation = ExampleLocation.values()[0];
-
- if (isEditingMode()) {
- OnlineRoutingEngine editedEngine = helper.getEngineByKey(editedEngineKey);
- if (editedEngine != null) {
- engine.customName = editedEngine.getParameter(EngineParameter.CUSTOM_NAME);
- engine.type = editedEngine.getType();
- String vehicleKey = editedEngine.getVehicleKey();
- if (vehicleKey != null) {
- VehicleType vehicleType = VehicleType.getVehicleByKey(vehicleKey);
- if (vehicleType == VehicleType.CUSTOM) {
- engine.customVehicleKey = vehicleKey;
- }
- engine.vehicleType = vehicleType;
+ private void testEngineWork() {
+ final OnlineRoutingEngine requestedEngine = (OnlineRoutingEngine) engine.clone();
+ final ExampleLocation location = selectedLocation;
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ StringBuilder message = new StringBuilder();
+ boolean resultOk = false;
+ try {
+ String response = helper.makeRequest(exampleCard.getEditedText());
+ resultOk = requestedEngine.parseServerMessage(message, response);
+ } catch (IOException | JSONException e) {
+ message.append(e.toString());
}
- engine.apiKey = editedEngine.getParameter(EngineParameter.API_KEY);
+ showTestResults(resultOk, message.toString(), location);
}
- }
- engine.cloneIn(initEngine);
+ }).start();
}
- private void dismiss() {
- FragmentActivity activity = getActivity();
- if (activity != null) {
- FragmentManager fragmentManager = activity.getSupportFragmentManager();
- if (!fragmentManager.isStateSaved()) {
- fragmentManager.popBackStack();
+ private void showTestResults(final boolean resultOk,
+ final @NonNull String message,
+ final @NonNull ExampleLocation location) {
+ app.runInUIThread(new Runnable() {
+ @Override
+ public void run() {
+ testResultsContainer.setVisibility(View.VISIBLE);
+ ImageView ivImage = testResultsContainer.findViewById(R.id.icon);
+ TextView tvTitle = testResultsContainer.findViewById(R.id.title);
+ TextView tvDescription = testResultsContainer.findViewById(R.id.description);
+ if (resultOk) {
+ ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_gdirections_dark));
+ tvTitle.setText(getString(R.string.shared_string_ok));
+ } else {
+ ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_alert));
+ tvTitle.setText(String.format(getString(R.string.message_server_error), message));
+ }
+ tvDescription.setText(location.getName());
+ }
+ });
+ }
+
+ private void updateCardViews(@NonNull BaseCard... cardsToUpdate) {
+ for (BaseCard card : cardsToUpdate) {
+ if (nameCard.equals(card)) {
+ if (Algorithms.isEmpty(engine.get(EngineParameter.CUSTOM_NAME))) {
+ nameCard.setEditedText(engine.getName(app));
+ }
+
+ } else if (typeCard.equals(card)) {
+ typeCard.setHeaderSubtitle(engine.getType().getTitle());
+ typeCard.setEditedText(engine.getBaseUrl());
+ if (engine.isParameterAllowed(EngineParameter.API_KEY)) {
+ apiKeyCard.show();
+ } else {
+ apiKeyCard.hide();
+ }
+
+ } else if (vehicleCard.equals(card)) {
+ VehicleType vt = engine.getSelectedVehicleType();
+ vehicleCard.setHeaderSubtitle(vt.getTitle(app));
+ if (vt.equals(CUSTOM_VEHICLE)) {
+ vehicleCard.showFieldBox();
+ vehicleCard.setEditedText(customVehicleKey);
+ } else {
+ vehicleCard.hideFieldBox();
+ }
+
+ } else if (exampleCard.equals(card)) {
+ exampleCard.setEditedText(getTestUrl());
}
}
}
@@ -670,9 +570,6 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
public void showExitDialog() {
View focus = view.findFocus();
AndroidUtils.hideSoftKeyboard(mapActivity, focus);
- if (engine.customName != null && initEngine.customName == null) {
- initEngine.customName = initEngine.getName(app);
- }
if (!engine.equals(initEngine)) {
AlertDialog.Builder dismissDialog = createWarningDialog(mapActivity,
R.string.shared_string_dismiss, R.string.exit_without_saving, R.string.shared_string_cancel);
@@ -697,8 +594,23 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
return warningDialog;
}
+ private void dismiss() {
+ FragmentActivity activity = getActivity();
+ if (activity != null) {
+ FragmentManager fragmentManager = activity.getSupportFragmentManager();
+ if (!fragmentManager.isStateSaved()) {
+ fragmentManager.popBackStack();
+ }
+ }
+ }
+
private boolean isNightMode() {
- return !app.getSettings().isLightContentForMode(appMode);
+ return !app.getSettings().isLightContentForMode(getAppMode());
+ }
+
+ @NonNull
+ private ApplicationMode getAppMode() {
+ return appMode != null ? appMode : app.getSettings().getApplicationMode();
}
@Nullable
@@ -715,9 +627,83 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
return UiUtilities.getInflater(mapActivity, isNightMode());
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ view.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayout);
+ } else {
+ view.getViewTreeObserver().removeGlobalOnLayoutListener(onGlobalLayout);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ saveState(outState);
+ }
+
+ private void saveState(@NonNull Bundle outState) {
+ outState.putString(ENGINE_TYPE_KEY, engine.getType().name());
+ for (EngineParameter key : EngineParameter.values()) {
+ String value = engine.get(key);
+ if (value != null) {
+ outState.putString(key.name(), value);
+ }
+ }
+ outState.putString(ENGINE_CUSTOM_VEHICLE_KEY, customVehicleKey);
+ outState.putString(EXAMPLE_LOCATION_KEY, selectedLocation.name());
+ outState.putString(APP_MODE_KEY, getAppMode().getStringKey());
+ outState.putString(EDITED_ENGINE_KEY, editedEngineKey);
+ }
+
+ private void restoreState(@NonNull Bundle savedState) {
+ initEngine = createInitStateEngine();
+ String typeKey = savedState.getString(ENGINE_TYPE_KEY);
+ EngineType type = EngineType.getTypeByName(typeKey);
+ engine = OnlineRoutingFactory.createEngine(type);
+ for (EngineParameter key : EngineParameter.values()) {
+ String value = savedState.getString(key.name());
+ if (value != null) {
+ engine.put(key, value);
+ }
+ }
+ customVehicleKey = savedState.getString(ENGINE_CUSTOM_VEHICLE_KEY);
+ selectedLocation = ExampleLocation.valueOf(savedState.getString(EXAMPLE_LOCATION_KEY));
+ appMode = ApplicationMode.valueOfStringKey(savedState.getString(APP_MODE_KEY), null);
+ editedEngineKey = savedState.getString(EngineParameter.KEY.name());
+ }
+
+ private void initState() {
+ initEngine = createInitStateEngine();
+ selectedLocation = ExampleLocation.values()[0];
+ engine = (OnlineRoutingEngine) initEngine.clone();
+ if (Algorithms.objectEquals(engine.getSelectedVehicleType(), CUSTOM_VEHICLE)) {
+ customVehicleKey = engine.get(EngineParameter.VEHICLE_KEY);
+ } else {
+ customVehicleKey = "";
+ }
+ }
+
+ private OnlineRoutingEngine createInitStateEngine() {
+ OnlineRoutingEngine engine;
+ OnlineRoutingEngine editedEngine = helper.getEngineByKey(editedEngineKey);
+ if (editedEngine != null) {
+ engine = (OnlineRoutingEngine) editedEngine.clone();
+ } else {
+ engine = OnlineRoutingFactory.createEngine(EngineType.values()[0]);
+ String vehicle = engine.getAllowedVehicles().get(0).getKey();
+ engine.put(EngineParameter.VEHICLE_KEY, vehicle);
+ if (editedEngineKey != null) {
+ engine.put(EngineParameter.KEY, editedEngineKey);
+ }
+ }
+ return engine;
+ }
+
public static void showInstance(@NonNull FragmentActivity activity,
- @NonNull ApplicationMode appMode,
- String editedEngineKey) {
+ @NonNull ApplicationMode appMode,
+ @Nullable String editedEngineKey) {
FragmentManager fm = activity.getSupportFragmentManager();
if (!fm.isStateSaved() && fm.findFragmentByTag(OnlineRoutingEngineFragment.TAG) == null) {
OnlineRoutingEngineFragment fragment = new OnlineRoutingEngineFragment();
@@ -728,57 +714,4 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
.addToBackStack(TAG).commitAllowingStateLoss();
}
}
-
- private static class OnlineRoutingEngineObject {
- private String customName;
- private EngineType type;
- private String customServerUrl;
- private VehicleType vehicleType;
- private String customVehicleKey;
- private String apiKey;
-
- public String getVehicleKey() {
- if (vehicleType == VehicleType.CUSTOM) {
- return customVehicleKey;
- }
- return vehicleType.getKey();
- }
-
- public String getName(Context ctx) {
- if (customName != null) {
- return customName;
- }
- return OnlineRoutingEngine.getStandardName(ctx, type, getVehicleKey());
- }
-
- public String getBaseUrl() {
- if (Algorithms.isEmpty(customServerUrl)) {
- return type.getStandardUrl();
- }
- return customServerUrl;
- }
-
- public void cloneIn(OnlineRoutingEngineObject clone) {
- clone.customName = customName;
- clone.type = type;
- clone.customServerUrl = customServerUrl;
- clone.vehicleType = vehicleType;
- clone.customVehicleKey = customVehicleKey;
- clone.apiKey = apiKey;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null || getClass() != obj.getClass()) return false;
-
- OnlineRoutingEngineObject engine = (OnlineRoutingEngineObject) obj;
- if (!Algorithms.stringsEqual(customName, engine.customName)) return false;
- if (type != engine.type) return false;
- if (!Algorithms.stringsEqual(getBaseUrl(), engine.getBaseUrl())) return false;
- if (vehicleType != engine.vehicleType) return false;
- if (!Algorithms.stringsEqual(getVehicleKey(), engine.getVehicleKey())) return false;
- return Algorithms.isEmpty(apiKey) ? Algorithms.isEmpty(engine.apiKey) : Algorithms.stringsEqual(apiKey, engine.apiKey);
- }
- }
}
diff --git a/OsmAnd/src/net/osmand/plus/profiles/OnlineRoutingEngineDataObject.java b/OsmAnd/src/net/osmand/plus/profiles/OnlineRoutingEngineDataObject.java
index 46a35ea67e..fd0f593462 100644
--- a/OsmAnd/src/net/osmand/plus/profiles/OnlineRoutingEngineDataObject.java
+++ b/OsmAnd/src/net/osmand/plus/profiles/OnlineRoutingEngineDataObject.java
@@ -1,12 +1,27 @@
package net.osmand.plus.profiles;
+import androidx.annotation.NonNull;
+
import net.osmand.plus.R;
public class OnlineRoutingEngineDataObject extends ProfileDataObject {
+ private int order;
+
public OnlineRoutingEngineDataObject(String name,
String description,
- String stringKey) {
+ String stringKey,
+ int order) {
super(name, description, stringKey, R.drawable.ic_world_globe_dark, false, null);
+ this.order = order;
+ }
+
+ @Override
+ public int compareTo(@NonNull ProfileDataObject profileDataObject) {
+ if (profileDataObject instanceof OnlineRoutingEngineDataObject) {
+ OnlineRoutingEngineDataObject another = (OnlineRoutingEngineDataObject) profileDataObject;
+ return (this.order < another.order) ? -1 : ((this.order == another.order) ? 0 : 1);
+ }
+ return 0;
}
}
diff --git a/OsmAnd/src/net/osmand/plus/profiles/ProfileDataUtils.java b/OsmAnd/src/net/osmand/plus/profiles/ProfileDataUtils.java
index 28967ba2f3..6306dee9cc 100644
--- a/OsmAnd/src/net/osmand/plus/profiles/ProfileDataUtils.java
+++ b/OsmAnd/src/net/osmand/plus/profiles/ProfileDataUtils.java
@@ -5,7 +5,7 @@ import android.content.Context;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
+import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.GeneralRouter;
@@ -56,7 +56,22 @@ public class ProfileDataUtils {
Collections.sort(fileNames, new Comparator() {
@Override
public int compare(String s, String t1) {
- return s.equals(OSMAND_NAVIGATION) ? -1 : t1.equals(OSMAND_NAVIGATION) ? 1 : s.compareToIgnoreCase(t1);
+ // OsmAnd navigation should be at the top of the list
+ if (s.equals(OSMAND_NAVIGATION)) {
+ return -1;
+ } else if (t1.equals(OSMAND_NAVIGATION)) {
+ return 1;
+
+ // Online navigation should be at the bottom of the list
+ } else if (s.equals(ONLINE_NAVIGATION)) {
+ return 1;
+ } else if (t1.equals(ONLINE_NAVIGATION)) {
+ return -1;
+
+ // Other sorted by file names
+ } else {
+ return s.compareToIgnoreCase(t1);
+ }
}
});
for (String fileName : fileNames) {
@@ -71,9 +86,11 @@ public class ProfileDataUtils {
public static List getOnlineRoutingProfiles(OsmandApplication app) {
List objects = new ArrayList<>();
- for (OnlineRoutingEngine engine : app.getOnlineRoutingHelper().getEngines()) {
+ List engines = app.getOnlineRoutingHelper().getEngines();
+ for (int i = 0; i < engines.size(); i++) {
+ OnlineRoutingEngine engine = engines.get(i);
objects.add(new OnlineRoutingEngineDataObject(
- engine.getName(app), engine.getBaseUrl(), engine.getStringKey()));
+ engine.getName(app), engine.getBaseUrl(), engine.getStringKey(), i));
}
return objects;
}
diff --git a/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheet.java
index 98ca4771cc..eb97a8ae85 100644
--- a/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheet.java
+++ b/OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheet.java
@@ -39,8 +39,9 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngineFragment;
+import net.osmand.plus.onlinerouting.ui.OnlineRoutingEngineFragment;
import net.osmand.router.RoutingConfiguration;
+import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@@ -250,7 +251,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
tvTitle.setText(profile.getName());
tvDescription.setText(profile.getDescription());
- boolean isSelected = setupSelected && profile.getStringKey().equals(selectedItemKey);
+ boolean isSelected = setupSelected && Algorithms.objectEquals(profile.getStringKey(), selectedItemKey);
int iconColor;
if (dialogMode == DialogMode.NAVIGATION_PROFILE) {
iconColor = isSelected ? activeColorResId : iconDefaultColorResId;
diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java
index 89c17f1c2b..96017bc96c 100644
--- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java
+++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java
@@ -2,7 +2,6 @@ package net.osmand.plus.routing;
import android.content.Context;
-import android.os.Build;
import android.os.Bundle;
import android.util.Base64;
@@ -20,16 +19,14 @@ import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.LatLon;
import net.osmand.data.LocationPoint;
import net.osmand.data.WptLocationPoint;
-import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
+import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
-import net.osmand.plus.Version;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.GeneralRouter;
@@ -48,21 +45,16 @@ import net.osmand.router.RoutingConfiguration.Builder;
import net.osmand.router.RoutingContext;
import net.osmand.router.TurnType;
import net.osmand.util.Algorithms;
-import net.osmand.util.GeoPolylineParserUtil;
import net.osmand.util.MapUtils;
import org.json.JSONException;
-import org.json.JSONObject;
import org.xml.sax.SAXException;
-import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.net.MalformedURLException;
-import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -1210,8 +1202,12 @@ public class RouteProvider {
private RouteCalculationResult findOnlineRoute(RouteCalculationParams params) throws IOException, JSONException {
OnlineRoutingHelper helper = params.ctx.getOnlineRoutingHelper();
String stringKey = params.mode.getRoutingProfile();
- List route = helper.calculateRouteOnline(helper.getEngineByKey(stringKey), getFullPathFromParams(params));
- if (!route.isEmpty()) {
+ OnlineRoutingEngine engine = helper.getEngineByKey(stringKey);
+ List route = null;
+ if (engine != null) {
+ route = helper.calculateRouteOnline(engine, getFullPathFromParams(params));
+ }
+ if (!Algorithms.isEmpty(route)) {
List res = new ArrayList<>();
for (LatLon pt : route) {
WptPt wpt = new WptPt();
diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/OnlineRoutingSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/OnlineRoutingSettingsItem.java
index 779a97d1df..cf08142393 100644
--- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/OnlineRoutingSettingsItem.java
+++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/OnlineRoutingSettingsItem.java
@@ -7,8 +7,9 @@ import androidx.annotation.Nullable;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
-import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameter;
+import net.osmand.plus.onlinerouting.EngineParameter;
+import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
+import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import org.json.JSONException;
@@ -93,8 +94,8 @@ public class OnlineRoutingSettingsItem extends CollectionSettingsItem