Merge pull request #10435 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2020-12-18 21:43:05 +01:00 committed by GitHub
commit 48148676cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 1240 additions and 273 deletions

View file

@ -92,6 +92,9 @@ import net.osmand.aidlapi.copyfile.CopyFileParams;
import net.osmand.aidlapi.navigation.ANavigationUpdateParams;
import net.osmand.aidlapi.navigation.ANavigationVoiceRouterMessageParams;
import net.osmand.aidlapi.navigation.ABlockedRoad;
import net.osmand.aidlapi.navigation.AddBlockedRoadParams;
import net.osmand.aidlapi.navigation.RemoveBlockedRoadParams;
import net.osmand.aidlapi.contextmenu.ContextMenuButtonsParams;
import net.osmand.aidlapi.contextmenu.UpdateContextMenuButtonsParams;
@ -892,4 +895,10 @@ interface IOsmAndAidlInterface {
boolean selectProfile(in SelectProfileParams params);
boolean getProfiles(out List<AProfile> profiles);
boolean getBlockedRoads(out List<ABlockedRoad> blockedRoads);
boolean addRoadBlock(in AddBlockedRoadParams params);
boolean removeRoadBlock(in RemoveBlockedRoadParams params);
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidlapi.navigation;
parcelable ABlockedRoad;

View file

@ -0,0 +1,85 @@
package net.osmand.aidlapi.navigation;
import android.os.Bundle;
import android.os.Parcel;
import net.osmand.aidlapi.AidlParams;
public class ABlockedRoad extends AidlParams {
private long roadId;
private double latitude;
private double longitude;
private double direction;
private String name;
private String appModeKey;
public ABlockedRoad(long roadId, double latitude, double longitude, double direction, String name, String appModeKey) {
this.roadId = roadId;
this.latitude = latitude;
this.longitude = longitude;
this.direction = direction;
this.name = name;
this.appModeKey = appModeKey;
}
protected ABlockedRoad(Parcel in) {
readFromParcel(in);
}
public static final Creator<ABlockedRoad> CREATOR = new Creator<ABlockedRoad>() {
@Override
public ABlockedRoad createFromParcel(Parcel in) {
return new ABlockedRoad(in);
}
@Override
public ABlockedRoad[] newArray(int size) {
return new ABlockedRoad[size];
}
};
public long getRoadId() {
return roadId;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
public double getDirection() {
return direction;
}
public String getName() {
return name;
}
public String getAppModeKey() {
return appModeKey;
}
@Override
protected void readFromBundle(Bundle bundle) {
roadId = bundle.getLong("roadId");
latitude = bundle.getDouble("latitude");
longitude = bundle.getDouble("longitude");
direction = bundle.getDouble("direction");
name = bundle.getString("name");
appModeKey = bundle.getString("appModeKey");
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putLong("roadId", roadId);
bundle.putDouble("latitude", latitude);
bundle.putDouble("longitude", longitude);
bundle.putDouble("direction", direction);
bundle.putString("name", name);
bundle.putString("appModeKey", appModeKey);
}
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidlapi.navigation;
parcelable AddBlockedRoadParams;

View file

@ -0,0 +1,46 @@
package net.osmand.aidlapi.navigation;
import android.os.Bundle;
import android.os.Parcel;
import net.osmand.aidlapi.AidlParams;
public class AddBlockedRoadParams extends AidlParams {
private ABlockedRoad blockedRoad;
public AddBlockedRoadParams(ABlockedRoad blockedRoad) {
this.blockedRoad = blockedRoad;
}
public AddBlockedRoadParams(Parcel in) {
readFromParcel(in);
}
public static final Creator<AddBlockedRoadParams> CREATOR = new Creator<AddBlockedRoadParams>() {
@Override
public AddBlockedRoadParams createFromParcel(Parcel in) {
return new AddBlockedRoadParams(in);
}
@Override
public AddBlockedRoadParams[] newArray(int size) {
return new AddBlockedRoadParams[size];
}
};
public ABlockedRoad getBlockedRoad() {
return blockedRoad;
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putParcelable("blockedRoad", blockedRoad);
}
@Override
protected void readFromBundle(Bundle bundle) {
bundle.setClassLoader(ABlockedRoad.class.getClassLoader());
blockedRoad = bundle.getParcelable("blockedRoad");
}
}

View file

@ -11,15 +11,18 @@ public class NavigateGpxParams extends AidlParams {
private String data;
private Uri uri;
private boolean force;
private boolean needLocationPermission;
public NavigateGpxParams(String data, boolean force) {
public NavigateGpxParams(String data, boolean force, boolean needLocationPermission) {
this.data = data;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateGpxParams(Uri uri, boolean force) {
public NavigateGpxParams(Uri uri, boolean force, boolean needLocationPermission) {
this.uri = uri;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateGpxParams(Parcel in) {
@ -50,11 +53,16 @@ public class NavigateGpxParams extends AidlParams {
return force;
}
public boolean isNeedLocationPermission() {
return needLocationPermission;
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putString("data", data);
bundle.putParcelable("uri", uri);
bundle.putBoolean("force", force);
bundle.putBoolean("needLocationPermission", needLocationPermission);
}
@Override
@ -62,5 +70,6 @@ public class NavigateGpxParams extends AidlParams {
data = bundle.getString("data");
uri = bundle.getParcelable("uri");
force = bundle.getBoolean("force");
needLocationPermission = bundle.getBoolean("needLocationPermission");
}
}

View file

@ -17,8 +17,10 @@ public class NavigateParams extends AidlParams {
private double destLon;
private boolean force;
private boolean needLocationPermission;
public NavigateParams(String startName, double startLat, double startLon, String destName, double destLat, double destLon, String profile, boolean force) {
public NavigateParams(String startName, double startLat, double startLon, String destName, double destLat,
double destLon, String profile, boolean force, boolean needLocationPermission) {
this.startName = startName;
this.startLat = startLat;
this.startLon = startLon;
@ -27,6 +29,7 @@ public class NavigateParams extends AidlParams {
this.destLon = destLon;
this.profile = profile;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateParams(Parcel in) {
@ -77,6 +80,10 @@ public class NavigateParams extends AidlParams {
return force;
}
public boolean isNeedLocationPermission() {
return needLocationPermission;
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putString("startName", startName);
@ -87,6 +94,7 @@ public class NavigateParams extends AidlParams {
bundle.putDouble("destLon", destLon);
bundle.putString("profile", profile);
bundle.putBoolean("force", force);
bundle.putBoolean("needLocationPermission", needLocationPermission);
}
@Override
@ -99,5 +107,6 @@ public class NavigateParams extends AidlParams {
destLon = bundle.getDouble("destLon");
profile = bundle.getString("profile");
force = bundle.getBoolean("force");
needLocationPermission = bundle.getBoolean("needLocationPermission");
}
}

View file

@ -17,10 +17,11 @@ public class NavigateSearchParams extends AidlParams {
private double searchLon;
private boolean force;
private boolean needLocationPermission;
public NavigateSearchParams(String startName, double startLat, double startLon,
String searchQuery, double searchLat, double searchLon,
String profile, boolean force) {
String searchQuery, double searchLat, double searchLon,
String profile, boolean force, boolean needLocationPermission) {
this.startName = startName;
this.startLat = startLat;
this.startLon = startLon;
@ -29,6 +30,7 @@ public class NavigateSearchParams extends AidlParams {
this.searchLon = searchLon;
this.profile = profile;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateSearchParams(Parcel in) {
@ -79,6 +81,10 @@ public class NavigateSearchParams extends AidlParams {
return force;
}
public boolean isNeedLocationPermission() {
return needLocationPermission;
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putString("startName", startName);
@ -89,6 +95,7 @@ public class NavigateSearchParams extends AidlParams {
bundle.putBoolean("force", force);
bundle.putDouble("searchLat", searchLat);
bundle.putDouble("searchLon", searchLon);
bundle.putBoolean("needLocationPermission", needLocationPermission);
}
@Override
@ -101,5 +108,6 @@ public class NavigateSearchParams extends AidlParams {
force = bundle.getBoolean("force");
searchLat = bundle.getDouble("searchLat");
searchLon = bundle.getDouble("searchLon");
needLocationPermission = bundle.getBoolean("needLocationPermission");
}
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidlapi.navigation;
parcelable RemoveBlockedRoadParams;

View file

@ -0,0 +1,46 @@
package net.osmand.aidlapi.navigation;
import android.os.Bundle;
import android.os.Parcel;
import net.osmand.aidlapi.AidlParams;
public class RemoveBlockedRoadParams extends AidlParams {
private ABlockedRoad blockedRoad;
public RemoveBlockedRoadParams(ABlockedRoad blockedRoad) {
this.blockedRoad = blockedRoad;
}
public RemoveBlockedRoadParams(Parcel in) {
readFromParcel(in);
}
public static final Creator<RemoveBlockedRoadParams> CREATOR = new Creator<RemoveBlockedRoadParams>() {
@Override
public RemoveBlockedRoadParams createFromParcel(Parcel in) {
return new RemoveBlockedRoadParams(in);
}
@Override
public RemoveBlockedRoadParams[] newArray(int size) {
return new RemoveBlockedRoadParams[size];
}
};
public ABlockedRoad getBlockedRoad() {
return blockedRoad;
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putParcelable("blockedRoad", blockedRoad);
}
@Override
protected void readFromBundle(Bundle bundle) {
bundle.setClassLoader(ABlockedRoad.class.getClassLoader());
blockedRoad = bundle.getParcelable("blockedRoad");
}
}

View file

@ -1539,8 +1539,19 @@ public class BinaryMapIndexReader {
return request;
}
public static SearchRequest<Amenity> buildSearchPoiRequest(LatLon latLon, int radius, int zoom,
SearchPoiTypeFilter poiTypeFilter,
ResultMatcher<Amenity> matcher) {
SearchRequest<Amenity> request = new SearchRequest<>();
request.setBBoxRadius(latLon.getLatitude(), latLon.getLongitude(), radius);
request.zoom = zoom;
request.poiTypeFilter = poiTypeFilter;
request.resultMatcher = matcher;
return request;
}
public static SearchRequest<RouteDataObject> buildSearchRouteRequest(int sleft, int sright, int stop, int sbottom,
ResultMatcher<RouteDataObject> matcher){
ResultMatcher<RouteDataObject> matcher) {
SearchRequest<RouteDataObject> request = new SearchRequest<RouteDataObject>();
request.left = sleft;
request.right = sright;
@ -1557,6 +1568,10 @@ public class BinaryMapIndexReader {
}
public static SearchRequest<Amenity> buildSearchPoiRequest(int x, int y, String nameFilter, int sleft, int sright, int stop, int sbottom, ResultMatcher<Amenity> resultMatcher, ResultMatcher<Amenity> rawDataCollector) {
return buildSearchPoiRequest(x, y, nameFilter, sleft, sright, stop, sbottom, null, resultMatcher, null);
}
public static SearchRequest<Amenity> buildSearchPoiRequest(int x, int y, String nameFilter, int sleft, int sright, int stop, int sbottom, SearchPoiTypeFilter poiTypeFilter, ResultMatcher<Amenity> resultMatcher, ResultMatcher<Amenity> rawDataCollector) {
SearchRequest<Amenity> request = new SearchRequest<Amenity>();
request.x = x;
request.y = y;
@ -1564,6 +1579,7 @@ public class BinaryMapIndexReader {
request.right = sright;
request.top = stop;
request.bottom = sbottom;
request.poiTypeFilter = poiTypeFilter;
request.resultMatcher = resultMatcher;
request.rawDataCollector = rawDataCollector;
request.nameQuery = nameFilter.trim();

View file

@ -8,6 +8,7 @@
<!--JavaScript files-->
<asset source="voice/ar/ar_tts.js" destination="voice/ar-tts/ar_tts.js" mode="overwriteOnlyIfExists" />
<asset source="voice/bg/bg_tts.js" destination="voice/bg-tts/bg_tts.js" mode="overwriteOnlyIfExists" />
<asset source="voice/be/be_tts.js" destination="voice/be-tts/be_tts.js" mode="overwriteOnlyIfExists" />
<asset source="voice/cs/cs_tts.js" destination="voice/cs-tts/cs_tts.js" mode="overwriteOnlyIfExists" />
<asset source="voice/da/da_tts.js" destination="voice/da-tts/da_tts.js" mode="overwriteOnlyIfExists" />

View file

@ -3364,8 +3364,8 @@
<string name="poi_url">الرابط</string>
<string name="poi_parking_space">أماكن لوقوف السيارات</string>
<string name="poi_grave">قبر</string>
<string name="poi_community_gender_male">جنس المجتمع: ذكر</string>
<string name="poi_community_gender_female">جنس المجتمع: أنثى</string>
<string name="poi_community_gender_male">نوع المجتمع: ذكر</string>
<string name="poi_community_gender_female">نوع المجتمع: أنثى</string>
<string name="poi_bath_open_air_no">لا</string>
<string name="poi_bath_open_air_yes">نعم</string>
<string name="poi_bath_type_foot_bath">حمام القدم</string>
@ -3659,4 +3659,17 @@
<string name="poi_wreck">حطام سفينة</string>
<string name="poi_rune_stone">حجر الشاهد القائم الروني</string>
<string name="poi_historic_tank">دبابة تاريخية</string>
<string name="poi_water_source_lake">بحيرة</string>
<string name="poi_water_source_river">نهر</string>
<string name="poi_water_source_well">بئر</string>
<string name="poi_water_source_powered_pump">مضخة</string>
<string name="poi_water_source_water_tank">خزان مياه</string>
<string name="poi_water_source_tap">حنفية</string>
<string name="poi_water_source_water_works">أعمال مياه</string>
<string name="poi_water_source_tube_well">شيب مياه</string>
<string name="poi_vaccination_covid19">لقاح كورونا COVID19</string>
<string name="poi_health_specialty_vaccination_yes">يتوفر لدهم لقاح</string>
<string name="poi_lifeguard_base">منصة الانقاذ</string>
<string name="poi_siren">صفارت إنذار</string>
<string name="poi_community_gender_mixed">نوع المجتمع: مختلط</string>
</resources>

View file

@ -1528,8 +1528,8 @@
<string name="poi_bathing_yes">Baden: ja</string>
<string name="poi_bathing_no">Baden: nein</string>
<string name="poi_boat_storage">Bootslager</string>
<string name="poi_bridge_ref">Brücke Nr.</string>
<string name="poi_tunnel_ref">Tunnel Nr.</string>
<string name="poi_bridge_ref">Bauwerksnummer</string>
<string name="poi_tunnel_ref">Bauwerksnummer</string>
<string name="poi_ref">Nr.</string>
<string name="poi_cargo_passengers">Passagiere</string>
<string name="poi_cargo_vehicle">Fahrzeuge</string>
@ -3889,4 +3889,16 @@
<string name="poi_lifeguard_base">Rettungsschwimmerbasis</string>
<string name="poi_vaccination_covid19">Impfung: COVID19</string>
<string name="poi_health_specialty_vaccination_yes">Impfung</string>
<string name="poi_water_source_tube_well">Rammbrunnen</string>
<string name="poi_water_source_lake">See</string>
<string name="poi_water_source_river">Fluss</string>
<string name="poi_water_source_well">Brunnen</string>
<string name="poi_water_source_powered_pump">Angetriebene Pumpe</string>
<string name="poi_water_source_water_tank">Wassertank</string>
<string name="poi_water_source_tap">Wasserhahn</string>
<string name="poi_water_source_water_works">Wasserwerk</string>
<string name="poi_lavoir">Waschplatz für Wäsche</string>
<string name="poi_waste_transfer_station">Müllumladestation</string>
<string name="poi_weightbridge">Fahrzeugwaage</string>
<string name="poi_ranger_station">Rangerstation</string>
</resources>

View file

@ -562,7 +562,7 @@
<string name="voices">Sprachansagen</string>
<string name="voice">Sprachansage</string>
<string name="no_vector_map_loaded">Vektorkarten wurden nicht geladen</string>
<string name="error_reading_gpx">GPX-Daten konnten nicht gelesen werden</string>
<string name="error_reading_gpx">GPX-Daten konnten nicht gelesen werden.</string>
<string name="vector_data">Offline-Vektorkarten</string>
<string name="transport_context_menu">Suche nach Verbindung an Haltestelle</string>
<string name="poi_context_menu_modify">Bearbeite POI</string>
@ -1960,7 +1960,7 @@
<string name="map_widget_bearing">Relative Peilung</string>
<string name="access_autoannounce_period">Zeit zwischen automatischen Ansagen</string>
<string name="map_widget_magnetic_bearing">Magnetische Peilung</string>
<string name="access_no_destination">Ziel ist nicht festgelegt</string>
<string name="access_no_destination">Modul für Bedienungshilfen: Ziel ist nicht festgelegt</string>
<string name="use_osm_live_routing">OsmAnd-Live-Navigation</string>
<string name="map_widget_battery">Akkustand</string>
<string name="move_marker_bottom_sheet_title">Karte bewegen, um die Position der Markierung zu verändern</string>
@ -2170,7 +2170,7 @@
<string name="quick_action_map_overlay_switch">Karten-Overlay wurde in „%s“ geändert.</string>
<string name="quick_action_map_underlay_switch">Karten-Underlay wurde in „%s“ geändert.</string>
<string name="navigate_point_olc_info_invalid">Ungültiger OLC
</string>
\n</string>
<string name="navigate_point_olc_info_short">Kurzer OLC
\nBitte geben Sie einen vollständigen Code ein</string>
<string name="navigate_point_olc_info_area">Gültiger vollständiger OLC
@ -3520,7 +3520,7 @@
<string name="import_profile_dialog_description">Das importierte Profil enthält zusätzliche Daten. Klicken Sie auf \"Importieren\", um nur Profildaten zu importieren, oder wählen Sie zusätzliche Daten aus.</string>
<string name="export_profile_dialog_description">Sie können zusätzliche Daten zum Exportieren zusammen mit dem Profil auswählen.</string>
<string name="index_name_antarctica">Antarktis</string>
<string name="osm_edits_view_descr">Sie können alle Ihre noch nicht hochgeladenen Bearbeitungen oder OSM-Fehlermeldungen in %1$s anzeigen. Hochgeladene Punkte werden in OsmAnd nicht angezeigt.</string>
<string name="osm_edits_view_descr">Betrachten Sie alle Ihre noch nicht hochgeladenen Bearbeitungen oder OSM-Hinweise in %1$s. Bereits hochgeladene Änderungen werden nicht mehr angezeigt.</string>
<string name="monitoring_min_speed_descr_recommendation">Empfehlung: Versuchen Sie zunächst, die Bewegungserkennung über den Filter zur Mindestabstandsmessung (B) zu verwenden. Das kann zu besseren Ergebnissen führen und Sie werden weniger Daten verlieren. Sollten Ihre Tracks bei niedrigen Geschwindigkeiten ungenau bleiben, versuchen Sie hier Werte ungleich Null. Bitte beachten Sie, dass einige Messungen (einige netzwerkbasierte Methoden) möglicherweise überhaupt keine Geschwindigkeitswerte anzeigen. In diesem Fall wird nichts aufgezeichnet.</string>
<string name="monitoring_min_accuracy_descr">Es werden nur Punkte aufgezeichnet, die mit der gewählten Mindestgenauigkeit bestimmt wurden (in Metern/Fuß, wie von Android je nach Chipsatz bereitgestellt). Die Genauigkeit beschreibt die Nähe der Messungen zur wahren Position und steht nicht unmittelbar in Bezug zur Präzision, der Streuung wiederholter Messungen.</string>
<string name="monitoring_min_accuracy_descr_remark">Bemerkung: Wenn das GPS unmittelbar vor einer Aufzeichnung ausgeschaltet war, kann der erste gemessene Punkt eine verminderte Genauigkeit haben, sodass wir in unserem Code vielleicht eine Sekunde oder so warten wollen, bevor ein Punkt (oder der beste von 3 aufeinanderfolgenden Punkten usw.) aufgezeichnet wird. Das ist aber noch nicht implementiert.</string>
@ -3801,9 +3801,9 @@
<string name="lenght_limit_description">Bitte geben Sie Ihre Fahrzeuglänge an. Für lange Fahrzeuge könnten einige Streckenabschnitte nicht befahrbar sein.</string>
<string name="quick_action_remove_next_destination">Nächstgelegenen Zielpunkt löschen</string>
<string name="please_provide_point_name_error">Bitte geben Sie einen Namen für das Profil an</string>
<string name="quick_action_remove_next_destination_descr">Der aktuelle Punkt auf der Route wird gelöscht. Wenn es das Ziel ist, wird die Navigation gestoppt.</string>
<string name="quick_action_remove_next_destination_descr">Löscht das nächste Ziel auf Ihrer Route. Wenn dies das endgültige Ziel ist, wird die Navigation gestoppt.</string>
<string name="search_download_wikipedia_maps">Wikipedia-Karten herunterladen</string>
<string name="plugin_wikipedia_description">Info über Sehenswürdigkeiten erhalten Sie bei Wikipedia. Es ist Ihr Offline-Wegweiser für die Hosentasche - aktivieren Sie einfach das Wikipedia-Modul und genießen Sie Artikel über Objekte in Ihrer Umgebung.</string>
<string name="plugin_wikipedia_description">Holen Sie sich Informationen über Sehenswürdigkeiten aus Wikipedia, einem Offline-Reiseführer für die Hosentasche mit Artikeln über Orte und Ziele.</string>
<string name="app_mode_enduro_motorcycle">Enduro</string>
<string name="app_mode_motor_scooter">Motorroller</string>
<string name="app_mode_wheelchair">Rollstuhl</string>
@ -3844,7 +3844,7 @@
<string name="add_address">Adresse hinzufügen</string>
<string name="access_hint_enter_address">Adresse eingeben</string>
<string name="street_level_imagery">Bilder auf Straßenebene</string>
<string name="plan_route_exit_dialog_descr">Sind Sie sicher, dass Sie alle Änderungen an der geplanten Route verwerfen wollen, indem Sie sie schließen\?</string>
<string name="plan_route_exit_dialog_descr">Sind Sie sicher, dass Sie alle Änderungen an der geplanten Route verwerfen wollen\?</string>
<string name="plan_route_change_route_type_before">Routentyp davor ändern</string>
<string name="plan_route_change_route_type_after">Routentyp danach ändern</string>
<string name="plan_route_trim_before">Davor trimmen</string>
@ -3877,7 +3877,7 @@
<string name="save_track_to_gpx">Während der Navigation automatisch Track aufzeichnen</string>
<string name="shared_string_gpx_route">Track Route</string>
<string name="import_track_descr">Track Datei zum Folgen auswählen, oder vom Gerät importieren.</string>
<string name="disable_recording_once_app_killed_descrp">Die GPX-Aufzeichnung wird angehalten, wenn OsmAnd beendet wird (über „zuletzt verwendete Apps“). (Die Hintergrunddienst-Anzeige verschwindet aus der Android-Benachrichtigungsleiste.)</string>
<string name="disable_recording_once_app_killed_descrp">Die Track-Aufzeichnung wird angehalten, wenn OsmAnd beendet wird (über „zuletzt verwendete Apps“). (Die Hintergrunddienst-Anzeige verschwindet aus der Android-Benachrichtigungsleiste.)</string>
<string name="save_global_track_interval_descr">Aufzeichnungsintervall für die generelle Track-Aufzeichnung festlegen (wird über die Schaltfläche \'Routenaufzeichung\' auf dem Kartenbildschirm angeschaltet).</string>
<string name="route_between_points_warning_desc">Als nächstes können Sie Ihren Track mit einem Ihrer Navigationsprofile auf die nächstgelegene erlaubte Straße einrasten lassen, um diese Option zu nutzen.</string>
<string name="quick_action_add_gpx">Track-Wegpunkt hinzufügen</string>
@ -3913,12 +3913,12 @@
<string name="sort_name_ascending">Name: A Z</string>
<string name="start_finish_icons">Start- und Zielsymbole</string>
<string name="contour_lines_thanks">Vielen Dank für den Kauf von \'Höhenlinien\'</string>
<string name="osm_live_payment_desc_hw">Das Abonnement wird pro ausgewähltem Zeitraum berechnet. Sie können das Abonnement jederzeit über die AppGallery kündigen.</string>
<string name="osm_live_payment_subscription_management_hw">Die Bezahlung wird Ihrem AppGallery-Konto bei der Bestätigung des Kaufs belastet.
<string name="osm_live_payment_desc_hw">Das Abonnement wird für den gewählten Zeitraum berechnet. Sie können es jederzeit in Ihrer AppGallery kündigen.</string>
<string name="osm_live_payment_subscription_management_hw">Ihr AppGallery-Konto wird mit der Kaufbestätigung belastet.
\n
\nDas Abonnement verlängert sich automatisch, sofern es nicht vor dem Verlängerungsdatum gekündigt wird. Ihr Konto wird für den Verlängerungszeitraum (Monat / drei Monate / Jahr) nur am Verlängerungsdatum belastet.
\nDas Abonnement verlängert sich automatisch, wenn es nicht vor dem Verlängerungsdatum gekündigt wird. Ihr Konto wird erst am Verlängerungsdatum für den Verlängerungszeitraum (Monat/drei Monate/Jahr) belastet.
\n
\nSie können Ihre Abonnements verwalten und kündigen, indem Sie zu Ihren AppGallery-Einstellungen gehen.</string>
\nSie können Ihre Abonnements in Ihren AppGallery-Einstellungen verwalten und kündigen.</string>
<string name="routing_attr_avoid_footways_description">Vermeidet Fußwege</string>
<string name="routing_attr_avoid_footways_name">Keine Fußwege</string>
<string name="development">Entwicklung</string>
@ -3942,7 +3942,7 @@
<string name="message_graph_will_be_available_after_recalculation">Bitte warten Sie.
\nDie Grafik wird nach der Neuberechnung der Route verfügbar sein.</string>
<string name="icon_group_amenity">Einrichtung</string>
<string name="icon_group_transport">ÖPNV</string>
<string name="icon_group_transport">Verkehr</string>
<string name="icon_group_service">Dienstleistung</string>
<string name="icon_group_travel">Reisen</string>
<string name="icon_group_sport">Sport</string>
@ -3953,7 +3953,7 @@
<string name="icon_group_special">Spezial</string>
<string name="message_you_need_add_two_points_to_show_graphs">Fügen Sie mindestens zwei Punkte hinzu</string>
<string name="manage_subscription">Abonnement verwalten</string>
<string name="subscription_payment_issue_title">Es gibt ein Problem mit Ihrem Abonnement. Tippen Sie auf die Schaltfläche, um zu den Einstellungen des Google Play Abonnements zu gelangen und Ihre Zahlungsmethode zu überprüfen.</string>
<string name="subscription_payment_issue_title">Tippen Sie auf die Schaltfläche, um eine Zahlungsmethode auf Google Play einzurichten und Ihr Abonnement zu bestätigen.</string>
<string name="subscription_expired_title">OsmAnd Live Abonnement ist abgelaufen</string>
<string name="subscription_paused_title">OsmAnd Live Abonnement wurde ausgesetzt</string>
<string name="subscription_on_hold_title">OsmAnd Live Abonnement liegt auf Eis</string>
@ -4020,4 +4020,7 @@
<string name="app_mode_gap">Lücke</string>
<string name="plan_route_join_segments">Segmente verbinden</string>
<string name="plan_route_add_new_segment">Neues Segment hinzufügen</string>
<string name="profile_type_osmand_string">OsmAnd-Profil</string>
<string name="profile_type_user_string">Benutzerprofil</string>
<string name="reverse_all_points">Alle Punkte umkehren</string>
</resources>

View file

@ -3887,4 +3887,6 @@
<string name="poi_water_source_tap">krano</string>
<string name="poi_water_source_water_works">akvokondukilo</string>
<string name="poi_water_source_tube_well">puto tuba (abisena)</string>
<string name="poi_weightbridge">Pezilo por aŭtomobiloj</string>
<string name="poi_ranger_station">Oficejo de naturrezervejo</string>
</resources>

View file

@ -3901,4 +3901,8 @@
<string name="poi_water_source_tap">Canilla</string>
<string name="poi_water_source_water_works">Planta potabilizadora</string>
<string name="poi_water_source_tube_well">Pozo entubado</string>
<string name="poi_weightbridge">Báscula puente</string>
<string name="poi_ranger_station">Estación de guardabosques</string>
<string name="poi_lavoir">Lavadero público de ropa</string>
<string name="poi_waste_transfer_station">Estación de transferencia de residuos</string>
</resources>

View file

@ -4023,4 +4023,5 @@
\n</string>
<string name="profile_type_osmand_string">Perfil de OsmAnd</string>
<string name="profile_type_user_string">Perfil de usuario</string>
<string name="reverse_all_points">Invertir todos los puntos</string>
</resources>

View file

@ -3843,4 +3843,18 @@
<string name="poi_diplomatic_services_citizen_services_no">Ei</string>
<string name="poi_siren">Sireen</string>
<string name="poi_lifeguard_base">Vetelpäästejaam</string>
<string name="poi_nurse">Õde</string>
<string name="poi_health_specialty_vaccination_yes">Vaktsineerimine</string>
<string name="poi_vaccination_covid19">Vaktsineerimine: COVID19</string>
<string name="poi_water_source_tube_well">Puurkaev</string>
<string name="poi_water_source_water_works">Veevärgi ettevõte</string>
<string name="poi_water_source_tap">Veekraan</string>
<string name="poi_water_source_water_tank">Veepaak</string>
<string name="poi_water_source_powered_pump">Mootoriga veepump</string>
<string name="poi_water_source_well">Kaev</string>
<string name="poi_water_source_river">Jõgi</string>
<string name="poi_water_source_lake">Järv</string>
<string name="poi_mobile_money_agent">Mobiiliraha müügikoht</string>
<string name="poi_ranger_station">Pargivahi maja</string>
<string name="poi_weightbridge">Autokaal</string>
</resources>

View file

@ -3850,4 +3850,6 @@
<string name="plan_route_split_after">Tükelda pärast</string>
<string name="plan_route_split_before">Tükelda enne</string>
<string name="plan_route_join_segments">Liida lõigud</string>
<string name="profile_type_user_string">Kasutajaprofiil</string>
<string name="profile_type_osmand_string">OsmAnd profiil</string>
</resources>

View file

@ -3987,4 +3987,23 @@
<string name="register_opr_create_new_account">ساخت حساب جدید</string>
<string name="register_opr_have_account">حساب کاربری دارم</string>
<string name="shared_string_search_history">تاریخچهٔ جست‌وجو</string>
<string name="export_not_enough_space_descr">دستگاه شما تنها %1$s فضای خالی دارد. لطفا مقادری فضا خالی کنید و یا تعداد موارد برون‌ریزی را کاهش دهید.</string>
<string name="export_not_enough_space">فضای کافی موجود نیست</string>
<string name="select_groups_for_import">گروه‌هایی را که درون‌ریزی خواهند شد را انتخاب کنید.</string>
<string name="select_items_for_import">مواردی را که درون‌ریزی خواهند شد را انتخاب کنید.</string>
<string name="add_to_mapillary">افزودن به مپیلاری</string>
<string name="add_to_opr">افزودن به OpenPlaceReviews</string>
<string name="use_dev_url_descr">برای امتحان کردن بارگذاری یادداشت / نقاط توجه و GPX از dev.openstreetmap.org به جای openstreetmep.org استفاده کنید.</string>
<string name="use_dev_url">از dev.openstreetmap.org استفاده کنید</string>
<string name="add_photos_descr">برنامه OsmAnd عکس‌ها را از چند منبع نشان می‌دهد:
\nاز OpenPlaceReview برای عکس‌های نقاط توجه؛
\nاز مپیلاری برای تصویر سطح خیابان؛
\nاز وب و ویکی‌پدیا برای عکس‌های نقاط توجه متناسب با داده‌های اوپن‌استریت‌مپ.</string>
<string name="app_mode_light_aircraft">هواپیمای سبک</string>
<string name="plan_route_join_segments">اتصال بخش‌ها</string>
<string name="plan_route_split_before">"تقطیع از این جا به قبل"</string>
<string name="plan_route_split_after">تقطیع از این جا به بعد</string>
<string name="plan_route_add_new_segment">افزودن یک بخش جدید</string>
<string name="profile_type_osmand_string">نمایهٔ OsmAnd</string>
<string name="profile_type_user_string">نمایهٔ کاربر</string>
</resources>

View file

@ -305,7 +305,7 @@
<string name="only_show">Näytä vain</string>
<string name="follow">Seuraa</string>
<string name="mark_final_location_first">Valitse päämäärä ensin</string>
<string name="get_directions">Ohjeet</string>
<string name="get_directions">Reittiohjeet</string>
<string name="opening_hours">Avoinna</string>
<string name="loading_streets_buildings">Ladataan katuja/rakennuksia…</string>
<string name="loading_postcodes">Ladataan postinumeroita…</string>
@ -390,7 +390,7 @@
<string name="poi_error_unexpected_template">Tapahtui odottamaton virhe suoritettaessa toimintoa {0}.</string>
<string name="poi_dialog_opening_hours">Avoinna</string>
<string name="edit_filter_save_as_menu_item">Tallenna nimellä</string>
<string name="rendering_attr_roadColors_description">Valitse tien väriteema:</string>
<string name="rendering_attr_roadColors_description">Valitse tien värimaailma:</string>
<string name="gps_not_available">Salli GPS:n käyttö asetuksista</string>
<string name="poi_filter_car_aid">Autotuki</string>
<string name="layer_map_appearance">Muokkaa näyttöä</string>
@ -412,7 +412,7 @@
<string name="osmand_parking_time_limit">Aikarajoitettu pysäköinti</string>
<string name="osmand_parking_time_no_limit">Aika rajoittamaton pysäköinti</string>
<string name="osmand_parking_position_description">Pysäköidyn autosi sijainti. %1$s</string>
<string name="osmand_parking_position_description_add">Nouda auto kello:</string>
<string name="osmand_parking_position_description_add">Nouda ajoneuvo kello:</string>
<string name="osmand_parking_pm">PM</string>
<string name="osmand_parking_am">AM</string>
<string name="asap">U-Käännös</string>
@ -488,7 +488,7 @@
<string name="accessibility_mode">Esteettömyys moodi</string>
<string name="accessibility_default">Globaalien systeemiasetusten mukaan</string>
<string name="zxing_barcode_scanner_not_found">ZXing viivakoodinlukusovellusta ei ole asennettuna. Etsitäänkö se Google Playstä?</string>
<string name="rendering_attr_roadColors_name">Tien väriteema</string>
<string name="rendering_attr_roadColors_name">Tien värimaailma</string>
<string name="map_widget_show_destination_arrow">Näytä kohteen suunta</string>
<string name="non_optimal_route_calculation">Laske mahdollisesti epäoptimaalinen reitti pitkille matkoille</string>
<string name="offline_edition_descr">Käytä aina offline editointia</string>
@ -836,7 +836,7 @@ Maailmanlaajuiset tiedot (välillä 70 astetta pohjoista ja 70 astetta eteläist
<string name="shared_string_recorded">Nauhoitettu</string>
<string name="shared_string_record">Nauhoita</string>
<string name="gpx_logging_no_data">Ei dataa</string>
<string name="rendering_attr_contourColorScheme_description">Korkeuskäyräviivojen väripaletti</string>
<string name="rendering_attr_contourColorScheme_description">Korkeuskäyräviivojen värimaailma</string>
<string name="save_track_min_speed">Miniminopeuden kirjaaminen</string>
<string name="save_track_min_speed_descr">Aseta miniminopeus kirjattavalle pisteelle.</string>
<string name="save_track_min_distance">Liikkeen tunnistuksen kirjaus</string>
@ -847,7 +847,7 @@ Maailmanlaajuiset tiedot (välillä 70 astetta pohjoista ja 70 astetta eteläist
<string name="christmas_desc_q">Näytä Joulupyhän KP:t\?</string>
<string name="rendering_value_light_brown_name">Vaaleanruskea</string>
<string name="rendering_value_dark_brown_name">Tummanruskea</string>
<string name="rendering_attr_contourColorScheme_name">Korkeuskäyrien väripaletti</string>
<string name="rendering_attr_contourColorScheme_name">Korkeuskäyrien värimaailma</string>
<string name="rendering_attr_surfaceIntegrity_name">Tienpinnan eheys</string>
<string name="search_hint">Kirjoita kaupunki, osoite, KP:n nimi</string>
<string name="edit_filter">Muokkaa luokkia</string>
@ -1728,7 +1728,7 @@ Maailmanlaajuiset tiedot (välillä 70 astetta pohjoista ja 70 astetta eteläist
Paina ja pidä nähdäksesi kartalla</string>
<string name="gpx_info_asc_altitude">Alas/Ylös: %1$s</string>
<string name="calculate_osmand_route_without_internet">Laske OsmAnd reitin segmentti ilman internettiä</string>
<string name="calculate_osmand_route_without_internet">OsmAnd reittisegmentin laskeminen ilman internettiä</string>
<string name="gpx_option_calculate_first_last_segment">Laske OsmAnd reitti ensimmäiselle ja viimeiselle reitin segmentille</string>
<string name="use_displayed_track_for_navigation">Käytetäänkö näytettävää jälkeä suunnistuksessa\?</string>
<string name="keep_and_add_destination_point">Lisää myöhemmäksi päämääräksi</string>
@ -2208,7 +2208,7 @@ Jos pidät OsmAndista ja OSMsta ja haluat tukea niitä, on tämä täydellinen t
<string name="increase_search_radius">Kasvata haun laajuutta</string>
<string name="nothing_found_descr">Muokkaa hakusanoja tai lisää haun laajuutta.</string>
<string name="quick_action_showhide_osmbugs_descr">Tämän toimintonappulan tökkääminen näyttää tai piilottaa OSM-huomautukset kartalla.</string>
<string name="srtm_color_scheme">Väriskeema</string>
<string name="srtm_color_scheme">Värimaailma</string>
<string name="routing_attr_allow_private_name">Salli yksityisalueet</string>
<string name="routing_attr_allow_private_description">Salli pääsy yksityisalueille.</string>
<string name="animate_my_location_desc">Ota käyttöön animoitu sijaintini kartan vieritys navigaation aikana.</string>
@ -2571,6 +2571,47 @@ Jos pidät OsmAndista ja OSMsta ja haluat tukea niitä, on tämä täydellinen t
<string name="week">Viikko</string>
<string name="shared_string_bearing">Suuntima</string>
<string name="plan_a_route">Suunnittele reitti</string>
<string name="plan_route_last_edited">Viimeksi muokattu</string>
<string name="plan_route_last_edited">Viimeksi muokatut</string>
<string name="plan_route_create_new_route">Luo uusi reitti</string>
<string name="select_color">Valitse väri</string>
<string name="select_icon_profile_dialog_title">Valitse kuvake</string>
<string name="select_group">Valitse ryhmä</string>
<string name="add_description">Lisää kuvaus</string>
<string name="route_between_points_next_segment_button_desc">Vain seuraava segmentti lasketaan uudelleen valitulla profiililla.</string>
<string name="next_segment">Seuraava segmentti</string>
<string name="all_next_segments">Kaikki seuraavat segmentit</string>
<string name="previous_segment">Edellinen segmentti</string>
<string name="all_previous_segments">Kaikki edelliset segmentit</string>
<string name="only_selected_segment_recalc">Vain valittu segmentti lasketaan uudelleen käyttämällä valittua profiilia.</string>
<string name="all_next_segments_will_be_recalc">Kaikki seuraavat segmentit lasketaan uudelleen käyttämällä valittua profiilia.</string>
<string name="all_previous_segments_will_be_recalc">Kaikki edelliset segmentit lasketaan uudelleen käyttämällä valittua profiilia.</string>
<string name="plan_route_join_segments">Yhdistä segmentit</string>
<string name="plan_route_add_new_segment">Lisää uusi segmentti</string>
<string name="shared_string_octagon">Kahdeksankulmio</string>
<string name="shared_string_square">Neliö</string>
<string name="shared_string_circle">Ympyrä</string>
<string name="select_shape">Valitse muoto</string>
<string name="reset_to_default">Palauta oletusarvot</string>
<string name="profile_prefs_reset_successful">Kaikki profiiliasetukset palautettu oletusarvoihin.</string>
<string name="plugin_prefs_reset_successful">Kaikki laajennuksen asetukset palautettu oletusarvoihin.</string>
<string name="shared_string_app_default_w_val">Sovelluksen oletus (%s)</string>
<string name="reset_deafult_order">Palauta oletus kohteiden järjestys</string>
<string name="default_screen_timeout">Näytön oletusaikakatkaisu</string>
<string name="system_default_theme">Järjestelmän oletus</string>
<string name="reorder_profiles">Muokkaa profiililuetteloa</string>
<string name="edit_profiles">Muokkaa profiileja</string>
<string name="import_profile">Tuo profiili</string>
<string name="selected_profile">Valittu profiili</string>
<string name="icon_group_amenity">Mukavuus</string>
<string name="icon_group_travel">Matkailu</string>
<string name="icon_group_special">Erityinen</string>
<string name="icon_group_sport">Urheilu</string>
<string name="process_downloading_service">OsmAnd-latauspalvelu</string>
<string name="icon_group_service">Palvelu</string>
<string name="icon_group_emergency">Hätätapaus</string>
<string name="icon_group_transport">Liikenne</string>
<string name="quick_action_transport_show">Näytä julkinen liikenne</string>
<string name="quick_action_transport_hide">Piilota julkinen liikenne</string>
<string name="icon_group_symbols">Symbolit</string>
<string name="replace_point_descr">Korvaa toinen kohde tällä.</string>
</resources>

View file

@ -3813,7 +3813,7 @@
<string name="threshold_distance">Seuil de distance</string>
<string name="navigation_profile">Profil de navigation</string>
<string name="street_level_imagery">Photos des rues</string>
<string name="plan_route_exit_dialog_descr">Voulez-vous vraiment fermer l\'itinéraire planifié sans enregistrer \? (vous perdrez vos modifications)</string>
<string name="plan_route_exit_dialog_descr">Souhaitez-vous vraiment ignorer toutes les modifications apportées à l\'itinéraire planifié \?</string>
<string name="in_case_of_reverse_direction">Si inversion du sens</string>
<string name="pass_whole_track_descr">Point de la trace vers lequel naviguer</string>
<string name="shared_string_gpx_route">Enregistrer le parcours</string>
@ -3852,7 +3852,7 @@
<string name="gpx_monitoring_start">Reprendre l\'enregistrement du trajet</string>
<string name="gpx_monitoring_stop">Suspendre l\'enregistrement du trajet</string>
<string name="save_global_track_interval_descr">Définit la fréquence denregistrement des points du parcours (activable depuis le gadget \"Enregistrement\" sur la carte).</string>
<string name="disable_recording_once_app_killed_descrp">Suspend l\'enregistrement du parcours lorsque l\'application est arrêtée via Applications récentes ; les indications OsmAnd ne seront plus affichées dans la barre de notifications.</string>
<string name="disable_recording_once_app_killed_descrp">L\'enregistrement de l\'itinéraire sera suspendu si l\'application est arrêtée via Applications récentes (les indications OsmAnd ne seront plus affichées dans la barre de notifications).</string>
<string name="all_next_segments_will_be_recalc">Tous les segments suivants seront recalculés avec le profil sélectionné.</string>
<string name="all_previous_segments_will_be_recalc">Tous les segments précédents seront recalculés avec le profil sélectionné.</string>
<string name="all_next_segments">Tous les segments suivants</string>
@ -3885,7 +3885,7 @@
<string name="sort_name_ascending">Nom : A Z</string>
<string name="start_finish_icons">Icônes de départ et d\'arrivée</string>
<string name="contour_lines_thanks">Merci pour votre achat de \'Courbes de niveaux\'</string>
<string name="osm_live_payment_desc_hw">Abonnement facturé pour chaque période sélectionnée. Annulation possible à tout moment sur AppGallery.</string>
<string name="osm_live_payment_desc_hw">L\'abonnement est facturé pour la période sélectionnée. Annulation possible à tout moment sur AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Éviter les trottoirs</string>
<string name="routing_attr_avoid_footways_name">Éviter les trottoirs</string>
<string name="development">Développement</string>
@ -3995,4 +3995,7 @@
<string name="plan_route_add_new_segment">Ajouter un nouveau segment</string>
<string name="gpx_upload_identifiable_visibility_descr">« Identifiable » siginifie que la trace sera affichée publiquement dans « Mes traces GPS » ainsi que dans les listes de traces GPS publiques. Ainsi les autres utilisateurs peuvent télécharger la trace brute et l\'associer avec votre nom d\'utilisateur. Les données de points de passage horodatés fournis par l\'API GPS publique feront référence à la page d\'origine de votre trace.</string>
<string name="gpx_upload_public_visibility_descr">« Public » signifie que la trace est affichée publiquement dans vos traces GPS et dans les listes de traces GPS publiques. Les données diffusées via l\'API ne font pas référence à votre page de traces. Les horodatages des points de trace ne sont pas disponibles via l\'API GPS publique et les points de trace ne sont pas classés par ordre chronologique.</string>
<string name="profile_type_osmand_string">Profil OsmAnd</string>
<string name="profile_type_user_string">Profil utilisateur</string>
<string name="reverse_all_points">Inverser tous les points</string>
</resources>

View file

@ -2174,4 +2174,40 @@
<string name="poi_departures_board_timetable">לוח זמנים</string>
<string name="poi_beehive">כוורת דבורים</string>
<string name="poi_nuts">חנות אגוזים</string>
<string name="poi_fire_hydrant_position_underground">תת־קרקעי</string>
<string name="poi_fire_hydrant_position_street">רחוב</string>
<string name="poi_fire_hydrant_position_parking_lot">חנייה</string>
<string name="poi_fire_hydrant_position_lane">נתיב</string>
<string name="poi_fire_hydrant_position_green">ירוק</string>
<string name="poi_fire_hydrant_position_sidewalk">מדרכה</string>
<string name="poi_fire_hydrant_flow_capacity">קיבולת זרימה של ברז כיבוי</string>
<string name="poi_diplomatic_services_citizen_services_filter">שירותים לאזרח</string>
<string name="poi_diplomatic_services_immigrant_visas_filter">ויזות למהגרים</string>
<string name="poi_consulate_filter">קונסוליה</string>
<string name="poi_embassy_filter">שגרירות</string>
<string name="poi_departures_board">לוח זמנים</string>
<string name="poi_drinking_water_refill">מילוי מי שתייה</string>
<string name="poi_traffic_signals_arrow">חץ</string>
<string name="poi_traffic_signals_vibration">רטט</string>
<string name="poi_fire_hydrant_pressure_filter">לחץ</string>
<string name="poi_recreation_center"></string>
<string name="poi_summer_camp"></string>
<string name="poi_salt_no"></string>
<string name="poi_salt_yes"></string>
<string name="poi_depth"></string>
<string name="poi_bicycle_parking_tree"></string>
<string name="poi_bicycle_parking_lockers"></string>
<string name="poi_military_checkpoint"></string>
<string name="poi_street_cabinet_street_lighting"></string>
<string name="poi_street_cabinet_water_management"></string>
<string name="poi_street_cabinet_waste"></string>
<string name="poi_street_cabinet_postal_service"></string>
<string name="poi_street_cabinet_gas"></string>
<string name="poi_street_cabinet_cable_tv"></string>
<string name="poi_street_cabinet_telecom"></string>
<string name="poi_street_cabinet_power"></string>
<string name="poi_in_service_yes"></string>
<string name="poi_water_source_stream"></string>
<string name="poi_water_source_pond"></string>
<string name="poi_water_source_main"></string>
</resources>

View file

@ -4018,4 +4018,7 @@
\n • תמיכה בצבעים מותאמים אישית למועדפים ולנקודות דרך במסלול
\n
\n</string>
<string name="profile_type_osmand_string">פרופיל</string>
<string name="profile_type_user_string">פרופיל</string>
<string name="reverse_all_points">להפוך את כל</string>
</resources>

View file

@ -2904,7 +2904,7 @@
<string name="routeInfo_road_types_name">Veityper</string>
<string name="exit_at">Gå av på</string>
<string name="sit_on_the_stop">Sitt på stoppet</string>
<string name="quick_action_show_hide_gpx_tracks">Vis/skjul GPX-spor</string>
<string name="quick_action_show_hide_gpx_tracks">Vis/skjul spor</string>
<string name="quick_action_show_hide_gpx_tracks_descr">Knapp for å vise eller skjule valgte spor på kartet.</string>
<string name="quick_action_gpx_tracks_hide">Skjul spor</string>
<string name="quick_action_gpx_tracks_show">Vis spor</string>
@ -2945,9 +2945,9 @@
<string name="rendering_attr_surface_paved_name">Fast dekke</string>
<string name="rendering_attr_surface_concrete_name">Betong</string>
<string name="rendering_attr_surface_sett_name">Brostein</string>
<string name="rendering_attr_surface_cobblestone_name">Rustikk brostein</string>
<string name="rendering_attr_surface_cobblestone_name">Naturlig brostein</string>
<string name="rendering_attr_surface_paving_stones_name">Steinbelagt</string>
<string name="rendering_attr_surface_pebblestone_name">Småstein</string>
<string name="rendering_attr_surface_pebblestone_name">Rullestein</string>
<string name="rendering_attr_surface_stone_name">Stein</string>
<string name="rendering_attr_surface_metal_name">Metall</string>
<string name="rendering_attr_surface_wood_name">Tre</string>
@ -3031,15 +3031,15 @@
<string name="make_osmand_better_descr">Tillat OsmAnd å samle inn og behandle anonym programbruksdata. Ingen data om din plassering, eller om plasseringer du ser på kartet blir samlet inn.
\n
\nDu kan alltid endre ditt valg i \"Innstillinger\" → \"Personvern og sikkerhet\".</string>
<string name="choose_data_to_share">Velg hvilken data du ønsker å dele:</string>
<string name="choose_data_to_share">Velg typen data du vil dele:</string>
<string name="downloaded_maps">Nedlastede kart</string>
<string name="visited_screens">Besøkte skjermer</string>
<string name="collected_data_descr">Definer hvilken data du ønsker å dele med OsmAnd.</string>
<string name="downloaded_maps_collect_descr">Hjelp oss å forstå hvilke kart over hvilke regioner og land som er mest populære.</string>
<string name="visited_screens_collect_descr">Hjelp oss å fastslå popularitet for OsmAnd-funksjoner.</string>
<string name="privacy_and_security_change_descr">Trykk \"Tillat\" hvis du samtykker du til vår %1$s</string>
<string name="downloaded_maps_collect_descr">Hjelp oss å forstå hvilke land- og regionkart som er mest populære.</string>
<string name="visited_screens_collect_descr">Hjelp oss å forstå hvilke OsmAnd-funksjoner som er mest populære.</string>
<string name="privacy_and_security_change_descr">Trykk \"Tillat\" hvis du er enig med vår %1$s</string>
<string name="settings_privacy_and_security">Personvern og sikkerhet</string>
<string name="settings_privacy_and_security_desc">Velg data til deling</string>
<string name="settings_privacy_and_security_desc">Velg hvilke data du deler</string>
<string name="shared_string_no_thank_you">Nei takk</string>
<string name="shared_string_allow">Tillat</string>
<string name="profile_name_hint">Profilnavn</string>
@ -3048,8 +3048,8 @@
<string name="app_mode_horse">Hest</string>
<string name="app_mode_helicopter">Helikopter</string>
<string name="osmand_routing_promo">Du kan legge til din egen endrede versjon av filen routing.xml til i ..osmand/routing</string>
<string name="app_mode_skiing">Skikjøring</string>
<string name="base_profile_descr_ski">Skikjøring</string>
<string name="app_mode_skiing">Stå på ski</string>
<string name="base_profile_descr_ski">Ski</string>
<string name="show_compass_ruler">Vis kompasslinjal</string>
<string name="hide_compass_ruler">Skjul kompasslinjal</string>
<string name="select_icon_profile_dialog_title">Velg ikon</string>
@ -3103,10 +3103,10 @@
<string name="app_mode_offroad">Terreng</string>
<string name="edit_profile_setup_title">Sett opp profil</string>
<string name="routing_attr_max_num_changes_name">Antall overganger</string>
<string name="app_mode_shuttle_bus">Pendlebuss</string>
<string name="app_mode_subway">Tunnelbane</string>
<string name="app_mode_shuttle_bus">Skyttelbuss</string>
<string name="app_mode_subway">T-bane</string>
<string name="select_base_profile_dialog_message">Baser din egendefinerte profil på en av de forvalgte programprofilene, dette definerer grunnleggende oppsett, som forvalg synliget for miniprogrammer, enheter for hastighet og distanse. Dette er de forvalgte programprofilene, sammen med eksempler på egentilpassede profiler de kan utvides til:</string>
<string name="base_profile_descr_public_transport">Alle typer offentlig transport</string>
<string name="base_profile_descr_public_transport">Offentlige transporttyper</string>
<string name="zoom_by_wunderlinq_descr">Endre kartforstørrelse ved å rulle hjulet opp og ned. Escape tar deg tilbake til WunderLINQ-programmet.</string>
<string name="quick_action_need_to_add_item_to_list">Legg til minst ett element i listen i hurtighandlingsinnstillingene</string>
<string name="routing_attr_piste_type_downhill_description">Bakker for alpin skisport og tilgang til skiheiser.</string>
@ -3125,8 +3125,8 @@
<string name="shared_string_min_speed">Minimumshastighet</string>
<string name="shared_string_max_speed">Maksimumshastighet</string>
<string name="default_speed_setting_title">Standardhastighet</string>
<string name="default_speed_setting_descr">Endre forvalgte hastighetsinnstillinger</string>
<string name="minmax_speed_dialog_title">Sett min/maks -hastighet</string>
<string name="default_speed_setting_descr">Endre standardhastighetsinnstillinger</string>
<string name="minmax_speed_dialog_title">Still inn min/maks-hastighet</string>
<string name="new_profile">Ny profil</string>
<string name="shared_string_crash">Krasj</string>
<string name="last_launch_crashed">OsmAnd krasjet tidligere. Hjelp til å forbedre OsmAnd ved å dele feilmeldingen.</string>
@ -3157,11 +3157,11 @@
<string name="app_mode_scooter">Scooter</string>
<string name="precision_hdop_and_vdop">Vannrett nøyaktighet: %1$s, loddrett: %2$s</string>
<string name="precision_hdop">Vannrett nøyaktighet: %s</string>
<string name="edit_profile_setup_subtitle">Profil beholder sine egne innstillinger</string>
<string name="edit_profile_setup_map_subtitle">Velg kartinnstillinger for profilen</string>
<string name="edit_profile_screen_options_subtitle">Velg skjerminnstillinger for profilen</string>
<string name="edit_profile_setup_subtitle">Profilen beholder sine egne innstillinger</string>
<string name="edit_profile_setup_map_subtitle">Velg kartalternativer for profilen</string>
<string name="edit_profile_screen_options_subtitle">Velg skjermalternativer for profilen</string>
<string name="edit_profile_nav_settings_subtitle">Velg navigeringsinnstillinger for profilen</string>
<string name="routing_attr_max_num_changes_description">Angi øvre grense for endringer</string>
<string name="routing_attr_max_num_changes_description">Bestem det maksimale antall overganger</string>
<string name="external_input_device">Eksterne inndataenheter</string>
<string name="external_input_device_descr">Velg en enhet for ekstern kontroll, som f.eks. tastatur eller WunderLINQ.</string>
<string name="sett_generic_ext_input">Tastatur</string>
@ -3309,10 +3309,10 @@
<string name="rendering_attr_piste_difficulty_connection_name">Overgang</string>
<string name="track_saved">Spor lagret</string>
<string name="empty_filename">Tomt filnavn</string>
<string name="turn_screen_on_router">Vekk for sving</string>
<string name="turn_screen_on_router">Slå på skjermen ved sving</string>
<string name="turn_screen_on_time_descr">Juster hvor lenge skjermen skal forbli påslått.</string>
<string name="turn_screen_on_sensor">Bruk nærhetssensor</string>
<string name="turn_screen_on_sensor_descr">Vift hånden din over toppen av skjermen for å skru den på under navigasjon.</string>
<string name="turn_screen_on_sensor_descr">Å bevege hånden over skjermen vil slå den på.</string>
<string name="rendering_attr_highway_class_track_grade1_name">Klasse 1</string>
<string name="rendering_attr_highway_class_track_grade2_name">Klasse 2</string>
<string name="rendering_attr_highway_class_track_grade3_name">Klasse 3</string>
@ -3939,4 +3939,5 @@
<string name="login_open_street_map_org">Logg inn på OpenStreetMap.org</string>
<string name="profile_type_osmand_string">OsmAnd-profil</string>
<string name="profile_type_user_string">Brukerprofil</string>
<string name="button_rate">Bedøm</string>
</resources>

View file

@ -1941,7 +1941,7 @@
<string name="rendering_value_thin_name">Cienki</string>
<string name="rendering_value_medium_name">Średni</string>
<string name="rendering_value_bold_name">Gruby</string>
<string name="access_no_destination">Nie ustalono celu</string>
<string name="access_no_destination">Wtyczka ułatwień dostępu: nie ustawiono miejsca docelowego</string>
<string name="access_disable_offroute_recalc">Utrzymywanie trasy po zboczeniu z niej</string>
<string name="access_disable_offroute_recalc_descr">Brak ponownego przeliczania trasy po zjechaniu z trasy.</string>
<string name="map_widget_magnetic_bearing">Orientacja magnetyczna</string>
@ -3791,9 +3791,9 @@
<string name="quick_action_remove_next_destination">Usuń najbliższy punkt docelowy</string>
<string name="use_volume_buttons_as_zoom_descr">Steruj poziomem powiększenia mapy za pomocą przycisków głośności na urządzeniu.</string>
<string name="please_provide_point_name_error">Podaj nazwę punktu</string>
<string name="quick_action_remove_next_destination_descr">Bieżący punkt docelowy na trasie zostanie usunięty. Jeśli będzie to miejsce docelowe, nawigacja zostanie zatrzymana.</string>
<string name="quick_action_remove_next_destination_descr">Usuwa następny cel na trasie. Jeśli jest to miejsce docelowe, nawigacja zostanie zatrzymana.</string>
<string name="search_download_wikipedia_maps">Pobierz mapy Wikipedii</string>
<string name="plugin_wikipedia_description">Uzyskaj informacje o interesujących miejscach z Wikipedii. Jest to kieszonkowy przewodnik offline - wystarczy włączyć wtyczkę Wikipedii i cieszyć się artykułami o obiektach wokół ciebie.</string>
<string name="plugin_wikipedia_description">Uzyskaj informacje o ciekawych miejscach z Wikipedii, kieszonkowego przewodnika offline zawierającego artykuły o miejscach i celach.</string>
<string name="app_mode_enduro_motorcycle">Motocykl Enduro</string>
<string name="app_mode_motor_scooter">Skuter</string>
<string name="routing_attr_length_description">Określ długość pojazdu dozwoloną na trasach.</string>
@ -3839,7 +3839,7 @@
<string name="route_between_points_desc">Wybierz sposób łączenia punktów, za pomocą linii prostej, lub oblicz trasę między nimi w sposób określony poniżej.</string>
<string name="route_between_points_warning_desc">Następnie przyciągnij trasę do najbliższej dozwolonej drogi za pomocą jednego z profili nawigacji, aby skorzystać z tej opcji.</string>
<string name="street_level_imagery">Zdjęcia z poziomu ulicy</string>
<string name="plan_route_exit_dialog_descr">Czy na pewno chcesz odrzucić wszystkie zmiany w zaplanowanej trasie, zamykając ją\?</string>
<string name="plan_route_exit_dialog_descr">Czy na pewno chcesz odrzucić wszystkie zmiany w zaplanowanej trasie\?</string>
<string name="in_case_of_reverse_direction">W przypadku odwrotnego kierunku</string>
<string name="navigate_to_track_descr">Przejdź z mojej lokalizacji na trasę</string>
<string name="app_mode_wheelchair_forward">Sportowy wózek inwalidzki</string>
@ -3912,7 +3912,7 @@
<string name="what_is_new">Co nowego</string>
<string name="start_finish_icons">Ikony startu i końca</string>
<string name="contour_lines_thanks">Dziękujemy za zakup \"Linii konturowych\"</string>
<string name="osm_live_payment_desc_hw">Subskrypcja naliczona za wybrany okres. Anuluj ją w AppGallery w dowolnym momencie.</string>
<string name="osm_live_payment_desc_hw">Subskrypcja jest naliczana za wybrany okres. Anuluj go w AppGallery w dowolnym momencie.</string>
<string name="osm_live_payment_subscription_management_hw">Płatność zostanie pobrana z konta AppGallery po potwierdzeniu zakupu.
\n
\nSubskrypcja jest automatycznie odnawiana, chyba że zostanie anulowana przed datą odnowienia. Twoje konto zostanie obciążone opłatą za okres odnowienia (miesiąc/trzy miesiące/rok) tylko w dniu odnowienia.
@ -3937,7 +3937,7 @@
<string name="navigate_point_format_mgrs">MGRS</string>
<string name="use_two_phase_routing">Użyj 2-fazowego algorytmu routingu A *</string>
<string name="shared_string_graph">Wykres</string>
<string name="message_need_calculate_route_before_show_graph">%1$s dane dostępne tylko na drogach, aby je uzyskać, musisz obliczyć trasę za pomocą opcji „Trasa między punktami”.</string>
<string name="message_need_calculate_route_before_show_graph">%1$s dane dostępne tylko na drogach, oblicz trasę, korzystając z opcji „Trasa między punktami”, aby wyświetlić wykresy.</string>
<string name="message_graph_will_be_available_after_recalculation">Proszę czekać.
\nWykres będzie dostępny po ponownym obliczeniu trasy.</string>
<string name="shared_string_local_maps">Mapy lokalne</string>
@ -3956,7 +3956,7 @@
<string name="subscription_paused_title">Subskrypcja OsmAnd Live została wstrzymana</string>
<string name="snowmobile_render_descr">Do jazdy skuterem śnieżnym z wyznaczonymi drogami i torami.</string>
<string name="message_you_need_add_two_points_to_show_graphs">Dodaj co najmniej dwa punkty</string>
<string name="subscription_payment_issue_title">Wystąpił problem z Twoją subskrypcją. Naciśnij przycisk, aby przejść do ustawień subskrypcji Google Play i naprawić metodę płatności.</string>
<string name="subscription_payment_issue_title">Stuknij przycisk, aby skonfigurować metodę płatności w Google Play i naprawić subskrypcję.</string>
<string name="subscription_on_hold_title">Subskrypcja OsmAnd Live jest wstrzymana</string>
<string name="user_login">Login</string>
<string name="login_open_street_map">Zaloguj się do OpenStreetMap</string>
@ -4021,4 +4021,7 @@
\n• Obsługa niestandardowych kolorów dla ulubionych i śledzenia punktów trasy
\n
\n</string>
<string name="profile_type_osmand_string">Profil OsmAnd</string>
<string name="profile_type_user_string">Profil użytkownika</string>
<string name="reverse_all_points">Odwróć wszystkie punkty</string>
</resources>

View file

@ -3894,4 +3894,6 @@
<string name="poi_water_source_tap">Toque</string>
<string name="poi_water_source_water_works">Estação de tratamento de água</string>
<string name="poi_water_source_tube_well">Bem embalado</string>
<string name="poi_weightbridge">Balança</string>
<string name="poi_ranger_station">Posto de guarda florestal</string>
</resources>

View file

@ -3890,4 +3890,8 @@
<string name="poi_water_source_tap">Isceta</string>
<string name="poi_water_source_water_works">Òperas idràulicas</string>
<string name="poi_water_source_tube_well">Putzu a tubu</string>
<string name="poi_weightbridge">Bilàntzia a ponte</string>
<string name="poi_ranger_station">Istatzione de sos rangers</string>
<string name="poi_lavoir">Sabunadòrgiu</string>
<string name="poi_waste_transfer_station">Istatzione de tramudòngiu de s\'arga</string>
</resources>

View file

@ -4013,4 +4013,7 @@
\n • Suportu pro colores personalizados pro sos preferidos e sos puntos de coladòrgiu de sas rastas
\n
\n</string>
<string name="profile_type_osmand_string">Profilu de OsmAnd</string>
<string name="profile_type_user_string">Profilu de s\'impreadore</string>
<string name="reverse_all_points">Fùrria totu sos puntos</string>
</resources>

View file

@ -4016,4 +4016,6 @@
\n• Podpora vlastných farieb pre obľúbené položky a sledovanie trasových bodov
\n
\n</string>
<string name="profile_type_osmand_string">Profil OsmAnd</string>
<string name="profile_type_user_string">Profil používateľa</string>
</resources>

View file

@ -3973,4 +3973,5 @@
\n</string>
<string name="profile_type_osmand_string">OsmAnd profili</string>
<string name="profile_type_user_string">Kullanıcı profili</string>
<string name="reverse_all_points">Tüm noktaları tersine çevir</string>
</resources>

View file

@ -3882,4 +3882,8 @@
<string name="poi_water_source_water_tank">Резервуар для води</string>
<string name="poi_water_source_lake">Озеро</string>
<string name="poi_water_source_river">Річка</string>
<string name="poi_ranger_station">Лісництво</string>
<string name="poi_weightbridge">Автомобільні ваги</string>
<string name="poi_lavoir">Громадська пральня</string>
<string name="poi_waste_transfer_station">Станція перевезення відходів</string>
</resources>

View file

@ -4012,4 +4012,7 @@
\n• Підтримка власних кольорів закладок та маршрутних точок треку
\n
\n</string>
<string name="profile_type_osmand_string">Профіль OsmAnd</string>
<string name="profile_type_user_string">Профіль користувача</string>
<string name="reverse_all_points">Повернути назад всі точки</string>
</resources>

View file

@ -3893,4 +3893,6 @@
<string name="poi_water_source_tap">點擊</string>
<string name="poi_water_source_water_works">自來水廠</string>
<string name="poi_water_source_tube_well">管井</string>
<string name="poi_weightbridge">地磅</string>
<string name="poi_ranger_station">護林員站</string>
</resources>

View file

@ -4318,4 +4318,13 @@
<string name="poi_water_source_well">Well</string>
<string name="poi_water_source_river">River</string>
<string name="poi_water_source_lake">Lake</string>
<string name="poi_ranger_station">Ranger station</string>
<string name="poi_weightbridge">Weightbridge</string>
<string name="poi_waste_transfer_station">Waste transfer station</string>
<string name="poi_lavoir">Lavoir</string>
</resources>

View file

@ -11,6 +11,7 @@
Thx - Hardy
-->
<string name="reverse_all_points">Reverse all points</string>
<string name="release_3_9">
• Added option to export and import all data including settings, resources, my places\n\n
• Plan Route: graphs for track segments with route, and added the ability to create and edit multiple track segments\n\n

View file

@ -56,7 +56,7 @@ public class AccessibilityPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.osmand_accessibility_description);
}

View file

@ -43,6 +43,7 @@ import net.osmand.aidl.tiles.ASqliteDbFile;
import net.osmand.aidlapi.customization.AProfile;
import net.osmand.aidlapi.info.AppInfoParams;
import net.osmand.aidlapi.map.ALatLon;
import net.osmand.aidlapi.navigation.ABlockedRoad;
import net.osmand.data.FavouritePoint;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
@ -62,6 +63,7 @@ import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.ColorDialogs;
import net.osmand.plus.helpers.ExternalApiHelper;
import net.osmand.plus.helpers.LockHelper;
@ -138,8 +140,11 @@ import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_UNSUPPORTED_FILE_
import static net.osmand.aidlapi.OsmandAidlConstants.COPY_FILE_WRITE_LOCK_ERROR;
import static net.osmand.aidlapi.OsmandAidlConstants.OK_RESPONSE;
import static net.osmand.plus.FavouritesDbHelper.FILE_TO_SAVE;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_ANGLE;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_LANES;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_NAME;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_POSSIBLY_LEFT;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_POSSIBLY_RIGHT;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_TURN;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DISTANCE;
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_IMMINENT;
@ -177,6 +182,7 @@ public class OsmandAidlApi {
private static final String AIDL_DATA = "aidl_data";
private static final String AIDL_URI = "aidl_uri";
private static final String AIDL_FORCE = "aidl_force";
private static final String AIDL_LOCATION_PERMISSION = "aidl_location_permission";
private static final String AIDL_SEARCH_QUERY = "aidl_search_query";
private static final String AIDL_SEARCH_LAT = "aidl_search_lat";
private static final String AIDL_SEARCH_LON = "aidl_search_lon";
@ -208,7 +214,7 @@ public class OsmandAidlApi {
private static final ApplicationMode DEFAULT_PROFILE = ApplicationMode.CAR;
private static final ApplicationMode[] VALID_PROFILES = new ApplicationMode[]{
private static final ApplicationMode[] VALID_PROFILES = new ApplicationMode[] {
ApplicationMode.CAR,
ApplicationMode.BICYCLE,
ApplicationMode.PEDESTRIAN
@ -287,7 +293,7 @@ public class OsmandAidlApi {
}
private void initOsmandTelegram() {
String[] packages = new String[]{"net.osmand.telegram", "net.osmand.telegram.debug"};
String[] packages = new String[] {"net.osmand.telegram", "net.osmand.telegram.debug"};
Intent intent = new Intent("net.osmand.telegram.InitApp");
for (String pack : packages) {
intent.setComponent(new ComponentName(pack, "net.osmand.telegram.InitAppBroadcastReceiver"));
@ -601,6 +607,7 @@ public class OsmandAidlApi {
final RoutingHelper routingHelper = app.getRoutingHelper();
boolean force = intent.getBooleanExtra(AIDL_FORCE, true);
final boolean locationPermission = intent.getBooleanExtra(AIDL_LOCATION_PERMISSION, false);
if (routingHelper.isFollowingMode() && !force) {
mapActivity.getMapActions().stopNavigationActionConfirm(new DialogInterface.OnDismissListener() {
@ -608,12 +615,12 @@ public class OsmandAidlApi {
public void onDismiss(DialogInterface dialog) {
MapActivity mapActivity = mapActivityRef.get();
if (mapActivity != null && !routingHelper.isFollowingMode()) {
ExternalApiHelper.startNavigation(mapActivity, start, startDesc, dest, destDesc, profile);
ExternalApiHelper.startNavigation(mapActivity, start, startDesc, dest, destDesc, profile, locationPermission);
}
}
});
} else {
ExternalApiHelper.startNavigation(mapActivity, start, startDesc, dest, destDesc, profile);
ExternalApiHelper.startNavigation(mapActivity, start, startDesc, dest, destDesc, profile, locationPermission);
}
}
}
@ -667,6 +674,7 @@ public class OsmandAidlApi {
if (searchLocation != null) {
final RoutingHelper routingHelper = app.getRoutingHelper();
boolean force = intent.getBooleanExtra(AIDL_FORCE, true);
final boolean locationPermission = intent.getBooleanExtra(AIDL_LOCATION_PERMISSION, false);
if (routingHelper.isFollowingMode() && !force) {
mapActivity.getMapActions().stopNavigationActionConfirm(new DialogInterface.OnDismissListener() {
@ -674,12 +682,14 @@ public class OsmandAidlApi {
public void onDismiss(DialogInterface dialog) {
MapActivity mapActivity = mapActivityRef.get();
if (mapActivity != null && !routingHelper.isFollowingMode()) {
ExternalApiHelper.searchAndNavigate(mapActivity, searchLocation, start, startDesc, profile, searchQuery, false);
ExternalApiHelper.searchAndNavigate(mapActivity, searchLocation, start,
startDesc, profile, searchQuery, false, locationPermission);
}
}
});
} else {
ExternalApiHelper.searchAndNavigate(mapActivity, searchLocation, start, startDesc, profile, searchQuery, false);
ExternalApiHelper.searchAndNavigate(mapActivity, searchLocation, start,
startDesc, profile, searchQuery, false, locationPermission);
}
}
}
@ -698,7 +708,8 @@ public class OsmandAidlApi {
GPXFile gpx = loadGpxFileFromIntent(mapActivity, intent);
if (gpx != null) {
boolean force = intent.getBooleanExtra(AIDL_FORCE, false);
ExternalApiHelper.saveAndNavigateGpx(mapActivity, gpx, force);
boolean locationPermission = intent.getBooleanExtra(AIDL_LOCATION_PERMISSION, false);
ExternalApiHelper.saveAndNavigateGpx(mapActivity, gpx, force, locationPermission);
}
}
}
@ -1652,8 +1663,8 @@ public class OsmandAidlApi {
}
boolean navigate(String startName, double startLat, double startLon,
String destName, double destLat, double destLon,
String profile, boolean force) {
String destName, double destLat, double destLon,
String profile, boolean force, boolean requestLocationPermission) {
Intent intent = new Intent();
intent.setAction(AIDL_NAVIGATE);
intent.putExtra(AIDL_START_NAME, startName);
@ -1664,13 +1675,14 @@ public class OsmandAidlApi {
intent.putExtra(AIDL_DEST_LON, destLon);
intent.putExtra(AIDL_PROFILE, profile);
intent.putExtra(AIDL_FORCE, force);
intent.putExtra(AIDL_LOCATION_PERMISSION, requestLocationPermission);
app.sendBroadcast(intent);
return true;
}
boolean navigateSearch(String startName, double startLat, double startLon,
String searchQuery, double searchLat, double searchLon,
String profile, boolean force) {
String searchQuery, double searchLat, double searchLon,
String profile, boolean force, boolean requestLocationPermission) {
Intent intent = new Intent();
intent.setAction(AIDL_NAVIGATE_SEARCH);
intent.putExtra(AIDL_START_NAME, startName);
@ -1681,6 +1693,7 @@ public class OsmandAidlApi {
intent.putExtra(AIDL_SEARCH_LON, searchLon);
intent.putExtra(AIDL_PROFILE, profile);
intent.putExtra(AIDL_FORCE, force);
intent.putExtra(AIDL_LOCATION_PERMISSION, requestLocationPermission);
app.sendBroadcast(intent);
return true;
}
@ -1720,12 +1733,13 @@ public class OsmandAidlApi {
return true;
}
boolean navigateGpx(String data, Uri uri, boolean force) {
boolean navigateGpx(String data, Uri uri, boolean force, boolean requestLocationPermission) {
Intent intent = new Intent();
intent.setAction(AIDL_NAVIGATE_GPX);
intent.putExtra(AIDL_DATA, data);
intent.putExtra(AIDL_URI, uri);
intent.putExtra(AIDL_FORCE, force);
intent.putExtra(AIDL_LOCATION_PERMISSION, requestLocationPermission);
app.sendBroadcast(intent);
return true;
}
@ -1791,6 +1805,9 @@ public class OsmandAidlApi {
RouteDirectionInfo a = ni.directionInfo;
bundle.putString(prefix + PARAM_NT_DIRECTION_NAME, RoutingHelper.formatStreetName(a.getStreetName(), a.getRef(), a.getDestinationName(), ""));
bundle.putString(prefix + PARAM_NT_DIRECTION_TURN, tt.toXmlString());
bundle.putFloat(prefix + PARAM_NT_DIRECTION_ANGLE, tt.getTurnAngle());
bundle.putBoolean(prefix + PARAM_NT_DIRECTION_POSSIBLY_LEFT, tt.isPossibleLeftTurn());
bundle.putBoolean(prefix + PARAM_NT_DIRECTION_POSSIBLY_RIGHT, tt.isPossibleRightTurn());
if (tt.getLanes() != null) {
bundle.putString(prefix + PARAM_NT_DIRECTION_LANES, Arrays.toString(tt.getLanes()));
}
@ -1798,7 +1815,7 @@ public class OsmandAidlApi {
}
boolean search(final String searchQuery, final int searchType, final double latitude, final double longitude,
final int radiusLevel, final int totalLimit, final SearchCompleteCallback callback) {
final int radiusLevel, final int totalLimit, final SearchCompleteCallback callback) {
if (Algorithms.isEmpty(searchQuery) || latitude == 0 || longitude == 0 || callback == null) {
return false;
}
@ -2167,7 +2184,7 @@ public class OsmandAidlApi {
}
boolean getBitmapForGpx(final Uri gpxUri, final float density, final int widthPixels,
final int heightPixels, final int color, final GpxBitmapCreatedCallback callback) {
final int heightPixels, final int color, final GpxBitmapCreatedCallback callback) {
if (gpxUri == null || callback == null) {
return false;
}
@ -2368,6 +2385,25 @@ public class OsmandAidlApi {
return true;
}
public boolean getBlockedRoads(List<ABlockedRoad> blockedRoads) {
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
for (AvoidRoadInfo info : impassableRoads.values()) {
blockedRoads.add(new ABlockedRoad(info.id, info.latitude, info.longitude, info.direction, info.name, info.appModeKey));
}
return true;
}
public boolean addRoadBlock(ABlockedRoad road) {
LatLon latLon = new LatLon(road.getLatitude(), road.getLongitude());
app.getAvoidSpecificRoads().addImpassableRoad(null, latLon, false, false, null);
return true;
}
public boolean removeRoadBlock(ABlockedRoad road) {
app.getAvoidSpecificRoads().removeImpassableRoad(new LatLon(road.getLatitude(), road.getLongitude()));
return true;
}
private static class FileCopyInfo {
long startTime;
long lastAccessTime;

View file

@ -44,6 +44,7 @@ import net.osmand.aidl.gpx.RemoveGpxParams;
import net.osmand.aidl.gpx.ShowGpxParams;
import net.osmand.aidl.gpx.StartGpxRecordingParams;
import net.osmand.aidl.gpx.StopGpxRecordingParams;
import net.osmand.aidl.lock.SetLockStateParams;
import net.osmand.aidl.map.ALatLon;
import net.osmand.aidl.map.SetMapLocationParams;
import net.osmand.aidl.maplayer.AddMapLayerParams;
@ -85,10 +86,9 @@ import net.osmand.aidl.quickaction.QuickActionParams;
import net.osmand.aidl.search.SearchParams;
import net.osmand.aidl.search.SearchResult;
import net.osmand.aidl.tiles.ASqliteDbFile;
import net.osmand.aidl.lock.SetLockStateParams;
import net.osmand.data.LatLon;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -736,7 +736,7 @@ public class OsmandAidlService extends Service implements AidlCallbackListener {
return params != null && api != null && api.navigate(
params.getStartName(), params.getStartLat(), params.getStartLon(),
params.getDestName(), params.getDestLat(), params.getDestLon(),
params.getProfile(), params.isForce());
params.getProfile(), params.isForce(), params.isNeedLocationPermission());
} catch (Exception e) {
handleException(e);
return false;
@ -747,7 +747,8 @@ public class OsmandAidlService extends Service implements AidlCallbackListener {
public boolean navigateGpx(NavigateGpxParams params) {
try {
OsmandAidlApi api = getApi("navigateGpx");
return params != null && api != null && api.navigateGpx(params.getData(), params.getUri(), params.isForce());
return params != null && api != null && api.navigateGpx(params.getData(), params.getUri(),
params.isForce(), params.isNeedLocationPermission());
} catch (Exception e) {
handleException(e);
return false;
@ -857,7 +858,7 @@ public class OsmandAidlService extends Service implements AidlCallbackListener {
return params != null && api != null && api.navigateSearch(
params.getStartName(), params.getStartLat(), params.getStartLon(),
params.getSearchQuery(), params.getSearchLat(), params.getSearchLon(),
params.getProfile(), params.isForce());
params.getProfile(), params.isForce(), params.isNeedLocationPermission());
} catch (Exception e) {
handleException(e);
return false;
@ -1328,6 +1329,7 @@ public class OsmandAidlService extends Service implements AidlCallbackListener {
return false;
}
}
@Override
public boolean setLockState(SetLockStateParams params) {
try {

View file

@ -73,13 +73,16 @@ import net.osmand.aidlapi.navdrawer.NavDrawerFooterParams;
import net.osmand.aidlapi.navdrawer.NavDrawerHeaderParams;
import net.osmand.aidlapi.navdrawer.NavDrawerItem;
import net.osmand.aidlapi.navdrawer.SetNavDrawerItemsParams;
import net.osmand.aidlapi.navigation.ABlockedRoad;
import net.osmand.aidlapi.navigation.ANavigationUpdateParams;
import net.osmand.aidlapi.navigation.ANavigationVoiceRouterMessageParams;
import net.osmand.aidlapi.navigation.AddBlockedRoadParams;
import net.osmand.aidlapi.navigation.MuteNavigationParams;
import net.osmand.aidlapi.navigation.NavigateGpxParams;
import net.osmand.aidlapi.navigation.NavigateParams;
import net.osmand.aidlapi.navigation.NavigateSearchParams;
import net.osmand.aidlapi.navigation.PauseNavigationParams;
import net.osmand.aidlapi.navigation.RemoveBlockedRoadParams;
import net.osmand.aidlapi.navigation.ResumeNavigationParams;
import net.osmand.aidlapi.navigation.StopNavigationParams;
import net.osmand.aidlapi.navigation.UnmuteNavigationParams;
@ -693,7 +696,7 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
return params != null && api != null && api.navigate(
params.getStartName(), params.getStartLat(), params.getStartLon(),
params.getDestName(), params.getDestLat(), params.getDestLon(),
params.getProfile(), params.isForce());
params.getProfile(), params.isForce(), params.isNeedLocationPermission());
} catch (Exception e) {
handleException(e);
return false;
@ -704,7 +707,8 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
public boolean navigateGpx(NavigateGpxParams params) {
try {
OsmandAidlApi api = getApi("navigateGpx");
return params != null && api != null && api.navigateGpx(params.getData(), params.getUri(), params.isForce());
return params != null && api != null && api.navigateGpx(params.getData(), params.getUri(),
params.isForce(), params.isNeedLocationPermission());
} catch (Exception e) {
handleException(e);
return false;
@ -814,7 +818,7 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
return params != null && api != null && api.navigateSearch(
params.getStartName(), params.getStartLat(), params.getStartLon(),
params.getSearchQuery(), params.getSearchLat(), params.getSearchLon(),
params.getProfile(), params.isForce());
params.getProfile(), params.isForce(), params.isNeedLocationPermission());
} catch (Exception e) {
handleException(e);
return false;
@ -1396,6 +1400,49 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
return false;
}
}
@Override
public boolean getBlockedRoads(List<ABlockedRoad> blockedRoads) {
try {
OsmandAidlApi api = getApi("getBlockedRoads");
return api != null && api.getBlockedRoads(blockedRoads);
} catch (Exception e) {
handleException(e);
return false;
}
}
@Override
public boolean addRoadBlock(AddBlockedRoadParams params) {
try {
OsmandAidlApi api = getApi("addRoadBlock");
if (params != null && api != null) {
ABlockedRoad road = params.getBlockedRoad();
if (road != null) {
return api.addRoadBlock(road);
}
}
} catch (Exception e) {
handleException(e);
}
return false;
}
@Override
public boolean removeRoadBlock(RemoveBlockedRoadParams params) {
try {
OsmandAidlApi api = getApi("removeRoadBlock");
if (params != null && api != null) {
ABlockedRoad road = params.getBlockedRoad();
if (road != null) {
return api.removeRoadBlock(road);
}
}
} catch (Exception e) {
handleException(e);
}
return false;
}
};
private void setCustomization(OsmandAidlApi api, CustomizationInfoParams params) {

View file

@ -9,15 +9,18 @@ public class NavigateGpxParams implements Parcelable {
private String data;
private Uri uri;
private boolean force;
private boolean needLocationPermission;
public NavigateGpxParams(String data, boolean force) {
public NavigateGpxParams(String data, boolean force, boolean needLocationPermission) {
this.data = data;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateGpxParams(Uri uri, boolean force) {
public NavigateGpxParams(Uri uri, boolean force, boolean needLocationPermission) {
this.uri = uri;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateGpxParams(Parcel in) {
@ -48,22 +51,27 @@ public class NavigateGpxParams implements Parcelable {
return force;
}
public boolean isNeedLocationPermission() {
return needLocationPermission;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(data);
out.writeParcelable(uri, flags);
out.writeByte((byte) (force ? 1 : 0));
out.writeByte((byte) (needLocationPermission ? 1 : 0));
}
private void readFromParcel(Parcel in) {
data = in.readString();
uri = in.readParcelable(Uri.class.getClassLoader());
force = in.readByte() != 0;
needLocationPermission = in.readByte() != 0;
}
@Override
public int describeContents() {
return 0;
}
}

View file

@ -13,8 +13,10 @@ public class NavigateParams implements Parcelable {
private double destLon;
private String profile;
private boolean force;
private boolean needLocationPermission;
public NavigateParams(String startName, double startLat, double startLon, String destName, double destLat, double destLon, String profile, boolean force) {
public NavigateParams(String startName, double startLat, double startLon, String destName, double destLat,
double destLon, String profile, boolean force, boolean needLocationPermission) {
this.startName = startName;
this.startLat = startLat;
this.startLon = startLon;
@ -23,6 +25,7 @@ public class NavigateParams implements Parcelable {
this.destLon = destLon;
this.profile = profile;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateParams(Parcel in) {
@ -73,6 +76,10 @@ public class NavigateParams implements Parcelable {
return force;
}
public boolean isNeedLocationPermission() {
return needLocationPermission;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(startName);
@ -83,6 +90,7 @@ public class NavigateParams implements Parcelable {
out.writeDouble(destLon);
out.writeString(profile);
out.writeByte((byte) (force ? 1 : 0));
out.writeByte((byte) (needLocationPermission ? 1 : 0));
}
private void readFromParcel(Parcel in) {
@ -94,11 +102,11 @@ public class NavigateParams implements Parcelable {
destLon = in.readDouble();
profile = in.readString();
force = in.readByte() != 0;
needLocationPermission = in.readByte() != 0;
}
@Override
public int describeContents() {
return 0;
}
}

View file

@ -13,10 +13,11 @@ public class NavigateSearchParams implements Parcelable {
private double searchLon;
private String profile;
private boolean force;
private boolean needLocationPermission;
public NavigateSearchParams(String startName, double startLat, double startLon,
String searchQuery, double searchLat, double searchLon,
String profile, boolean force) {
String profile, boolean force, boolean needLocationPermission) {
this.startName = startName;
this.startLat = startLat;
this.startLon = startLon;
@ -25,6 +26,7 @@ public class NavigateSearchParams implements Parcelable {
this.searchLon = searchLon;
this.profile = profile;
this.force = force;
this.needLocationPermission = needLocationPermission;
}
public NavigateSearchParams(Parcel in) {
@ -75,6 +77,10 @@ public class NavigateSearchParams implements Parcelable {
return force;
}
public boolean isNeedLocationPermission() {
return needLocationPermission;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(startName);
@ -85,6 +91,7 @@ public class NavigateSearchParams implements Parcelable {
out.writeByte((byte) (force ? 1 : 0));
out.writeDouble(searchLat);
out.writeDouble(searchLon);
out.writeByte((byte) (needLocationPermission ? 1 : 0));
}
private void readFromParcel(Parcel in) {
@ -96,11 +103,11 @@ public class NavigateSearchParams implements Parcelable {
force = in.readByte() != 0;
searchLat = in.readDouble();
searchLon = in.readDouble();
needLocationPermission = in.readByte() != 0;
}
@Override
public int describeContents() {
return 0;
}
}

View file

@ -461,7 +461,6 @@ public class AppInitializer implements IProgress {
// TODOTRAVEL_OBF_HELPER check ResourceManager and use TravelObfHelper
app.travelHelper = !TravelDbHelper.checkIfDbFileExists(app) ? new TravelObfHelper(app) : new TravelDbHelper(app);
app.travelHelper.initializeDataOnAppStartup();
app.travelHelper = startupInit(app.travelHelper, TravelHelper.class);
app.lockHelper = startupInit(new LockHelper(app), LockHelper.class);
@ -661,7 +660,7 @@ public class AppInitializer implements IProgress {
initPoiTypes();
notifyEvent(InitEvents.POI_TYPES_INITIALIZED);
app.resourceManager.reloadIndexesOnStart(this, warnings);
app.travelHelper.initializeDataOnAppStartup();
// native depends on renderers
initNativeCore();
notifyEvent(InitEvents.NATIVE_INITIALIZED);

View file

@ -1195,6 +1195,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
getMapLayers().getContextMenuLayer().enterAddGpxPointMode(newGpxPoint);
} else if (toShow instanceof GpxData) {
hideContextAndRouteInfoMenues();
GpxData gpxData = (GpxData) toShow;
QuadRect qr = gpxData.getRect();
mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);

View file

@ -581,7 +581,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.audionotes_plugin_description);
}

View file

@ -37,7 +37,7 @@ public class OsmandDevelopmentPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.osmand_development_plugin_description);
}

View file

@ -26,7 +26,6 @@ import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadPoint;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
@ -35,6 +34,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.RouteSegmentSearchResult;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.views.layers.ContextMenuLayer;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
@ -59,7 +59,7 @@ public class AvoidSpecificRoads {
loadImpassableRoads();
}
public void loadImpassableRoads(){
public void loadImpassableRoads() {
for (AvoidRoadInfo avoidRoadInfo : app.getSettings().getImpassableRoadPoints()) {
impassableRoads.put(new LatLon(avoidRoadInfo.latitude, avoidRoadInfo.longitude), avoidRoadInfo);
}
@ -390,7 +390,14 @@ public class AvoidSpecificRoads {
if (avoidRoadInfo == null) {
avoidRoadInfo = new AvoidRoadInfo();
}
avoidRoadInfo.id = object != null ? object.id : 0;
if (object != null) {
avoidRoadInfo.id = object.id;
// avoidRoadInfo.direction = object.directionRoute(0, true);
avoidRoadInfo.direction = Double.NaN;
} else {
avoidRoadInfo.id = 0;
avoidRoadInfo.direction = Double.NaN;
}
avoidRoadInfo.latitude = lat;
avoidRoadInfo.longitude = lon;
avoidRoadInfo.appModeKey = appModeKey;
@ -400,6 +407,7 @@ public class AvoidSpecificRoads {
public static class AvoidRoadInfo {
public long id;
public double direction = Double.NaN;
public double latitude;
public double longitude;
public String name;

View file

@ -30,6 +30,7 @@ import net.osmand.data.PointDescription;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
@ -129,6 +130,7 @@ public class ExternalApiHelper {
public static final String PARAM_URI = "uri";
public static final String PARAM_DATA = "data";
public static final String PARAM_FORCE = "force";
public static final String PARAM_LOCATION_PERMISSION = "location_permission";
public static final String PARAM_START_NAME = "start_name";
public static final String PARAM_DEST_NAME = "dest_name";
@ -151,6 +153,9 @@ public class ExternalApiHelper {
public static final String PARAM_NT_DIRECTION_NAME = "turn_name";
public static final String PARAM_NT_DIRECTION_TURN = "turn_type";
public static final String PARAM_NT_DIRECTION_LANES = "turn_lanes";
public static final String PARAM_NT_DIRECTION_ANGLE = "turn_angle";
public static final String PARAM_NT_DIRECTION_POSSIBLY_LEFT = "turn_possibly_left";
public static final String PARAM_NT_DIRECTION_POSSIBLY_RIGHT = "turn_possibly_right";
public static final String PARAM_CLOSE_AFTER_COMMAND = "close_after_command";
@ -237,7 +242,8 @@ public class ExternalApiHelper {
if (gpx != null) {
if (navigate) {
boolean force = uri.getBooleanQueryParameter(PARAM_FORCE, false);
saveAndNavigateGpx(mapActivity, gpx, force);
boolean locationPermission = uri.getBooleanQueryParameter(PARAM_LOCATION_PERMISSION, false);
saveAndNavigateGpx(mapActivity, gpx, force, locationPermission);
} else {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
}
@ -289,6 +295,7 @@ public class ExternalApiHelper {
final PointDescription destDesc = new PointDescription(PointDescription.POINT_TYPE_LOCATION, destName);
boolean force = uri.getBooleanQueryParameter(PARAM_FORCE, false);
final boolean locationPermission = uri.getBooleanQueryParameter(PARAM_LOCATION_PERMISSION, false);
final RoutingHelper routingHelper = app.getRoutingHelper();
if (routingHelper.isFollowingMode() && !force) {
@ -297,12 +304,12 @@ public class ExternalApiHelper {
@Override
public void onDismiss(DialogInterface dialog) {
if (!routingHelper.isFollowingMode()) {
startNavigation(mapActivity, start, startDesc, dest, destDesc, profile);
startNavigation(mapActivity, start, startDesc, dest, destDesc, profile, locationPermission);
}
}
});
} else {
startNavigation(mapActivity, start, startDesc, dest, destDesc, profile);
startNavigation(mapActivity, start, startDesc, dest, destDesc, profile, locationPermission);
}
}
@ -348,6 +355,7 @@ public class ExternalApiHelper {
resultCode = RESULT_CODE_ERROR_SEARCH_LOCATION_UNDEFINED;
} else {
boolean force = uri.getBooleanQueryParameter(PARAM_FORCE, false);
final boolean locationPermission = uri.getBooleanQueryParameter(PARAM_LOCATION_PERMISSION, false);
final RoutingHelper routingHelper = app.getRoutingHelper();
if (routingHelper.isFollowingMode() && !force) {
@ -356,12 +364,12 @@ public class ExternalApiHelper {
@Override
public void onDismiss(DialogInterface dialog) {
if (!routingHelper.isFollowingMode()) {
searchAndNavigate(mapActivity, searchLocation, start, startDesc, profile, searchQuery, showSearchResults);
searchAndNavigate(mapActivity, searchLocation, start, startDesc, profile, searchQuery, showSearchResults, locationPermission);
}
}
});
} else {
searchAndNavigate(mapActivity, searchLocation, start, startDesc, profile, searchQuery, showSearchResults);
searchAndNavigate(mapActivity, searchLocation, start, startDesc, profile, searchQuery, showSearchResults, locationPermission);
}
resultCode = Activity.RESULT_OK;
}
@ -629,7 +637,8 @@ public class ExternalApiHelper {
return null;
}
public static void saveAndNavigateGpx(MapActivity mapActivity, final GPXFile gpxFile, final boolean force) {
public static void saveAndNavigateGpx(MapActivity mapActivity, final GPXFile gpxFile,
final boolean force, final boolean checkLocationPermission) {
final WeakReference<MapActivity> mapActivityRef = new WeakReference<>(mapActivity);
if (Algorithms.isEmpty(gpxFile.path)) {
@ -670,12 +679,12 @@ public class ExternalApiHelper {
public void onDismiss(DialogInterface dialog) {
MapActivity mapActivity = mapActivityRef.get();
if (mapActivity != null && !routingHelper.isFollowingMode()) {
ExternalApiHelper.startNavigation(mapActivity, gpxFile);
ExternalApiHelper.startNavigation(mapActivity, gpxFile, checkLocationPermission);
}
}
});
} else {
startNavigation(mapActivity, gpxFile);
startNavigation(mapActivity, gpxFile, checkLocationPermission);
}
}
}
@ -690,6 +699,9 @@ public class ExternalApiHelper {
RouteDirectionInfo a = ni.directionInfo;
result.putExtra(prefix + PARAM_NT_DIRECTION_NAME, RoutingHelper.formatStreetName(a.getStreetName(), a.getRef(), a.getDestinationName(), ""));
result.putExtra(prefix + PARAM_NT_DIRECTION_TURN, tt.toXmlString());
result.putExtra(prefix + PARAM_NT_DIRECTION_ANGLE, tt.getTurnAngle());
result.putExtra(prefix + PARAM_NT_DIRECTION_POSSIBLY_LEFT, tt.isPossibleLeftTurn());
result.putExtra(prefix + PARAM_NT_DIRECTION_POSSIBLY_RIGHT, tt.isPossibleRightTurn());
if (tt.getLanes() != null) {
result.putExtra(prefix + PARAM_NT_DIRECTION_LANES, Arrays.toString(tt.getLanes()));
}
@ -705,23 +717,22 @@ public class ExternalApiHelper {
mapContextMenu.show(new LatLon(lat, lon), pointDescription, object);
}
static public void startNavigation(MapActivity mapActivity,
@NonNull GPXFile gpx) {
startNavigation(mapActivity, gpx, null, null, null, null, null);
static public void startNavigation(MapActivity mapActivity, @NonNull GPXFile gpx, boolean checkLocationPermission) {
startNavigation(mapActivity, gpx, null, null, null, null, null, checkLocationPermission);
}
static public void startNavigation(MapActivity mapActivity,
@Nullable LatLon from, @Nullable PointDescription fromDesc,
@Nullable LatLon to, @Nullable PointDescription toDesc,
@NonNull ApplicationMode mode) {
startNavigation(mapActivity, null, from, fromDesc, to, toDesc, mode);
@NonNull ApplicationMode mode, boolean checkLocationPermission) {
startNavigation(mapActivity, null, from, fromDesc, to, toDesc, mode, checkLocationPermission);
}
static private void startNavigation(MapActivity mapActivity,
GPXFile gpx,
LatLon from, PointDescription fromDesc,
LatLon to, PointDescription toDesc,
ApplicationMode mode) {
ApplicationMode mode, boolean checkLocationPermission) {
OsmandApplication app = mapActivity.getMyApplication();
RoutingHelper routingHelper = app.getRoutingHelper();
if (gpx == null) {
@ -745,12 +756,15 @@ public class ExternalApiHelper {
app.getRoutingHelper().notifyIfRouteIsCalculated();
routingHelper.setCurrentLocation(app.getLocationProvider().getLastKnownLocation(), false);
}
if (checkLocationPermission) {
OsmAndLocationProvider.requestFineLocationPermissionIfNeeded(mapActivity);
}
}
static public void searchAndNavigate(@NonNull MapActivity mapActivity, @NonNull final LatLon searchLocation,
@Nullable final LatLon from, @Nullable final PointDescription fromDesc,
@NonNull final ApplicationMode mode, @NonNull final String searchQuery,
final boolean showSearchResults) {
final boolean showSearchResults, final boolean checkLocationPermission) {
final WeakReference<MapActivity> mapActivityRef = new WeakReference<>(mapActivity);
OsmandApplication app = mapActivity.getMyApplication();
@ -791,7 +805,7 @@ public class ExternalApiHelper {
LatLon to = new LatLon(res.getLatitude(), res.getLongitude());
PointDescription toDesc = new PointDescription(
PointDescription.POINT_TYPE_TARGET, res.getLocalName() + ", " + res.getLocalTypeName());
startNavigation(mapActivity, from, fromDesc, to, toDesc, mode);
startNavigation(mapActivity, from, fromDesc, to, toDesc, mode, checkLocationPermission);
} else {
mapActivity.getMyApplication().showToastMessage(mapActivity.getString(R.string.search_nothing_found));
}

View file

@ -39,15 +39,17 @@ import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*
*/
public class WaypointDialogHelper {
private MapActivity mapActivity;
private OsmandApplication app;
private WaypointHelper waypointHelper;
private List<WaypointDialogHelperCallback> helperCallbacks= new ArrayList<>();
private List<WaypointDialogHelperCallback> helperCallbacks = new ArrayList<>();
private boolean flat;
private List<LocationPointWrapper> deletedPoints;
@ -242,8 +244,8 @@ public class WaypointDialogHelper {
// switch start & finish
public static void switchStartAndFinish(TargetPointsHelper targetPointsHelper, TargetPoint finish,
Activity ctx, TargetPoint start, OsmandApplication app,
WaypointDialogHelper helper) {
Activity ctx, TargetPoint start, OsmandApplication app,
WaypointDialogHelper helper) {
if (finish == null) {
app.showShortToastMessage(R.string.mark_final_location_first);
} else {
@ -263,6 +265,20 @@ public class WaypointDialogHelper {
}
}
public static void reverseAllPoints(OsmandApplication app, Activity ctx,
WaypointDialogHelper helper) {
TargetPointsHelper targets = app.getTargetPointsHelper();
if (!targets.getAllPoints().isEmpty()) {
List<TargetPoint> points = targets.getAllPoints();
Collections.reverse(points);
TargetPoint start = points.get(0);
targets.setStartPoint(start.point, false, start.getOriginalPointDescription());
points.remove(start);
targets.reorderAllTargetPoints(points, true);
updateControls(ctx, helper);
}
}
public static void updateControls(Activity ctx, WaypointDialogHelper helper) {
if (helper != null && helper.helperCallbacks != null) {
for (WaypointDialogHelperCallback callback : helper.helperCallbacks) {
@ -278,7 +294,7 @@ public class WaypointDialogHelper {
}
public static void replaceStartWithFirstIntermediate(TargetPointsHelper targetPointsHelper, Activity ctx,
WaypointDialogHelper helper) {
WaypointDialogHelper helper) {
List<TargetPoint> intermediatePoints = targetPointsHelper.getIntermediatePointsWithTarget();
TargetPoint firstIntermediate = intermediatePoints.remove(0);
targetPointsHelper.setStartPoint(new LatLon(firstIntermediate.getLatitude(),
@ -443,7 +459,8 @@ public class WaypointDialogHelper {
@Override
public void createMenuItems(Bundle savedInstanceState) {
items.add(new TitleItem(getString(R.string.shared_string_options)));
final OsmandApplication app = requiredMyApplication();
final TargetPointsHelper targetsHelper = app.getTargetPointsHelper();
BaseBottomSheetItem sortDoorToDoorItem = new SimpleBottomSheetItem.Builder()
.setIcon(getContentIcon(R.drawable.ic_action_sort_door_to_door))
.setTitle(getString(R.string.intermediate_items_sort_by_distance))
@ -491,6 +508,30 @@ public class WaypointDialogHelper {
.create();
items.add(reorderStartAndFinishItem);
BaseBottomSheetItem reorderAllItems = new SimpleBottomSheetItem.Builder()
.setIcon(getContentIcon(R.drawable.ic_action_sort_reverse_order))
.setTitle(getString(R.string.reverse_all_points))
.setLayoutId(R.layout.bottom_sheet_item_simple)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
WaypointDialogHelper.reverseAllPoints(
app,
mapActivity,
mapActivity.getDashboard().getWaypointDialogHelper()
);
}
dismiss();
}
})
.create();
int intermediateSize = targetsHelper.getIntermediatePoints().size();
if (intermediateSize > 2) {
items.add(reorderAllItems);
}
items.add(new DividerHalfItem(getContext()));
final BaseBottomSheetItem[] addWaypointItem = new BaseBottomSheetItem[1];

View file

@ -83,7 +83,7 @@ public class MapillaryPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.plugin_mapillary_descr);
}

View file

@ -70,13 +70,14 @@ import net.osmand.plus.measurementtool.command.MovePointCommand;
import net.osmand.plus.measurementtool.command.RemovePointCommand;
import net.osmand.plus.measurementtool.command.ReorderPointCommand;
import net.osmand.plus.measurementtool.command.ReversePointsCommand;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DialogMode;
import net.osmand.plus.measurementtool.command.SplitPointsCommand;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.OnAppModeConfiguredCallback;
import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DialogMode;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.layers.MapControlsLayer;
import net.osmand.plus.views.layers.MapControlsLayer.MapControlsThemeInfoProvider;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView;
@ -108,8 +109,8 @@ import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCo
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener,
SaveAsNewTrackFragmentListener, MapControlsLayer.MapControlsThemeInfoProvider,
RouteOptionsBottomSheet.OnAppModeConfiguredCallback{
SaveAsNewTrackFragmentListener, MapControlsThemeInfoProvider,
OnAppModeConfiguredCallback {
public static final String TAG = MeasurementToolFragment.class.getSimpleName();
public static final String TAPS_DISABLED_KEY = "taps_disabled_key";
@ -179,7 +180,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
return mainView.getHeight();
}
public boolean shouldShowXAxisPoints () {
public boolean shouldShowXAxisPoints() {
return false;
}
}
@ -546,7 +547,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
if (savedInstanceState == null) {
if (fileName != null) {
addNewGpxData(getGpxFile(fileName));
} else if (editingCtx.isApproximationNeeded()) {
} else if (editingCtx.isApproximationNeeded() && isFollowTrackMode()) {
enterApproximationMode(mapActivity);
}
} else {

View file

@ -117,7 +117,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.record_plugin_description);
}

View file

@ -17,6 +17,7 @@ import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationCompat.BigTextStyle;
import androidx.core.app.NotificationCompat.Builder;
import net.osmand.Location;
import net.osmand.plus.NavigationService;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
@ -77,7 +78,7 @@ public class NavigationNotification extends OsmandNotification {
RoutingHelper routingHelper = app.getRoutingHelper();
routingHelper.setRoutePlanningMode(false);
routingHelper.setFollowingMode(true);
routingHelper.setCurrentLocation(app.getLocationProvider().getLastKnownLocation(), false);
routingHelper.setCurrentLocation(getLastKnownLocation(), false);
}
}, new IntentFilter(OSMAND_RESUME_NAVIGATION_SERVICE_ACTION));
@ -136,10 +137,15 @@ public class NavigationNotification extends OsmandNotification {
if (service != null && (service.getUsedBy() & USED_BY_NAVIGATION) != 0) {
color = app.getResources().getColor(R.color.osmand_orange);
String distanceStr = OsmAndFormatter.getFormattedDistance(app.getRoutingHelper().getLeftDistance(), app);
String timeStr = OsmAndFormatter.getFormattedDuration(app.getRoutingHelper().getLeftTime(), app);
String distanceStr = OsmAndFormatter.getFormattedDistance(routingHelper.getLeftDistance(), app);
String timeStr = OsmAndFormatter.getFormattedDuration(routingHelper.getLeftTime(), app);
String etaStr = SimpleDateFormat.getTimeInstance(DateFormat.SHORT)
.format(new Date(System.currentTimeMillis() + app.getRoutingHelper().getLeftTime() * 1000));
.format(new Date(System.currentTimeMillis() + routingHelper.getLeftTime() * 1000));
String speedStr = null;
Location location = getLastKnownLocation();
if (location != null && location.hasSpeed()) {
speedStr = OsmAndFormatter.getFormattedSpeed(location.getSpeed(), app);
}
TurnType turnType = null;
boolean deviatedFromRoute;
@ -199,9 +205,12 @@ public class NavigationNotification extends OsmandNotification {
notificationText.append("\n");
}
}
notificationText.append(distanceStr).append("").append(timeStr).append("").append(etaStr);
notificationText.append(distanceStr)
.append("").append(timeStr)
.append("").append(etaStr);
if (speedStr != null) {
notificationText.append("").append(speedStr);
}
} else {
notificationTitle = app.getString(R.string.shared_string_navigation);
String error = routingHelper.getLastRouteCalcErrorShort();
@ -211,7 +220,6 @@ public class NavigationNotification extends OsmandNotification {
notificationText.append(error);
}
}
} else if (routingHelper.isRoutePlanningMode() && routingHelper.isPauseNavigation()) {
ongoing = false;
notificationTitle = app.getString(R.string.shared_string_navigation);
@ -266,6 +274,10 @@ public class NavigationNotification extends OsmandNotification {
}
}
private Location getLastKnownLocation() {
return app.getLocationProvider().getLastKnownLocation();
}
public Bitmap drawableToBitmap(Drawable drawable) {
int height = (int) app.getResources().getDimension(android.R.dimen.notification_large_icon_height);
int width = (int) app.getResources().getDimension(android.R.dimen.notification_large_icon_width);

View file

@ -42,7 +42,7 @@ public class NauticalMapsPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(net.osmand.plus.R.string.plugin_nautical_descr);
}

View file

@ -378,7 +378,7 @@ public class OsmEditingPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.osm_editing_plugin_description);
}

View file

@ -168,7 +168,7 @@ public class ParkingPositionPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.osmand_parking_plugin_description);
}

View file

@ -89,7 +89,7 @@ public class OsmandRasterMapsPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.osmand_rastermaps_plugin_description);
}

View file

@ -801,7 +801,7 @@ public class ResourceManager {
return warnings;
}
private List<BinaryMapIndexReader> getTravelRepositories() {
public List<BinaryMapIndexReader> getTravelRepositories() {
List<String> fileNames = new ArrayList<>(travelRepositories.keySet());
Collections.sort(fileNames, Algorithms.getStringVersionComparator());
List<BinaryMapIndexReader> res = new ArrayList<>();
@ -814,7 +814,7 @@ public class ResourceManager {
return res;
}
private List<BinaryMapIndexReader> getTravelRepositories(double topLat, double leftLon, double bottomLat, double rightLon) {
public List<BinaryMapIndexReader> getTravelRepositories(double topLat, double leftLon, double bottomLat, double rightLon) {
List<String> fileNames = new ArrayList<>(travelRepositories.keySet());
Collections.sort(fileNames, Algorithms.getStringVersionComparator());
int leftX31 = MapUtils.get31TileNumberX(leftLon);

View file

@ -101,7 +101,8 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
DIRECTIONS(),
PLAN_ROUTE(MuteSoundRoutingParameter.class,
RouteSimulationItem.class,
GpxLocalRoutingParameter.class);
GpxLocalRoutingParameter.class,
ShowAlongTheRouteItem.class);
private final Class<? extends LocalRoutingParameter>[] excludeParameters;

View file

@ -92,6 +92,14 @@ public class ApplicationMode {
.icon(R.drawable.ic_action_pedestrian_dark)
.description(R.string.base_profile_descr_pedestrian).reg();
public static final ApplicationMode TRUCK = create(ApplicationMode.CAR, R.string.app_mode_truck, "truck")
.icon(R.drawable.ic_action_truck_dark)
.description(R.string.app_mode_truck).reg();
public static final ApplicationMode MOTORCYCLE = create(ApplicationMode.CAR, R.string.app_mode_motorcycle, "motorcycle")
.icon(R.drawable.ic_action_motorcycle_dark)
.description(R.string.app_mode_motorcycle).reg();
public static final ApplicationMode PUBLIC_TRANSPORT = createBase(R.string.app_mode_public_transport, "public_transport")
.icon(R.drawable.ic_action_bus_dark)
.description(R.string.base_profile_descr_public_transport).reg();
@ -108,14 +116,6 @@ public class ApplicationMode {
.icon(R.drawable.ic_action_skiing)
.description(R.string.base_profile_descr_ski).reg();
public static final ApplicationMode TRUCK = create(ApplicationMode.CAR, R.string.app_mode_truck, "truck")
.icon(R.drawable.ic_action_truck_dark)
.description(R.string.app_mode_truck).reg();
public static final ApplicationMode MOTORCYCLE = create(ApplicationMode.CAR, R.string.app_mode_motorcycle, "motorcycle")
.icon(R.drawable.ic_action_motorcycle_dark)
.description(R.string.app_mode_motorcycle).reg();
public static List<ApplicationMode> values(OsmandApplication app) {
if (customizationListener == null) {
customizationListener = new OsmAndAppCustomization.OsmAndAppCustomizationListener() {
@ -512,6 +512,14 @@ public class ApplicationMode {
mode.app = app;
mode.updateAppModeIcon();
}
if (app.getSettings().APP_MODE_ORDER.isSetForMode(PEDESTRIAN)) {
if (!app.getSettings().APP_MODE_ORDER.isSetForMode(TRUCK)) {
TRUCK.setOrder(PEDESTRIAN.getOrder() + 1);
}
if (!app.getSettings().APP_MODE_ORDER.isSetForMode(MOTORCYCLE)) {
MOTORCYCLE.setOrder(PEDESTRIAN.getOrder() + 1);
}
}
}
private static void initCustomModes(OsmandApplication app) {
@ -606,7 +614,7 @@ public class ApplicationMode {
return gson.toJson(toModeBean());
}
public ApplicationModeBean toModeBean(){
public ApplicationModeBean toModeBean() {
ApplicationModeBean mb = new ApplicationModeBean();
mb.stringKey = stringKey;
mb.userProfileName = getUserProfileName();

View file

@ -12,6 +12,7 @@ import java.util.StringTokenizer;
class ImpassableRoadsStorage extends SettingsMapPointsStorage {
protected String roadsIdsKey;
protected String directionsKey;
protected String appModeKey;
public ImpassableRoadsStorage(OsmandSettings osmandSettings) {
@ -19,6 +20,7 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
pointsKey = OsmandSettings.IMPASSABLE_ROAD_POINTS;
descriptionsKey = OsmandSettings.IMPASSABLE_ROADS_DESCRIPTIONS;
roadsIdsKey = OsmandSettings.IMPASSABLE_ROADS_IDS;
directionsKey = OsmandSettings.IMPASSABLE_ROADS_DIRECTIONS;
appModeKey = OsmandSettings.IMPASSABLE_ROADS_APP_MODE_KEYS;
}
@ -37,6 +39,21 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
return list;
}
public List<Double> getDirections(int size) {
List<Double> list = new ArrayList<>();
String directions = getSettingsAPI().getString(getOsmandSettings().getGlobalPreferences(), directionsKey, "");
if (directions.trim().length() > 0) {
StringTokenizer tok = new StringTokenizer(directions, ",");
while (tok.hasMoreTokens() && list.size() <= size) {
list.add(Double.parseDouble(tok.nextToken()));
}
}
while (list.size() < size) {
list.add(0.0);
}
return list;
}
public List<String> getAppModeKeys(int size) {
List<String> list = new ArrayList<>();
String roadIds = getSettingsAPI().getString(getOsmandSettings().getGlobalPreferences(), appModeKey, "");
@ -55,6 +72,7 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
public List<AvoidRoadInfo> getImpassableRoadsInfo() {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<Double> directions = getDirections(points.size());
List<String> appModeKeys = getAppModeKeys(points.size());
List<String> descriptions = getPointDescriptions(points.size());
@ -68,6 +86,7 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
avoidRoadInfo.id = roadIds.get(i);
avoidRoadInfo.latitude = latLon.getLatitude();
avoidRoadInfo.longitude = latLon.getLongitude();
avoidRoadInfo.direction = directions.get(i);
avoidRoadInfo.name = description.getName();
avoidRoadInfo.appModeKey = appModeKeys.get(i);
avoidRoadsInfo.add(avoidRoadInfo);
@ -79,15 +98,17 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
public boolean addImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<Double> directions = getDirections(points.size());
List<String> appModeKeys = getAppModeKeys(points.size());
List<String> descriptions = getPointDescriptions(points.size());
roadIds.add(0, avoidRoadInfo.id);
directions.add(0, avoidRoadInfo.direction);
points.add(0, new LatLon(avoidRoadInfo.latitude, avoidRoadInfo.longitude));
appModeKeys.add(0, avoidRoadInfo.appModeKey);
descriptions.add(0, PointDescription.serializeToString(new PointDescription("", avoidRoadInfo.name)));
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys, directions);
}
public boolean updateImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) {
@ -96,13 +117,15 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
int index = points.indexOf(new LatLon(avoidRoadInfo.latitude, avoidRoadInfo.longitude));
if (index != -1) {
List<Long> roadIds = getRoadIds(points.size());
List<Double> directions = getDirections(points.size());
List<String> appModeKeys = getAppModeKeys(points.size());
List<String> descriptions = getPointDescriptions(points.size());
roadIds.set(index, avoidRoadInfo.id);
directions.set(index, avoidRoadInfo.direction);
appModeKeys.set(index, avoidRoadInfo.appModeKey);
descriptions.set(index, PointDescription.serializeToString(new PointDescription("", avoidRoadInfo.name)));
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys, directions);
}
return false;
}
@ -111,15 +134,17 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
public boolean deletePoint(int index) {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<Double> directions = getDirections(points.size());
List<String> appModeKeys = getAppModeKeys(points.size());
List<String> descriptions = getPointDescriptions(points.size());
if (index < points.size()) {
points.remove(index);
roadIds.remove(index);
directions.remove(index);
appModeKeys.remove(index);
descriptions.remove(index);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys, directions);
}
return false;
}
@ -128,6 +153,7 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
public boolean deletePoint(LatLon latLon) {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<Double> directions = getDirections(points.size());
List<String> appModeKeys = getAppModeKeys(points.size());
List<String> descriptions = getPointDescriptions(points.size());
@ -135,9 +161,10 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
if (index != -1) {
points.remove(index);
roadIds.remove(index);
directions.remove(index);
appModeKeys.remove(index);
descriptions.remove(index);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys, directions);
}
return false;
}
@ -146,21 +173,23 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
public boolean movePoint(LatLon latLonEx, LatLon latLonNew) {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<Double> directions = getDirections(points.size());
List<String> appModeKeys = getAppModeKeys(points.size());
List<String> descriptions = getPointDescriptions(points.size());
int i = points.indexOf(latLonEx);
if (i != -1) {
points.set(i, latLonNew);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys);
return saveAvoidRoadData(points, descriptions, roadIds, appModeKeys, directions);
} else {
return false;
}
}
public boolean saveAvoidRoadData(List<LatLon> points, List<String> descriptions,
List<Long> roadIds, List<String> appModeKeys) {
return savePoints(points, descriptions) && saveRoadIds(roadIds) && saveAppModeKeys(appModeKeys);
public boolean saveAvoidRoadData(List<LatLon> points, List<String> descriptions, List<Long> roadIds,
List<String> appModeKeys, List<Double> directions) {
return savePoints(points, descriptions) && saveRoadIds(roadIds)
&& saveAppModeKeys(appModeKeys) && saveDirections(directions);
}
public boolean saveRoadIds(List<Long> roadIds) {
@ -177,6 +206,20 @@ class ImpassableRoadsStorage extends SettingsMapPointsStorage {
.commit();
}
public boolean saveDirections(List<Double> directions) {
StringBuilder stringBuilder = new StringBuilder();
Iterator<Double> iterator = directions.iterator();
while (iterator.hasNext()) {
stringBuilder.append(iterator.next());
if (iterator.hasNext()) {
stringBuilder.append(",");
}
}
return getSettingsAPI().edit(getOsmandSettings().getGlobalPreferences())
.putString(directionsKey, stringBuilder.toString())
.commit();
}
public boolean saveAppModeKeys(List<String> appModeKeys) {
StringBuilder stringBuilder = new StringBuilder();
Iterator<String> iterator = appModeKeys.iterator();

View file

@ -978,7 +978,16 @@ public class OsmandSettings {
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.SKI, "ski");
}
public final CommonPreference<RouteService> ROUTE_SERVICE = new EnumStringPreference<>(this, "route_service", RouteService.OSMAND, RouteService.values()).makeProfile().cache();
public final CommonPreference<RouteService> ROUTE_SERVICE = new EnumStringPreference<RouteService>(this, "route_service", RouteService.OSMAND, RouteService.values()) {
@Override
public RouteService getModeValue(ApplicationMode mode) {
if (mode == ApplicationMode.DEFAULT) {
return RouteService.STRAIGHT;
} else {
return super.getModeValue(mode);
}
}
}.makeProfile().cache();
{
ROUTE_SERVICE.setModeDefaultValue(ApplicationMode.DEFAULT, RouteService.STRAIGHT);
@ -2097,6 +2106,7 @@ public class OsmandSettings {
public static final String IMPASSABLE_ROAD_POINTS = "impassable_road_points";
public static final String IMPASSABLE_ROADS_DESCRIPTIONS = "impassable_roads_descriptions";
public static final String IMPASSABLE_ROADS_IDS = "impassable_roads_ids";
public static final String IMPASSABLE_ROADS_DIRECTIONS = "impassable_roads_directions";
public static final String IMPASSABLE_ROADS_APP_MODE_KEYS = "impassable_roads_app_mode_keys";
public void backupPointToStart() {

View file

@ -9,6 +9,7 @@ import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
@ -19,16 +20,16 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecificRoads.AvoidRoadInfo> {
public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidRoadInfo> {
private OsmandSettings settings;
private AvoidSpecificRoads specificRoads;
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull List<AvoidSpecificRoads.AvoidRoadInfo> items) {
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull List<AvoidRoadInfo> items) {
super(app, null, items);
}
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @Nullable AvoidRoadsSettingsItem baseItem, @NonNull List<AvoidSpecificRoads.AvoidRoadInfo> items) {
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @Nullable AvoidRoadsSettingsItem baseItem, @NonNull List<AvoidRoadInfo> items) {
super(app, baseItem, items);
}
@ -64,16 +65,16 @@ public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecific
@Override
public void apply() {
List<AvoidSpecificRoads.AvoidRoadInfo> newItems = getNewItems();
List<AvoidRoadInfo> newItems = getNewItems();
if (!newItems.isEmpty() || !duplicateItems.isEmpty()) {
appliedItems = new ArrayList<>(newItems);
for (AvoidSpecificRoads.AvoidRoadInfo duplicate : duplicateItems) {
for (AvoidRoadInfo duplicate : duplicateItems) {
LatLon latLon = new LatLon(duplicate.latitude, duplicate.longitude);
if (settings.removeImpassableRoad(latLon)) {
settings.addImpassableRoad(duplicate);
}
}
for (AvoidSpecificRoads.AvoidRoadInfo avoidRoad : appliedItems) {
for (AvoidRoadInfo avoidRoad : appliedItems) {
settings.addImpassableRoad(avoidRoad);
}
specificRoads.loadImpassableRoads();
@ -82,8 +83,8 @@ public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecific
}
@Override
public boolean isDuplicate(@NonNull AvoidSpecificRoads.AvoidRoadInfo item) {
for (AvoidSpecificRoads.AvoidRoadInfo roadInfo : existingItems) {
public boolean isDuplicate(@NonNull AvoidRoadInfo item) {
for (AvoidRoadInfo roadInfo : existingItems) {
if (roadInfo.id == item.id) {
return true;
}
@ -103,7 +104,7 @@ public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecific
@NonNull
@Override
public AvoidSpecificRoads.AvoidRoadInfo renameItem(@NonNull AvoidSpecificRoads.AvoidRoadInfo item) {
public AvoidRoadInfo renameItem(@NonNull AvoidRoadInfo item) {
return item;
}
@ -118,13 +119,15 @@ public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecific
JSONObject object = jsonArray.getJSONObject(i);
double latitude = object.optDouble("latitude");
double longitude = object.optDouble("longitude");
double direction = object.optDouble("direction");
String name = object.optString("name");
String appModeKey = object.optString("appModeKey");
long id = object.optLong("roadId");
AvoidSpecificRoads.AvoidRoadInfo roadInfo = new AvoidSpecificRoads.AvoidRoadInfo();
AvoidRoadInfo roadInfo = new AvoidRoadInfo();
roadInfo.id = id;
roadInfo.latitude = latitude;
roadInfo.longitude = longitude;
roadInfo.direction = direction;
roadInfo.name = name;
if (ApplicationMode.valueOfStringKey(appModeKey, null) != null) {
roadInfo.appModeKey = appModeKey;
@ -144,13 +147,16 @@ public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecific
JSONArray jsonArray = new JSONArray();
if (!items.isEmpty()) {
try {
for (AvoidSpecificRoads.AvoidRoadInfo avoidRoad : items) {
for (AvoidRoadInfo avoidRoad : items) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("latitude", avoidRoad.latitude);
jsonObject.put("longitude", avoidRoad.longitude);
jsonObject.put("name", avoidRoad.name);
jsonObject.put("appModeKey", avoidRoad.appModeKey);
jsonObject.put("roadId", avoidRoad.id);
if (!Double.isNaN(avoidRoad.direction)) {
jsonObject.put("direction", avoidRoad.direction);
}
jsonArray.put(jsonObject);
}
json.put("items", jsonArray);

View file

@ -21,7 +21,7 @@ public class SkiMapsPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(net.osmand.plus.R.string.plugin_ski_descr);
}

View file

@ -119,7 +119,7 @@ public class SRTMPlugin extends OsmandPlugin {
}
@Override
public String getDescription() {
public CharSequence getDescription() {
return app.getString(R.string.srtm_plugin_description);
}

View file

@ -99,13 +99,13 @@ public class TravelDbHelper implements TravelHelper {
private final OsmandApplication application;
private TravelLocalDataHelper localDataHelper;
private Collator collator;
private final Collator collator;
private SQLiteConnection connection = null;
private File selectedTravelBook = null;
private List<File> existingTravelBooks = new ArrayList<>();
private List<TravelArticle> popularArticles = new ArrayList<TravelArticle>();
private List<TravelArticle> popularArticles = new ArrayList<>();
public TravelDbHelper(OsmandApplication application) {
@ -126,6 +126,7 @@ public class TravelDbHelper implements TravelHelper {
return false;
}
@Override
public TravelLocalDataHelper getBookmarksHelper() {
return localDataHelper;
}
@ -135,6 +136,7 @@ public class TravelDbHelper implements TravelHelper {
return selectedTravelBook != null;
}
@Override
public void initializeDataOnAppStartup() {
List<File> files = getPossibleFiles();
String travelBook = application.getSettings().SELECTED_TRAVEL_BOOK.get();
@ -168,12 +170,14 @@ public class TravelDbHelper implements TravelHelper {
return null;
}
@Override
public void initializeDataToDisplay() {
localDataHelper.refreshCachedData();
loadPopularArticles();
}
@Override
public String getSelectedTravelBookName() {
if (selectedTravelBook != null) {
return selectedTravelBook.getName();
@ -210,8 +214,9 @@ public class TravelDbHelper implements TravelHelper {
}
}
@Override
@NonNull
public List<WikivoyageSearchResult> search(final String searchQuery) {
public List<WikivoyageSearchResult> search(@NonNull String searchQuery) {
List<WikivoyageSearchResult> res = new ArrayList<>();
SQLiteConnection conn = openConnection();
String[] queries = searchQuery.replace('_', ' ').replace('/', ' ').split(" ");
@ -260,6 +265,7 @@ public class TravelDbHelper implements TravelHelper {
return list;
}
@Override
@NonNull
public List<TravelArticle> getPopularArticles() {
return popularArticles;
@ -270,7 +276,7 @@ public class TravelDbHelper implements TravelHelper {
String language = application.getLanguage();
SQLiteConnection conn = openConnection();
if (conn == null) {
popularArticles = new ArrayList<TravelArticle>();
popularArticles = new ArrayList<>();
return popularArticles;
}
String LANG_WHERE = " WHERE " + ARTICLES_COL_LANG + " = '" + language + "'";
@ -376,7 +382,7 @@ public class TravelDbHelper implements TravelHelper {
return res;
}
private void sortSearchResults(final String searchQuery, List<WikivoyageSearchResult> list) {
private void sortSearchResults(@NonNull final String searchQuery, @NonNull List<WikivoyageSearchResult> list) {
Collections.sort(list, new Comparator<WikivoyageSearchResult>() {
@Override
public int compare(WikivoyageSearchResult o1, WikivoyageSearchResult o2) {
@ -444,8 +450,9 @@ public class TravelDbHelper implements TravelHelper {
}
@NonNull
@Override
public LinkedHashMap<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(
final TravelArticle article) {
@NonNull final TravelArticle article) {
String lang = article.getLang();
String title = article.getTitle();
if (TextUtils.isEmpty(lang) || TextUtils.isEmpty(title)) {
@ -533,8 +540,9 @@ public class TravelDbHelper implements TravelHelper {
return res;
}
@Override
@Nullable
public TravelArticle getArticleById(String routeId, String lang) {
public TravelArticle getArticleById(@NonNull String routeId, @NonNull String lang) {
TravelArticle res = null;
SQLiteConnection conn = openConnection();
if (conn != null && !Algorithms.isEmpty(routeId)) {
@ -550,8 +558,9 @@ public class TravelDbHelper implements TravelHelper {
return res;
}
@Override
@Nullable
public TravelArticle getArticleByTitle(String title, String lang) {
public TravelArticle getArticleByTitle(@NonNull String title, @NonNull String lang) {
TravelArticle res = null;
SQLiteConnection conn = openConnection();
if (conn != null) {
@ -567,7 +576,9 @@ public class TravelDbHelper implements TravelHelper {
return res;
}
public String getArticleId(String title, String lang) {
@NonNull
@Override
public String getArticleId(@NonNull String title, @NonNull String lang) {
String res = "";
SQLiteConnection conn = openConnection();
if (conn != null) {
@ -585,7 +596,8 @@ public class TravelDbHelper implements TravelHelper {
}
@NonNull
public ArrayList<String> getArticleLangs(String routeId) {
@Override
public ArrayList<String> getArticleLangs(@NonNull String routeId) {
ArrayList<String> res = new ArrayList<>();
SQLiteConnection conn = openConnection();
if (conn != null) {
@ -652,12 +664,16 @@ public class TravelDbHelper implements TravelHelper {
return nm.substring(0, nm.indexOf('.')).replace('_', ' ');
}
public String getGPXName(TravelArticle article) {
@NonNull
@Override
public String getGPXName(@NonNull final TravelArticle article) {
return article.getTitle().replace('/', '_').replace('\'', '_')
.replace('\"', '_') + IndexConstants.GPX_FILE_EXT;
}
public File createGpxFile(TravelArticle article) {
@NonNull
@Override
public File createGpxFile(@NonNull final TravelArticle article) {
final GPXFile gpx = article.getGpxFile();
File file = application.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
if (!file.exists()) {

View file

@ -3,11 +3,8 @@ package net.osmand.plus.wikivoyage.data;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.OsmandApplication;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -22,25 +19,31 @@ public interface TravelHelper {
boolean isAnyTravelBookPresent();
@NonNull
List<WikivoyageSearchResult> search(final String searchQuery);
List<WikivoyageSearchResult> search(@NonNull String searchQuery);
@NonNull
List<TravelArticle> getPopularArticles();
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(
final TravelArticle article);
@NonNull
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull final TravelArticle article);
TravelArticle getArticleById(String routeId, String lang);
@Nullable
TravelArticle getArticleById(@NonNull String routeId, @NonNull String lang);
TravelArticle getArticleByTitle(String title, String lang);
@Nullable
TravelArticle getArticleByTitle(@NonNull String title, @NonNull String lang);
String getArticleId(String title, String lang);
@NonNull
String getArticleId(@NonNull String title, @NonNull String lang);
ArrayList<String> getArticleLangs(String articleId);
@NonNull
ArrayList<String> getArticleLangs(@NonNull String routeId);
String getGPXName(TravelArticle article);
@NonNull
String getGPXName(@NonNull final TravelArticle article);
File createGpxFile(TravelArticle article);
@NonNull
File createGpxFile(@NonNull final TravelArticle article);
// TODO: this method should be deleted once TravelDBHelper is deleted
// For TravelOBFHelper it could always return "" and should be no problem

View file

@ -118,6 +118,7 @@ public class TravelLocalDataHelper {
saved.content = WikiArticleHelper.getPartialContent(article.getContent());
saved.lat = article.lat;
saved.lon = article.lon;
saved.routeId = article.routeId;
savedArticles.add(saved);
dbHelper.addSavedArticle(saved);
notifySavedUpdated();
@ -168,7 +169,7 @@ public class TravelLocalDataHelper {
private static class WikivoyageLocalDataDbHelper {
private static final int DB_VERSION = 4;
private static final int DB_VERSION = 5;
private static final String DB_NAME = "wikivoyage_local_data";
private static final String HISTORY_TABLE_NAME = "wikivoyage_search_history";
@ -202,6 +203,7 @@ public class TravelLocalDataHelper {
private static final String BOOKMARKS_COL_TRAVEL_BOOK = "travel_book";
private static final String BOOKMARKS_COL_LAT = "lat";
private static final String BOOKMARKS_COL_LON = "lon";
private static final String BOOKMARKS_COL_ROUTE_ID = "route_id";
private static final String BOOKMARKS_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS " +
BOOKMARKS_TABLE_NAME + " (" +
@ -212,7 +214,8 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_PARTIAL_CONTENT + " TEXT, " +
BOOKMARKS_COL_TRAVEL_BOOK + " TEXT, " +
BOOKMARKS_COL_LAT + " double, " +
BOOKMARKS_COL_LON + " double);";
BOOKMARKS_COL_LON + " double, " +
BOOKMARKS_COL_ROUTE_ID + " TEXT" + ");";
private static final String BOOKMARKS_TABLE_SELECT = "SELECT " +
BOOKMARKS_COL_ARTICLE_TITLE + ", " +
@ -221,7 +224,8 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_IMAGE_TITLE + ", " +
BOOKMARKS_COL_PARTIAL_CONTENT + ", " +
BOOKMARKS_COL_LAT + ", " +
BOOKMARKS_COL_LON +
BOOKMARKS_COL_LON + ", " +
BOOKMARKS_COL_ROUTE_ID +
" FROM " + BOOKMARKS_TABLE_NAME;
private final OsmandApplication context;
@ -271,6 +275,9 @@ public class TravelLocalDataHelper {
conn.execSQL("ALTER TABLE " + BOOKMARKS_TABLE_NAME + " ADD " + BOOKMARKS_COL_LAT + " double");
conn.execSQL("ALTER TABLE " + BOOKMARKS_TABLE_NAME + " ADD " + BOOKMARKS_COL_LON + " double");
}
if (oldVersion < 5) {
conn.execSQL("ALTER TABLE " + BOOKMARKS_TABLE_NAME + " ADD " + BOOKMARKS_COL_ROUTE_ID + " TEXT");
}
}
@NonNull
@ -420,11 +427,12 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_PARTIAL_CONTENT + ", " +
BOOKMARKS_COL_TRAVEL_BOOK + ", " +
BOOKMARKS_COL_LAT + ", " +
BOOKMARKS_COL_LON +
") VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
BOOKMARKS_COL_LON + ", " +
BOOKMARKS_COL_ROUTE_ID +
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
conn.execSQL(query, new Object[]{article.title, article.lang,
article.aggregatedPartOf, article.imageTitle, article.content,
travelBook, article.lat, article.lon});
travelBook, article.lat, article.lon, article.routeId});
} finally {
conn.close();
}
@ -475,6 +483,7 @@ public class TravelLocalDataHelper {
res.content = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_PARTIAL_CONTENT));
res.lat = cursor.getDouble(cursor.getColumnIndex(BOOKMARKS_COL_LAT));
res.lon = cursor.getDouble(cursor.getColumnIndex(BOOKMARKS_COL_LON));
res.routeId = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_ROUTE_ID));
return res;
}

View file

@ -3,116 +3,385 @@ package net.osmand.plus.wikivoyage.data;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.Collator;
import net.osmand.CollatorStringMatcher;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.IndexConstants;
import net.osmand.OsmAndCollator;
import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter;
import net.osmand.data.Amenity;
import net.osmand.data.MapObject;
import net.osmand.data.LatLon;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.api.SQLiteAPI;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static net.osmand.CollatorStringMatcher.StringMatcherMode.CHECK_EQUALS_FROM_SPACE;
public class TravelObfHelper implements TravelHelper {
private static final Log LOG = PlatformUtil.getLog(TravelObfHelper.class);
public static final String ROUTE_ARTICLE = "route_article";
public static final int SEARCH_RADIUS = 100000;
private final OsmandApplication app;
private final Collator collator;
private final OsmandApplication application;
private List<TravelArticle> popularArticles = new ArrayList<>();
private final Map<String, TravelArticle> cachedArticles;
private final TravelLocalDataHelper localDataHelper;
private TravelLocalDataHelper localDataHelper;
private List<TravelArticle> popularArticles = new ArrayList<TravelArticle>();
public TravelObfHelper(OsmandApplication application) {
this.application = application;
localDataHelper = new TravelLocalDataHelper(application);
public TravelObfHelper(OsmandApplication app) {
this.app = app;
collator = OsmAndCollator.primaryCollator();
localDataHelper = new TravelLocalDataHelper(app);
cachedArticles = new HashMap<>();
}
@Override
public TravelLocalDataHelper getBookmarksHelper() {
return localDataHelper;
}
@Override
public void initializeDataOnAppStartup() {
}
@Override
public boolean isAnyTravelBookPresent() {
return checkIfObfFileExists(application);
}
public void initializeDataToDisplay() {
localDataHelper.refreshCachedData();
loadPopularArticles();
}
@NonNull
public List<WikivoyageSearchResult> search(final String searchQuery) {
List<WikivoyageSearchResult> res = new ArrayList<>();
public List<TravelArticle> loadPopularArticles() {
String language = app.getLanguage();
List<TravelArticle> popularArticles = new ArrayList<>();
for (BinaryMapIndexReader travelBookReader : getTravelBookReaders()) {
try {
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
BinaryMapIndexReader.SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
location, SEARCH_RADIUS, -1, getSearchRouteArticleFilter(), null);
List<Amenity> amenities = travelBookReader.searchPoi(req);
if (amenities.size() > 0) {
for (Amenity a : amenities) {
if (!Algorithms.isEmpty(a.getName(language))) {
TravelArticle article = readArticle(a, language);
popularArticles.add(article);
cachedArticles.put(article.routeId, article);
if (popularArticles.size() >= 100) {
break;
}
}
}
Collections.sort(popularArticles, new Comparator<TravelArticle>() {
@Override
public int compare(TravelArticle article1, TravelArticle article2) {
int d1 = (int) (MapUtils.getDistance(article1.getLat(), article1.getLon(),
location.getLatitude(), location.getLongitude()));
int d2 = (int) (MapUtils.getDistance(article2.getLat(), article2.getLon(),
location.getLatitude(), location.getLongitude()));
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
}
});
}
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
this.popularArticles = popularArticles;
return popularArticles;
}
SearchPoiTypeFilter getSearchRouteArticleFilter() {
return new SearchPoiTypeFilter() {
@Override
public boolean accept(PoiCategory type, String subcategory) {
return subcategory.equals(ROUTE_ARTICLE);
}
@Override
public boolean isEmpty() {
return false;
}
};
}
private TravelArticle readArticle(@NonNull Amenity amenity, @Nullable String lang) {
TravelArticle res = new TravelArticle();
String title = Algorithms.isEmpty(amenity.getName(lang)) ? amenity.getName() : amenity.getName(lang);
if (Algorithms.isEmpty(title)) {
Map<String, String> namesMap = amenity.getNamesMap(true);
if (!namesMap.isEmpty()) {
lang = namesMap.keySet().iterator().next();
title = amenity.getName(lang);
}
}
res.title = title;
res.content = amenity.getDescription(lang);
res.isPartOf = emptyIfNull(amenity.getTagContent(Amenity.IS_PART, lang));
res.lat = amenity.getLocation().getLatitude();
res.lon = amenity.getLocation().getLongitude();
res.imageTitle = emptyIfNull(amenity.getTagContent(Amenity.IMAGE_TITLE, lang));
res.routeId = getRouteId(amenity);
res.originalId = 0;
res.lang = lang;
res.contentsJson = emptyIfNull(amenity.getTagContent(Amenity.CONTENT_JSON, lang));
res.aggregatedPartOf = emptyIfNull(amenity.getTagContent(Amenity.IS_AGGR_PART, lang));
return res;
}
private String emptyIfNull(String text) {
return text == null ? "" : text;
}
private String getRouteId(Amenity amenity) {
return amenity.getTagContent(Amenity.ROUTE_ID, null);
}
@Override
public boolean isAnyTravelBookPresent() {
return !Algorithms.isEmpty(getTravelBookReaders());
}
@NonNull
@Override
public List<WikivoyageSearchResult> search(@NonNull String searchQuery) {
List<WikivoyageSearchResult> res = new ArrayList<>();
List<Amenity> searchObjects = null;
for (BinaryMapIndexReader reader : app.getResourceManager().getTravelRepositories()) {
try {
BinaryMapIndexReader.SearchRequest<Amenity> searchRequest = BinaryMapIndexReader.
buildSearchPoiRequest(0, 0, searchQuery,
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchRouteArticleFilter(), null, null);
searchObjects = reader.searchPoiByName(searchRequest);
} catch (IOException e) {
LOG.error(e);
}
}
if (!Algorithms.isEmpty(searchObjects)) {
String baseLng = app.getLanguage();
for (Amenity obj : searchObjects) {
WikivoyageSearchResult r = new WikivoyageSearchResult();
TravelArticle article = readArticle(obj, baseLng);
r.articleTitles = new ArrayList<>(Collections.singletonList(article.title));
r.imageTitle = article.imageTitle;
r.routeId = article.routeId;
r.isPartOf = new ArrayList<>(Collections.singletonList(article.isPartOf));
r.langs = new ArrayList<>(Collections.singletonList(baseLng));
res.add(r);
cachedArticles.put(article.routeId, article);
}
res = new ArrayList<>(groupSearchResultsByRouteId(res));
sortSearchResults(res);
}
return res;
}
private void sortSearchResults(@NonNull List<WikivoyageSearchResult> list) {
Collections.sort(list, new Comparator<WikivoyageSearchResult>() {
@Override
public int compare(WikivoyageSearchResult res1, WikivoyageSearchResult res2) {
return collator.compare(res1.articleTitles.get(0), res2.articleTitles.get(0));
}
});
}
@NonNull
private Collection<WikivoyageSearchResult> groupSearchResultsByRouteId(@NonNull List<WikivoyageSearchResult> res) {
String baseLng = app.getLanguage();
Map<String, WikivoyageSearchResult> wikivoyage = new HashMap<>();
for (WikivoyageSearchResult rs : res) {
WikivoyageSearchResult prev = wikivoyage.get(rs.routeId);
if (prev != null) {
int insInd = prev.langs.size();
if (rs.langs.get(0).equals(baseLng)) {
insInd = 0;
} else if (rs.langs.get(0).equals("en")) {
if (!prev.langs.get(0).equals(baseLng)) {
insInd = 0;
} else {
insInd = 1;
}
}
prev.articleTitles.add(insInd, rs.articleTitles.get(0));
prev.langs.add(insInd, rs.langs.get(0));
prev.isPartOf.add(insInd, rs.isPartOf.get(0));
} else {
wikivoyage.put(rs.routeId, rs);
}
}
return wikivoyage.values();
}
@NonNull
@Override
public List<TravelArticle> getPopularArticles() {
return popularArticles;
}
@NonNull
@Override
public Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(TravelArticle article) {
return null;
public Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull final TravelArticle article) {
return Collections.emptyMap();
}
@Override
public TravelArticle getArticleById(String routeId, String lang) {
return null;
public TravelArticle getArticleById(@NonNull String routeId, @NonNull String lang) {
TravelArticle article = cachedArticles.get(routeId);
if (article != null) {
return article;
} else {
return getArticleByIdFromTravelBooks(routeId, lang);
}
}
@Override
public TravelArticle getArticleByTitle(String title, String lang) {
return null;
private TravelArticle getArticleByIdFromTravelBooks(final String routeId, final String lang) {
TravelArticle article = null;
final List<Amenity> amenities = new ArrayList<>();
for (BinaryMapIndexReader travelBookReader : getTravelBookReaders()) {
try {
BinaryMapIndexReader.SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, -1, getSearchRouteArticleFilter(),
new ResultMatcher<Amenity>() {
boolean done = false;
@Override
public boolean publish(Amenity amenity) {
if (getRouteId(amenity).equals(routeId)) {
amenities.add(amenity);
done = true;
}
return false;
}
@Override
public boolean isCancelled() {
return done;
}
});
travelBookReader.searchPoi(req);
} catch (IOException e) {
LOG.error(e.getMessage());
}
if (!amenities.isEmpty()) {
article = readArticle(amenities.get(0), lang);
cachedArticles.put(article.routeId, article);
}
}
return article;
}
@Nullable
@Override
public String getArticleId(String title, String lang) {
return null;
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang) {
TravelArticle article = null;
final List<Amenity> amenities = new ArrayList<>();
for (BinaryMapIndexReader travelBookReader : getTravelBookReaders()) {
try {
BinaryMapIndexReader.SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
0, 0, title, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchRouteArticleFilter(),
new ResultMatcher<Amenity>() {
boolean done = false;
@Override
public boolean publish(Amenity amenity) {
if (CollatorStringMatcher.cmatches(collator, title, amenity.getName(lang), CHECK_EQUALS_FROM_SPACE)) {
amenities.add(amenity);
done = true;
}
return false;
}
@Override
public boolean isCancelled() {
return done;
}
}, null);
travelBookReader.searchPoiByName(req);
} catch (IOException e) {
LOG.error(e.getMessage());
}
if (!amenities.isEmpty()) {
article = readArticle(amenities.get(0), lang);
cachedArticles.put(article.routeId, article);
}
}
return article;
}
@Override
public ArrayList<String> getArticleLangs(String articleId) {
return null;
private List<BinaryMapIndexReader> getTravelBookReaders() {
if (!app.isApplicationInitializing()) {
return app.getResourceManager().getTravelRepositories();
} else {
return new ArrayList<>();
}
}
@NonNull
public List<TravelArticle> loadPopularArticles() {
popularArticles = new ArrayList<>();
return popularArticles;
@Override
public String getArticleId(@NonNull String title, @NonNull String lang) {
TravelArticle a = null;
for (TravelArticle article : cachedArticles.values()) {
if (article.getTitle().equals(title)) {
a = article;
break;
}
}
if (a == null) {
TravelArticle article = getArticleByTitle(title, lang);
if (article != null) {
a = article;
}
}
return a != null && a.getRouteId() != null ? a.getRouteId() : "";
}
public String getGPXName(TravelArticle article) {
@NonNull
@Override
public ArrayList<String> getArticleLangs(@NonNull String routeId) {
ArrayList<String> res = new ArrayList<>();
res.add("en");
for (TravelArticle article : popularArticles) {
if (article.getRouteId().equals(routeId)) {
res.add(article.getLang());
}
}
return res;
}
@NonNull
@Override
public String getGPXName(@NonNull final TravelArticle article) {
return article.getTitle().replace('/', '_').replace('\'', '_')
.replace('\"', '_') + IndexConstants.GPX_FILE_EXT;
}
public File createGpxFile(TravelArticle article) {
final GPXUtilities.GPXFile gpx = article.getGpxFile();
File file = application.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
@NonNull
@Override
public File createGpxFile(@NonNull final TravelArticle article) {
final GPXFile gpx = article.getGpxFile();
File file = app.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
if (!file.exists()) {
GPXUtilities.writeGpxFile(file, gpx);
}
@ -121,18 +390,6 @@ public class TravelObfHelper implements TravelHelper {
@Override
public String getSelectedTravelBookName() {
return null;
}
public static boolean checkIfObfFileExists(OsmandApplication app) {
File[] files = app.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR).listFiles();
if (files != null) {
for (File f : files) {
if (f.getName().contains(IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT)) {
return true;
}
}
}
return false;
return "";
}
}

View file

@ -38,6 +38,7 @@ import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
import net.osmand.plus.wikivoyage.data.TravelArticle;
import net.osmand.plus.wikivoyage.data.TravelHelper;
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
import net.osmand.plus.wikivoyage.search.WikivoyageSearchDialogFragment;
import net.osmand.util.Algorithms;
@ -45,7 +46,8 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class WikivoyageExploreActivity extends TabActivity implements DownloadEvents, OnDialogFragmentResultListener {
public class WikivoyageExploreActivity extends TabActivity implements DownloadEvents, OnDialogFragmentResultListener,
TravelLocalDataHelper.Listener {
private static final String TAB_SELECTED = "tab_selected";
private static final String ROUTE_ID_KEY = "route_id_key";
@ -59,7 +61,6 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
protected List<WeakReference<Fragment>> fragments = new ArrayList<>();
private LockableViewPager viewPager;
private boolean updateNeeded;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -190,6 +191,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
setIntent(null);
}
getMyApplication().getDownloadThread().setUiActivity(this);
app.getTravelHelper().getBookmarksHelper().addListener(this);
}
protected void parseLaunchIntentLink(Uri data) {
@ -211,6 +213,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
protected void onPause() {
super.onPause();
getMyApplication().getDownloadThread().resetUiActivity(this);
app.getTravelHelper().getBookmarksHelper().removeListener(this);
}
@Nullable
@ -225,7 +228,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
}
@Nullable
private SavedArticlesTabFragment getSavedArticlesTabFragment() {
public SavedArticlesTabFragment getSavedArticlesTabFragment() {
for (WeakReference<Fragment> ref : fragments) {
Fragment f = ref.get();
if (f instanceof SavedArticlesTabFragment) {
@ -319,16 +322,13 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
updateFragments();
}
private void updateFragments() {
public void updateFragments() {
ExploreTabFragment exploreTabFragment = getExploreTabFragment();
SavedArticlesTabFragment savedArticlesTabFragment = getSavedArticlesTabFragment();
if (exploreTabFragment != null && savedArticlesTabFragment != null
&& exploreTabFragment.isAdded() && savedArticlesTabFragment.isAdded()) {
exploreTabFragment.populateData();
savedArticlesTabFragment.savedArticlesUpdated();
updateNeeded = false;
} else {
updateNeeded = true;
}
}
@ -353,9 +353,12 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
}
public void onTabFragmentResume(Fragment fragment) {
if (updateNeeded) {
updateFragments();
}
updateFragments();
}
@Override
public void savedArticlesUpdated() {
updateFragments();
}
private static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {