Merge branch 'master' into OnlineRoutingBackend

# Conflicts:
#	OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngine.java
#	OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingEngineFragment.java
#	OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java
This commit is contained in:
nazar-kutz 2021-01-11 00:15:55 +02:00
commit 259ab4d4f0
82 changed files with 1111 additions and 279 deletions

View file

@ -1790,6 +1790,7 @@ public class GPXUtilities {
serializer.attribute(null, "creator", file.author); //$NON-NLS-1$
}
serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$
serializer.attribute(null, "xmlns:osmand", "https://osmand.net");
serializer.attribute(null, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
serializer.attribute(null, "xsi:schemaLocation",
"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd");
@ -1938,7 +1939,7 @@ public class GPXUtilities {
serializer.startTag(null, "extensions");
if (!extensions.isEmpty()) {
for (Entry<String, String> s : extensions.entrySet()) {
writeNotNullText(serializer, s.getKey(), s.getValue());
writeNotNullText(serializer,"osmand:" + s.getKey(), s.getValue());
}
}
if (extensionsWriter != null) {

View file

@ -533,16 +533,19 @@ public class BinaryRoutePlanner {
long fid = to.getRoad().getId();
for (int i = 0; i < from.getRoad().getRestrictionLength(); i++) {
long id = from.getRoad().getRestrictionId(i);
int tp = from.getRoad().getRestrictionType(i);
if (fid == id) {
int tp = from.getRoad().getRestrictionType(i);
if (tp == MapRenderingTypes.RESTRICTION_NO_LEFT_TURN ||
tp == MapRenderingTypes.RESTRICTION_NO_RIGHT_TURN ||
tp == MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON ||
tp == MapRenderingTypes.RESTRICTION_NO_U_TURN) {
if (tp == MapRenderingTypes.RESTRICTION_NO_LEFT_TURN
|| tp == MapRenderingTypes.RESTRICTION_NO_RIGHT_TURN
|| tp == MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON
|| tp == MapRenderingTypes.RESTRICTION_NO_U_TURN) {
return false;
}
break;
}
if (tp == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) {
return false;
}
}
}
return true;
@ -647,24 +650,36 @@ public class BinaryRoutePlanner {
int type = -1;
if (!reverseWay) {
for (int i = 0; i < road.getRestrictionLength(); i++) {
int rt = road.getRestrictionType(i);
long rv = road.getRestrictionVia(i);
if (road.getRestrictionId(i) == next.road.id) {
if(!via || road.getRestrictionVia(i) == viaId) {
type = road.getRestrictionType(i);
if (!via || rv == viaId) {
type = rt;
break;
}
}
if (rv == viaId && rt == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) {
type = MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON;
break;
}
}
} else {
for (int i = 0; i < next.road.getRestrictionLength(); i++) {
int rt = next.road.getRestrictionType(i);
long rv = next.road.getRestrictionVia(i);
long restrictedTo = next.road.getRestrictionId(i);
if (restrictedTo == road.id) {
if(!via || next.road.getRestrictionVia(i) == viaId) {
if (!via || rv == viaId) {
type = rt;
break;
}
}
if (rv == viaId && rt == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) {
type = MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON;
break;
}
// Check if there is restriction only to the other than current road
if (rt == MapRenderingTypes.RESTRICTION_ONLY_RIGHT_TURN || rt == MapRenderingTypes.RESTRICTION_ONLY_LEFT_TURN
|| rt == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) {

View file

@ -553,11 +553,20 @@ public class GeoPointParserUtil {
}
if (searchRequest != null) {
String searchPattern = Pattern.compile("(?:\\.|,|\\s+|\\+|[+-]?\\d+(?:\\.\\d+)?)").pattern();
String[] search = searchRequest.split(searchPattern);
if (search.length > 0) {
return new GeoParsedPoint(searchRequest);
}
final Matcher positionInSearchRequestMatcher =
positionPattern.matcher(searchRequest);
if (lat == 0.0 && lon == 0.0 && positionInSearchRequestMatcher.find()) {
lat = Double.valueOf(positionInSearchRequestMatcher.group(1));
lon = Double.valueOf(positionInSearchRequestMatcher.group(2));
double tempLat = Double.valueOf(positionInSearchRequestMatcher.group(1));
double tempLon = Double.valueOf(positionInSearchRequestMatcher.group(2));
if (tempLat >= -90 && tempLat <= 90 && tempLon >= -180 && tempLon <= 180) {
lat = tempLat;
lon = tempLon;
}
}
}

View file

@ -15,13 +15,11 @@ import java.util.TreeSet;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.LatLon;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -76,41 +74,52 @@ public class RouteTestingTest {
} else {
binaryMapIndexReaders = new BinaryMapIndexReader[]{new BinaryMapIndexReader(raf, new File(fl))};
}
RoutingConfiguration config = builder.build(params.containsKey("vehicle") ? params.get("vehicle") : "car",
RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3, params);
RoutingContext ctx = fe.buildRoutingContext(config, null, binaryMapIndexReaders,
RoutePlannerFrontEnd.RouteCalculationMode.NORMAL);
ctx.leftSideNavigation = false;
List<RouteSegmentResult> routeSegments = fe.searchRoute(ctx, te.getStartPoint(), te.getEndPoint(), te.getTransitPoint());
Set<Long> reachedSegments = new TreeSet<Long>();
Assert.assertNotNull(routeSegments);
int prevSegment = -1;
for (int i = 0; i <= routeSegments.size(); i++) {
if (i == routeSegments.size() || routeSegments.get(i).getTurnType() != null) {
if (prevSegment >= 0) {
String name = routeSegments.get(prevSegment).getDescription();
long segmentId = routeSegments.get(prevSegment).getObject().getId() >> (RouteResultPreparation.SHIFT_ID);
System.out.println("segmentId: " + segmentId + " description: " + name);
for (int planRoadDirection = -1; planRoadDirection <= 1; planRoadDirection++) {
if (params.containsKey("wrongPlanRoadDirection")) {
if (params.get("wrongPlanRoadDirection").equals(planRoadDirection + "")) {
continue;
}
prevSegment = i;
}
if (i < routeSegments.size()) {
reachedSegments.add(routeSegments.get(i).getObject().getId() >> (RouteResultPreparation.SHIFT_ID));
}
}
Map<Long, String> expectedResults = te.getExpectedResults();
Iterator<Entry<Long, String>> it = expectedResults.entrySet().iterator();
while (it.hasNext()) {
Entry<Long, String> es = it.next();
if (es.getValue().equals("false")) {
Assert.assertTrue("Expected segment " + (es.getKey()) + " was wrongly reached in route segments "
+ reachedSegments.toString(), !reachedSegments.contains(es.getKey()));
} else {
Assert.assertTrue("Expected segment " + (es.getKey()) + " weren't reached in route segments "
+ reachedSegments.toString(), reachedSegments.contains(es.getKey()));
}
}
RoutingConfiguration config = builder.build(params.containsKey("vehicle") ? params.get("vehicle") : "car",
RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3, params);
config.planRoadDirection = planRoadDirection;
RoutingContext ctx = fe.buildRoutingContext(config, null, binaryMapIndexReaders,
RoutePlannerFrontEnd.RouteCalculationMode.NORMAL);
ctx.leftSideNavigation = false;
List<RouteSegmentResult> routeSegments = fe.searchRoute(ctx, te.getStartPoint(), te.getEndPoint(),
te.getTransitPoint());
Set<Long> reachedSegments = new TreeSet<Long>();
Assert.assertNotNull(routeSegments);
int prevSegment = -1;
for (int i = 0; i <= routeSegments.size(); i++) {
if (i == routeSegments.size() || routeSegments.get(i).getTurnType() != null) {
if (prevSegment >= 0) {
String name = routeSegments.get(prevSegment).getDescription();
long segmentId = routeSegments.get(prevSegment).getObject()
.getId() >> (RouteResultPreparation.SHIFT_ID);
System.out.println("segmentId: " + segmentId + " description: " + name);
}
prevSegment = i;
}
if (i < routeSegments.size()) {
reachedSegments.add(routeSegments.get(i).getObject().getId() >> (RouteResultPreparation.SHIFT_ID));
}
}
Map<Long, String> expectedResults = te.getExpectedResults();
Iterator<Entry<Long, String>> it = expectedResults.entrySet().iterator();
while (it.hasNext()) {
Entry<Long, String> es = it.next();
if (es.getValue().equals("false")) {
Assert.assertTrue("Expected segment " + (es.getKey()) + " was wrongly reached in route segments "
+ reachedSegments.toString(), !reachedSegments.contains(es.getKey()));
} else {
Assert.assertTrue("Expected segment " + (es.getKey()) + " weren't reached in route segments "
+ reachedSegments.toString(), reachedSegments.contains(es.getKey()));
}
}
}
}
}

View file

@ -267,4 +267,7 @@
<string name="privacy_policy_agree">\"Jarraitu\" sakatuz, Telegram eta OsmAnd pribatutasun-politiken baldintzak onartzen dituzu.</string>
<string name="privacy_policy_telegram_client">OsmAnd aztarnariak Telegram plataforma irekia erabiltzen duten bezeroetako bat da. Zure kontaktuek Telegram-eko beste edozein bezero erabil dezakete.</string>
<string name="last_update_from_telegram_date">Telegram-eko azken eguneratzea: %1$s</string>
<string name="shared_string_export">Esportatu</string>
<string name="logcat_buffer">Logcat bufferra</string>
<string name="send_report">Bidali txostena</string>
</resources>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="background_work_description">Endre batterioptimiseringsinnstillinger for mer stabil posisjonsdeling.</string>
<string name="background_work_description">Endre batterioptimaliseringsinnstillinger for mer stabil posisjonsdeling.</string>
<string name="background_work">Bakgrunnsarbeid</string>
<string name="battery_optimization_description">Skru av batterioptimisering for OsmAnd-sporeren slik at det ikke plutselig skrur seg av når det er i bakgrunnen.</string>
<string name="battery_optimization_description">Skru av batterioptimalisering for OsmAnd-sporeren slik at det ikke plutselig skrur seg av når det er i bakgrunnen.</string>
<string name="sharing_in_background">Deling i bakgrunnen</string>
<string name="go_to_settings">Gå til innstillinger</string>
<string name="shared_string_later">Senere</string>

View file

@ -0,0 +1,91 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="328dp"
android:height="90dp"
android:viewportWidth="328"
android:viewportHeight="90">
<group>
<clip-path android:pathData="M0,0h328v90h-328z M 0,0"/>
<path
android:pathData="M2.0,0.0L326.0,0.0A2.0,2.0,0,0,1,328.0,2.0L328.0,88.0A2.0,2.0,0,0,1,326.0,90.0L2.0,90.0A2.0,2.0,0,0,1,0.0,88.0L0.0,2.0A2.0,2.0,0,0,1,2.0,0.0z"
android:fillColor="#F5F5F5"/>
<path
android:pathData="M306 0H278V31H0V59H278V90H306V59H328V31H306V0Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M304 0H280V33H0V57H280V90H304V57H328V33H304V0Z"
android:fillColor="#EAEAEC"/>
<path
android:pathData="M8 45C8 44.4477 8.44772 44 9 44H19C19.5523 44 20 44.4477 20 45C20 45.5523 19.5523 46 19 46H9C8.44772 46 8 45.5523 8 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M32 45C32 44.4477 32.4477 44 33 44H43C43.5523 44 44 44.4477 44 45C44 45.5523 43.5523 46 43 46H33C32.4477 46 32 45.5523 32 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M80 45C80 44.4477 80.4477 44 81 44H91C91.5523 44 92 44.4477 92 45C92 45.5523 91.5523 46 91 46H81C80.4477 46 80 45.5523 80 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M128 45C128 44.4477 128.448 44 129 44H139C139.552 44 140 44.4477 140 45C140 45.5523 139.552 46 139 46H129C128.448 46 128 45.5523 128 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M177 44C176.448 44 176 44.4477 176 45C176 45.5523 176.448 46 177 46H187C187.552 46 188 45.5523 188 45C188 44.4477 187.552 44 187 44H177Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M321 44C320.448 44 320 44.4477 320 45C320 45.5523 320.448 46 321 46H331C331.552 46 332 45.5523 332 45C332 44.4477 331.552 44 331 44H321Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M273 44C272.448 44 272 44.4477 272 45C272 45.5523 272.448 46 273 46H283C283.552 46 284 45.5523 284 45C284 44.4477 283.552 44 283 44H273Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M225 44C224.448 44 224 44.4477 224 45C224 45.5523 224.448 46 225 46H235C235.552 46 236 45.5523 236 45C236 44.4477 235.552 44 235 44H225Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M152 45C152 44.4477 152.448 44 153 44H163C163.552 44 164 44.4477 164 45C164 45.5523 163.552 46 163 46H153C152.448 46 152 45.5523 152 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M104 45C104 44.4477 104.448 44 105 44H115C115.552 44 116 44.4477 116 45C116 45.5523 115.552 46 115 46H105C104.448 46 104 45.5523 104 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M297 44C296.448 44 296 44.4477 296 45C296 45.5523 296.448 46 297 46H307C307.552 46 308 45.5523 308 45C308 44.4477 307.552 44 307 44H297Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M56 45C56 44.4477 56.4477 44 57 44H67C67.5523 44 68 44.4477 68 45C68 45.5523 67.5523 46 67 46H57C56.4477 46 56 45.5523 56 45Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M249 44C248.448 44 248 44.4477 248 45C248 45.5523 248.448 46 249 46H259C259.552 46 260 45.5523 260 45C260 44.4477 259.552 44 259 44H249Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M201 44C200.448 44 200 44.4477 200 45C200 45.5523 200.448 46 201 46H211C211.552 46 212 45.5523 212 45C212 44.4477 211.552 44 211 44H201Z"
android:fillColor="#D7D8DB"/>
<path
android:pathData="M23.8187 58.233C23.2003 57.6146 23.047 56.6698 23.4381 55.8876L28.8819 45L23.4381 34.1124C23.047 33.3302 23.2003 32.3854 23.8187 31.767C24.3865 31.1993 25.2354 31.0191 25.9848 31.3074L57.3923 43.3872C58.0596 43.6438 58.5 44.285 58.5 45C58.5 45.715 58.0596 46.3562 57.3923 46.6128L25.9848 58.6926C25.2354 58.9809 24.3865 58.8007 23.8187 58.233Z"
android:strokeAlpha="0.6"
android:fillColor="#3252F1"
android:fillType="evenOdd"
android:fillAlpha="0.6"/>
<path
android:pathData="M57.0333 44.3205C57.3145 44.4286 57.5 44.6987 57.5 45C57.5 45.3012 57.3145 45.5713 57.0333 45.6795L25.6259 57.7593C25.2453 57.9056 24.8142 57.8142 24.5259 57.5258C24.2118 57.2118 24.134 56.732 24.3326 56.3348L30 45L24.3326 33.6651C24.134 33.2679 24.2118 32.7881 24.5259 32.4741C24.8142 32.1858 25.2453 32.0943 25.6259 32.2407L57.0333 44.3205Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M32 45L27 55L53.2287 44.9999L27 35L32 45Z"
android:fillColor="#3252F1"
android:fillType="evenOdd"/>
<path
android:pathData="M36 45L27 55L32 45L27 35L36 45Z"
android:fillColor="#000000"
android:fillAlpha="0.2"/>
<path
android:pathData="M53.5 45L27 55L36 45H53.5Z"
android:fillColor="#ffffff"
android:fillAlpha="0.1"/>
<path
android:pathData="M65 38H67V52H65V38Z"
android:fillColor="#EE5622"/>
<path
android:pathData="M278 38H280V52H278V38Z"
android:fillColor="#EE5622"/>
<path
android:pathData="M77.1783 50.2652L72.5577 46H272.442L267.822 50.2652L269.178 51.7348L276.474 45L269.178 38.2652L267.822 39.7348L272.442 44H72.5577L77.1783 39.7348L75.8217 38.2652L68.5257 45L75.8217 51.7348L77.1783 50.2652Z"
android:fillColor="#EE5622"/>
</group>
</vector>

View file

@ -0,0 +1,91 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="328dp"
android:height="90dp"
android:viewportWidth="328"
android:viewportHeight="90">
<group>
<clip-path android:pathData="M0,0h328v90h-328z M 0,0"/>
<path
android:pathData="M2.0,0.0L326.0,0.0A2.0,2.0,0,0,1,328.0,2.0L328.0,88.0A2.0,2.0,0,0,1,326.0,90.0L2.0,90.0A2.0,2.0,0,0,1,0.0,88.0L0.0,2.0A2.0,2.0,0,0,1,2.0,0.0z"
android:fillColor="#28292A"/>
<path
android:pathData="M306 0H278V31H0V59H278V90H306V59H328V31H306V0Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M304 0H280V33H0V57H280V90H304V57H328V33H304V0Z"
android:fillColor="#58595B"/>
<path
android:pathData="M8 45C8 44.4477 8.44772 44 9 44H19C19.5523 44 20 44.4477 20 45C20 45.5523 19.5523 46 19 46H9C8.44772 46 8 45.5523 8 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M32 45C32 44.4477 32.4477 44 33 44H43C43.5523 44 44 44.4477 44 45C44 45.5523 43.5523 46 43 46H33C32.4477 46 32 45.5523 32 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M80 45C80 44.4477 80.4477 44 81 44H91C91.5523 44 92 44.4477 92 45C92 45.5523 91.5523 46 91 46H81C80.4477 46 80 45.5523 80 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M128 45C128 44.4477 128.448 44 129 44H139C139.552 44 140 44.4477 140 45C140 45.5523 139.552 46 139 46H129C128.448 46 128 45.5523 128 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M177 44C176.448 44 176 44.4477 176 45C176 45.5523 176.448 46 177 46H187C187.552 46 188 45.5523 188 45C188 44.4477 187.552 44 187 44H177Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M321 44C320.448 44 320 44.4477 320 45C320 45.5523 320.448 46 321 46H331C331.552 46 332 45.5523 332 45C332 44.4477 331.552 44 331 44H321Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M273 44C272.448 44 272 44.4477 272 45C272 45.5523 272.448 46 273 46H283C283.552 46 284 45.5523 284 45C284 44.4477 283.552 44 283 44H273Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M225 44C224.448 44 224 44.4477 224 45C224 45.5523 224.448 46 225 46H235C235.552 46 236 45.5523 236 45C236 44.4477 235.552 44 235 44H225Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M152 45C152 44.4477 152.448 44 153 44H163C163.552 44 164 44.4477 164 45C164 45.5523 163.552 46 163 46H153C152.448 46 152 45.5523 152 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M104 45C104 44.4477 104.448 44 105 44H115C115.552 44 116 44.4477 116 45C116 45.5523 115.552 46 115 46H105C104.448 46 104 45.5523 104 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M297 44C296.448 44 296 44.4477 296 45C296 45.5523 296.448 46 297 46H307C307.552 46 308 45.5523 308 45C308 44.4477 307.552 44 307 44H297Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M56 45C56 44.4477 56.4477 44 57 44H67C67.5523 44 68 44.4477 68 45C68 45.5523 67.5523 46 67 46H57C56.4477 46 56 45.5523 56 45Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M249 44C248.448 44 248 44.4477 248 45C248 45.5523 248.448 46 249 46H259C259.552 46 260 45.5523 260 45C260 44.4477 259.552 44 259 44H249Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M201 44C200.448 44 200 44.4477 200 45C200 45.5523 200.448 46 201 46H211C211.552 46 212 45.5523 212 45C212 44.4477 211.552 44 211 44H201Z"
android:fillColor="#4B4C4E"/>
<path
android:pathData="M23.8187 58.233C23.2003 57.6146 23.047 56.6698 23.4381 55.8876L28.8819 45L23.4381 34.1124C23.047 33.3302 23.2003 32.3854 23.8187 31.767C24.3865 31.1993 25.2354 31.0191 25.9848 31.3074L57.3923 43.3872C58.0596 43.6438 58.5 44.285 58.5 45C58.5 45.715 58.0596 46.3562 57.3923 46.6128L25.9848 58.6926C25.2354 58.9809 24.3865 58.8007 23.8187 58.233Z"
android:strokeAlpha="0.6"
android:fillColor="#3252F1"
android:fillType="evenOdd"
android:fillAlpha="0.6"/>
<path
android:pathData="M57.0333 44.3205C57.3145 44.4286 57.5 44.6987 57.5 45C57.5 45.3012 57.3145 45.5713 57.0333 45.6795L25.6259 57.7593C25.2453 57.9056 24.8142 57.8142 24.5259 57.5258C24.2118 57.2118 24.134 56.732 24.3326 56.3348L30 45L24.3326 33.6651C24.134 33.2679 24.2118 32.7881 24.5259 32.4741C24.8142 32.1858 25.2453 32.0943 25.6259 32.2407L57.0333 44.3205Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M32 45L27 55L53.2287 44.9999L27 35L32 45Z"
android:fillColor="#3252F1"
android:fillType="evenOdd"/>
<path
android:pathData="M36 45L27 55L32 45L27 35L36 45Z"
android:fillColor="#000000"
android:fillAlpha="0.2"/>
<path
android:pathData="M53.5 45L27 55L36 45H53.5Z"
android:fillColor="#ffffff"
android:fillAlpha="0.1"/>
<path
android:pathData="M65 38H67V52H65V38Z"
android:fillColor="#EE5622"/>
<path
android:pathData="M278 38H280V52H278V38Z"
android:fillColor="#EE5622"/>
<path
android:pathData="M77.1783 50.2652L72.5577 46H272.442L267.822 50.2652L269.178 51.7348L276.474 45L269.178 38.2652L267.822 39.7348L272.442 44H72.5577L77.1783 39.7348L75.8217 38.2652L68.5257 45L75.8217 51.7348L77.1783 50.2652Z"
android:fillColor="#EE5622"/>
</group>
</vector>

View file

@ -14,7 +14,7 @@
app:theme="?attr/toolbar_theme"
android:background="?attr/pstsTabBackground"/>
<WebView
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View file

@ -63,7 +63,8 @@
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<WebView
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/content_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View file

@ -4,7 +4,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView android:id="@+id/webView"
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>

View file

@ -4,12 +4,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>
</net.osmand.plus.widgets.WebViewEx>
<include layout="@layout/mapillary_no_internet"
android:id="@+id/mapillaryNoInternetLayout"

View file

@ -3,7 +3,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/printDialogWebview"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View file

@ -74,7 +74,7 @@
android:layout_height="0dp"
android:layout_weight="1">
<WebView
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/content_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View file

@ -108,7 +108,7 @@
<string name="poi_cave_entrance">Höhleneingang</string>
<string name="poi_cemetery">Friedhof</string>
<string name="poi_chalet">Ferienhaus</string>
<string name="poi_electricity_combined_charging">Ladestation</string>
<string name="poi_electricity_combined_charging">Ladestation;Ladestation für elektische Fahrzeuge;Aufladestation</string>
<string name="poi_chemist">Drogerie</string>
<string name="poi_chess">Schach</string>
<string name="poi_clothes_children">Kinderbekleidungsgeschäft</string>

View file

@ -4032,4 +4032,22 @@
<string name="routing_attr_allow_intermittent_description">Gewässer erlauben, die nicht ständig Wasser führen</string>
<string name="routing_attr_allow_intermittent_name">Gewässer erlauben, die nicht ständig Wasser führen</string>
<string name="voice_prompts_timetable">Zeiten der Sprachansagen</string>
<string name="add_online_routing_engine">Online Routenplaner hinzufügen</string>
<string name="edit_online_routing_engine">Online Routenplaner bearbeiten</string>
<string name="shared_string_vehicle">Fahrzeug</string>
<string name="shared_string_api_key">API Schlüssel</string>
<string name="shared_string_server_url">Server URL</string>
<string name="shared_string_enter_param">Parameter eingeben</string>
<string name="online_routing_example_hint">Die URL mit allen Parametern wird so aussehen:</string>
<string name="test_route_calculation">Routenberechnung testen</string>
<string name="routing_engine_vehicle_type_foot">Zu Fuß</string>
<string name="routing_engine_vehicle_type_bike">Fahrrad</string>
<string name="routing_engine_vehicle_type_car">Auto</string>
<string name="message_error_recheck_parameters">Fehler, Parameter erneut prüfen</string>
<string name="shared_string_subtype">Subtyp</string>
<string name="keep_it_empty_if_not">Leer lassen, wenn kein API-Schlüssel vorhanden</string>
<string name="copy_address">Adresse kopieren</string>
<string name="routing_engine_vehicle_type_driving">Fahren</string>
<string name="online_routing_engine">Online Navigationssystem</string>
<string name="online_routing_engines">Online Navigationssysteme</string>
</resources>

View file

@ -4028,4 +4028,22 @@
<string name="routing_attr_allow_intermittent_description">Permesi navigi per periode sekiĝantaj akvovojoj</string>
<string name="routing_attr_allow_intermittent_name">Permesi sezonajn akvovojojn</string>
<string name="voice_prompts_timetable">Tempoj de voĉaj anoncoj</string>
<string name="add_online_routing_engine">Aldoni enretan navigilon</string>
<string name="edit_online_routing_engine">Redakti enretan navigilon</string>
<string name="shared_string_subtype">Subspeco</string>
<string name="shared_string_vehicle">Veturilo</string>
<string name="shared_string_api_key">API-ŝlosilo</string>
<string name="shared_string_server_url">Ligilo al servilo</string>
<string name="shared_string_enter_param">Enigu parametron</string>
<string name="keep_it_empty_if_not">Se malnecesa, enigu nenion</string>
<string name="online_routing_example_hint">Ligilo kun ĉiuj parametroj aspektos kiel tiu ĉi:</string>
<string name="routing_engine_vehicle_type_driving">Stirado</string>
<string name="test_route_calculation">Testi kalkuli kurson</string>
<string name="routing_engine_vehicle_type_foot">Piediranto</string>
<string name="routing_engine_vehicle_type_bike">Biciklo</string>
<string name="routing_engine_vehicle_type_car">Aŭtomobilo</string>
<string name="message_error_recheck_parameters">Eraro, rekontrolu parametrojn</string>
<string name="copy_address">Kopii adreson</string>
<string name="online_routing_engine">Enreta navigilo</string>
<string name="online_routing_engines">Enretaj navigiloj</string>
</resources>

View file

@ -4033,4 +4033,20 @@
<string name="routing_attr_allow_intermittent_description">Permite cursos de agua intermitentes</string>
<string name="routing_attr_allow_intermittent_name">Permitir cursos de agua intermitentes</string>
<string name="voice_prompts_timetable">Tiempo de los avisos por voz</string>
<string name="add_online_routing_engine">Añadir motor de navegación en línea</string>
<string name="edit_online_routing_engine">Editar motor de navegación en línea</string>
<string name="shared_string_subtype">Subtipo</string>
<string name="shared_string_vehicle">Vehículo</string>
<string name="shared_string_api_key">Clave de la API</string>
<string name="shared_string_server_url">URL del servidor</string>
<string name="shared_string_enter_param">Ingresa parámetro</string>
<string name="keep_it_empty_if_not">Si no, mantenerlo vacío</string>
<string name="online_routing_example_hint">La URL con todos los parámetros se verá así:</string>
<string name="test_route_calculation">Cálculo de la ruta de prueba</string>
<string name="routing_engine_vehicle_type_driving">Automóvil</string>
<string name="routing_engine_vehicle_type_foot">Peatón</string>
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
<string name="routing_engine_vehicle_type_car">Automóvil</string>
<string name="message_error_recheck_parameters">Error, vuelve a comprobar los parámetros</string>
<string name="copy_address">Copiar dirección</string>
</resources>

View file

@ -785,7 +785,7 @@
<string name="no_fav_to_save">Ez dago gogoko punturik gordetzeko</string>
<string name="shared_string_import">Inportatu</string>
<string name="error_occurred_loading_gpx">Ezin izan da GPX kargatu.</string>
<string name="send_report">Bidali informea</string>
<string name="send_report">Bidali txostena</string>
<string name="none_region_found">Ezin izan da deskargatutako maparik aurkitu memoria txartelean.</string>
<string name="poi_namefinder_query_empty">Idatzi interesgune bat bilatzeko</string>
<string name="any_poi">Edozein</string>
@ -4008,4 +4008,18 @@ Area honi dagokio: %1$s x %2$s</string>
<string name="plan_route_split_before">Zatitu aurretik</string>
<string name="plan_route_split_after">Zatitu ondoren</string>
<string name="plan_route_add_new_segment">Gehitu segmentu berria</string>
<string name="shared_string_subtype">Azpimota</string>
<string name="shared_string_vehicle">Ibilgailua</string>
<string name="shared_string_api_key">API gakoa</string>
<string name="shared_string_server_url">Zerbitzariaren URLa</string>
<string name="shared_string_enter_param">Sartu parametroa</string>
<string name="keep_it_empty_if_not">Mantendu hutsik hala ez bada</string>
<string name="online_routing_example_hint">Parametro guztiak dituen URLak itxura hau izango du:</string>
<string name="test_route_calculation">Proba ibilbidearen kalkulua</string>
<string name="routing_engine_vehicle_type_driving">Gidatzen</string>
<string name="routing_engine_vehicle_type_foot">Oinez</string>
<string name="routing_engine_vehicle_type_bike">Bizikleta</string>
<string name="routing_engine_vehicle_type_car">Kotxea</string>
<string name="message_error_recheck_parameters">Errorea, egiaztatu parametroak berriro</string>
<string name="copy_address">Kopiatu helbidea</string>
</resources>

View file

@ -163,7 +163,7 @@
<string name="local_osm_changes_backup">پشتیبان‌گیری در قالب تغییر OSM</string>
<string name="delete_point">حذف نقطه</string>
<string name="use_kalman_filter_compass">استفاده از پالایهٔ Kalman</string>
<string name="cancel_route">حذف مسیر</string>
<string name="cancel_route">کنارگذاشتن مسیر؟</string>
<string name="max_speed_none">هیچ‌کدام</string>
<string name="dropbox_plugin_name">افزونهٔ دراپ‌باکس</string>
<string name="av_use_external_recorder_descr">برای فیلم‌برداری از ضبط‌کنندهٔ سیستم استفاده شود.</string>
@ -644,7 +644,7 @@
<string name="auto_announce_off">توقف اعلام خودکار</string>
<string name="use_fluorescent_overlays_descr">برای نمایش ردها و مسیرها از رنگ‌های شب‌نما استفاده شود.</string>
<string name="offline_edition">ویرایش آفلاین</string>
<string name="offline_edition_descr">ویرایش‌ها را همیشه آفلاین انجام می‌دهم.</string>
<string name="offline_edition_descr">اگر ویرایش آفلاین فعال باشد، تغییرات ابتدا روی دستگاه ذخیره می‌شود و با درخواست شما آپلود می‌گردد. در غیر این صورت دردَم آپلود خواهد شد.</string>
<string name="local_openstreetmap_uploading">در حال آپلود…</string>
<string name="local_openstreetmap_were_uploaded">تعداد {0} یادداشت/POI آپلود شد</string>
<string name="update_poi_does_not_change_indexes">تغییراتی که به‌وسیلهٔ برنامه روی POIها انجام می‌دهید روی نقشه‌های دانلود‌شده تأثیری ندارد. تغییرات روی فایل دیگری در دستگاه ذخیره می‌شود.</string>
@ -1687,7 +1687,7 @@
<string name="access_direction_haptic_feedback_descr">بیان‌کردن جهت مقصد با لرزش.</string>
<string name="use_osm_live_routing_description">مسیریابی با استفاده از به‌روزرسانی‌های OsmAnd Live فعال شود.</string>
<string name="use_osm_live_routing">مسیریابی با OsmAnd Live</string>
<string name="access_no_destination">مقصد تنظیم نشده</string>
<string name="access_no_destination">افزونهٔ قابلیت دسترسی: مقصدی تنظیم نشده</string>
<string name="map_widget_magnetic_bearing">سویهٔ مغناطیسی</string>
<string name="map_widget_bearing">سویهٔ نسبی</string>
<string name="access_disable_offroute_recalc">اگر از مسیر خارج شدم، مسیر تازه‌ای پیدا نکن</string>
@ -2151,7 +2151,7 @@
<string name="number_of_contributors">تعداد مشارکت‌کنندگان</string>
<string name="number_of_edits">تعداد ویرایش‌ها</string>
<string name="reports_for">گزارش برای</string>
<string name="file_name_containes_illegal_char">در نام فایل از نویسهٔ غیرمجاز استفاده شده است</string>
<string name="file_name_containes_illegal_char">نویسهٔ غیرمجاز در نام فایل</string>
<string name="configure_screen_quick_action">کنش فوری</string>
<string name="quick_action_item_action">کنش %d</string>
<string name="quick_action_item_screen">صفحهٔ %d</string>
@ -2301,7 +2301,7 @@
<string name="quick_action_showhide_osmbugs_descr">دکمه‌ای برای آشکار/پنهان کردن یادداشت‌های OSM بر روی نقشه.</string>
<string name="sorted_by_distance">مرتب‌شده بر اساس مسافت</string>
<string name="search_favorites">جست‌وجو در علاقه‌مندی‌ها</string>
<string name="hillshade_menu_download_descr">«لایهٔ سایه‌روشن» را دانلود کنید تا سایه‌های عمودی را ببینید.</string>
<string name="hillshade_menu_download_descr">لایهٔ «سایه‌روشن» را دانلود کنید تا سایه‌زنی‌های عمودی را ببینید.</string>
<string name="hillshade_purchase_header">افزونهٔ «منحنی‌های میزان» را نصب کنید تا طبقه‌بندی عمودی محدوده‌ها را ببینید.</string>
<string name="hide_from_zoom_level">از این زوم پنهان شود</string>
<string name="srtm_menu_download_descr">نقشهٔ «منحنی میزان» را برای استفاده در این منطقه دانلود کنید.</string>
@ -2664,7 +2664,7 @@
<string name="copy_location_name">کپی موقعیت/نام POI</string>
<string name="toast_empty_name_error">مکان بی‌نام</string>
<string name="show_closed_notes">دیدن یادداشت‌های بسته</string>
<string name="switch_osm_notes_visibility_desc">پنهان/آشکارکردن یادداشت‌های OSM.</string>
<string name="switch_osm_notes_visibility_desc">پنهان یا آشکارکردن یادداشت‌های OSM.</string>
<string name="gpx_file_desc">GPX - مناسب برای استفاده در JOSM یا سایر ویرایشگرهای OSM.</string>
<string name="osc_file_desc">OSC - مناسب برای استفاده در OSM.</string>
<string name="shared_string_gpx_file">فایل GPX</string>
@ -3188,9 +3188,9 @@
<string name="rendering_attr_showLez_description">محدوده‌های کاهش آلودگی هوای شهر را روی نقشه نشان بده. روی مسیریابی اثر نمی‌گذارد.</string>
<string name="rendering_attr_showLez_name">محدوده‌های کاهش</string>
<string name="temporary_conditional_routing">در نظر گرفتن محدودیت‌های موقت در مسیریابی</string>
<string name="routing_attr_piste_type_downhill_name">اسکی آلپاین/دان‌هیل</string>
<string name="routing_attr_piste_type_downhill_name">اسکی آلپاین و دانهیل</string>
<string name="routing_attr_piste_type_downhill_description">سراشیبی‌های اسکی آلپاین یا دان‌هیل و دسترسی به بالابرهای اسکی.</string>
<string name="routing_attr_piste_type_nordic_name">اسکی کراس/نوردیک</string>
<string name="routing_attr_piste_type_nordic_name">اسکی کراس‌کانتری و نوردیک</string>
<string name="routing_attr_piste_type_nordic_description">مسیرهای اسکی کراس یا نوردیک.</string>
<string name="shared_string_crash">شکست</string>
<string name="shared_string_open_track">باز کن</string>
@ -3456,7 +3456,7 @@
<string name="button_rate">امتیاز بدهید</string>
<string name="monitoring_prefs_descr">ناوبری، صحت ردنگاری</string>
<string name="multimedia_notes_prefs_descr">اندازهٔ عکس، کیفیت صدا و ویدئو</string>
<string name="osm_editing_prefs_descr">ثبت ورود، گذرواژه، ویرایش آفلاین</string>
<string name="osm_editing_prefs_descr">نام کاربری، گذرواژه، ویرایش آفلاین</string>
<string name="accessibility_prefs_descr">انتخاب نماد، رنگ و نام</string>
<string name="live_monitoring">ردیابی آنلاین</string>
<string name="save_track_logging_accuracy">صحت ردنگاری</string>
@ -3464,7 +3464,7 @@
<string name="photo_notes">یادداشت‌های عکسی</string>
<string name="route_recalculation">محاسبهٔ مجدد مسیر</string>
<string name="login_and_pass">نام کاربری و گذرواژه</string>
<string name="plugin_global_prefs_info">این تنظیمات افزونه، سراسری است و روی همهٔ پروفایل‌ها به کار گرفته می‌شود.</string>
<string name="plugin_global_prefs_info">این تنظیمات افزونه، سراسری است و روی همهٔ پروفایل‌ها به کار گرفته می‌شود</string>
<string name="osm_editing">ویرایش OSM</string>
<string name="app_mode_osm">OSM</string>
<string name="select_nav_icon_descr">نمادی که هنگام حرکت یا ناوبری نمایش داده می‌شود.</string>
@ -3594,7 +3594,7 @@
<string name="shared_string_terrain">ناهمواری‌ها</string>
<string name="hillshade_description">نقشهٔ سایه‌روشن که شیب‌ها، بلندی‌ها و پستی‌ها را با استفاده از سایه‌های تیره نمایان می‌کند.</string>
<string name="terrain_slider_description">کمینه و بیشینهٔ زوم برای نمایش لایه را مشخص کنید.</string>
<string name="hillshade_download_description">برای مشاهدهٔ سایه‌روشن‌ها روی نقشه باید نقشهٔ دیگری را نیز دانلود کنید.</string>
<string name="hillshade_download_description">"باید نقشهٔ دیگری را نیز دانلود کنید تا سایه‌روشن‌ها را روی نقشه ببینید."</string>
<string name="slope_download_description">برای مشاهدهٔ شیب‌ها روی نقشه باید نقشهٔ دیگری را نیز دانلود کنید.</string>
<string name="slope_read_more">دربارهٔ شیب‌ها می‌توانید در %1$s بیشتر بخوانید.</string>
<string name="shared_string_transparency">شفافیت</string>
@ -3604,7 +3604,7 @@
<string name="shared_string_hillshade">سایه‌روشن</string>
<string name="n_items_of_z">%1$s از %2$s</string>
<string name="download_slope_maps">شیب‌ها</string>
<string name="quick_action_show_hide_terrain">آشکار/پنهان کردن ناهمواری‌ها</string>
<string name="quick_action_show_hide_terrain">آشکار یا پنهان کردن ناهمواری‌ها</string>
<string name="quick_action_terrain_hide">پنهان‌کردن ناهمواری‌ها</string>
<string name="quick_action_terrain_show">نمایش ناهمواری‌ها</string>
<string name="quick_action_terrain_descr">دکمه‌ای برای آشکار یا پنهان کردن لایهٔ ناهمواری‌ها روی نقشه.</string>
@ -3717,12 +3717,12 @@
\n
\n</string>
<string name="back_to_editing">بازگشت به ویرایش</string>
<string name="create_edit_poi">ایجاد / ویرایش POI</string>
<string name="add_edit_favorite">افزودن / ویرایش علاقه‌مندی</string>
<string name="create_edit_poi">ایجاد یا ویرایش POI</string>
<string name="add_edit_favorite">افزودن یا ویرایش علاقه‌مندی</string>
<string name="additional_actions_descr">برای دسترسی به این کنش‌ها می‌توانید روی دکمهٔ «%1$s» بزنید.</string>
<string name="quick_action_transport_hide">مخفی‌کردن حمل‌ونقل عمومی</string>
<string name="quick_action_transport_show">نمایش حمل‌ونقل عمومی</string>
<string name="quick_action_show_hide_transport">آشکار/پنهان کردن حمل‌ونقل عمومی</string>
<string name="quick_action_show_hide_transport">آشکار یا پنهان کردن حمل‌ونقل عمومی</string>
<string name="quick_action_transport_descr">دکمه‌ای برای آشکار یا پنهان کردن حمل‌ونقل عمومی روی نقشه.</string>
<string name="quick_action_switch_profile_descr">با لمس دکمهٔ عملیاتی بین پروفایل‌های انتخاب‌شده جابه‌جا شوید.</string>
<string name="shared_string_add_profile">افزودن پروفایل</string>
@ -3823,7 +3823,7 @@
<string name="quick_action_remove_next_destination">حذف نزدیک‌ترین مقصد</string>
<string name="please_provide_point_name_error">لطفاً نام نقطه را بنویسید</string>
<string name="search_download_wikipedia_maps">دانلود نقشه‌های ویکی‌پدیا</string>
<string name="plugin_wikipedia_description">از ویکی‌پدیا دربارهٔ نقاط توجه اطلاعات کسب کنید؛ مانند یک راهنمای آفلاین جیبی. کافی است افزونهٔ ویکی‌پدیا را فعال کنید و از مقاله‌های مربوط به چیزهای دوروبرتان لذت ببرید.</string>
<string name="plugin_wikipedia_description">دربارهٔ نقاط توجه، از ویکی‌پدیا اطلاعات کسب کنید. یک راهنمای آفلاینِ جیبی که مقاله‌هایی دربارهٔ مکان‌ها و مقصدها دارد.</string>
<string name="app_mode_wheelchair">صندلی چرخ‌دار</string>
<string name="osm_edit_closed_note">یادداشت اُاِس‌اِمی بسته</string>
<string name="add_hidden_group_info">نقطهٔ اضافه‌شده روی نقشه دیده نمی‌شود، زیرا گروه انتخاب‌شده پنهان است. آن را در «%s» پیدا می‌کنید.</string>
@ -3864,11 +3864,11 @@
\n</string>
<string name="plan_route_trim_before">حذفِ قبل</string>
<string name="plan_route_trim_after">حذفِ بعد</string>
<string name="plan_route_change_route_type_before">تغییر نوع مسیرِ بعد آن</string>
<string name="plan_route_change_route_type_after">تغییر نوع مسیرِ قبل آن</string>
<string name="plan_route_change_route_type_before">تغییر نوع مسیرِ بعد</string>
<string name="plan_route_change_route_type_after">تغییر نوع مسیرِ قبل</string>
<string name="track_coloring_solid">تک‌رنگ</string>
<string name="lenght_limit_description">طول وسیلهٔ نقلیهٔ خود را مشخص کنید. ممکن است محدودیت‌های مسیر برای وسایل نقلیهٔ طویل اِعمال شود.</string>
<string name="quick_action_remove_next_destination_descr">مقصد کنونی مسیر حذف خواهد شد. اگر این قرار است مقصد باشد، ناوبری متوقف می‌شود.</string>
<string name="quick_action_remove_next_destination_descr">مقصد بعدیِ مسیر شما را حذف خواهد کرد. البته اگر مقصد نهایی باشد، ناوبری را متوقف می‌کند.</string>
<string name="add_to_a_track">افزودن به یک رد</string>
<string name="save_as_new_track">ذخیره به‌عنوان رد جدید</string>
<string name="reverse_route">برعکس‌کردن مسیر</string>
@ -3886,7 +3886,7 @@
<string name="navigation_profile">پروفایل ناوبری</string>
<string name="route_between_points_add_track_desc">یک فایل رد انتخاب کنید تا پارهٔ جدید را به آن بیفزایید.</string>
<string name="street_level_imagery">تصاویر نمای خیابان</string>
<string name="plan_route_exit_dialog_descr">آیا می‌خواهید خارج شوید و همهٔ تغییرات مسیر طراحی‌شده را از بین ببرید؟</string>
<string name="plan_route_exit_dialog_descr">آیا می‌خواهید همهٔ تغییرات در مسیر طراحی‌شده از بین برود؟</string>
<string name="in_case_of_reverse_direction">اگر برعکس حرکت کردم</string>
<string name="start_of_the_track">ابتدای رد</string>
<string name="follow_track_descr">انتخاب فایل رد برای دنبال‌کردن</string>
@ -3963,15 +3963,15 @@
\nنمودار پس از بازمحاسبهٔ مسیر فراهم می‌شود.</string>
<string name="ltr_or_rtl_combine_via_dash">%1$s — %2$s</string>
<string name="message_you_need_add_two_points_to_show_graphs">دست‌کم دو نقطه اضافه کنید</string>
<string name="login_open_street_map">ثبت ورود در اوپن‌استریت‌مپ</string>
<string name="login_open_street_map_org">ثبت ورود در OpenStreetMap.org</string>
<string name="login_open_street_map">ورود به اوپن‌استریت‌مپ</string>
<string name="login_open_street_map_org">ورود به OpenStreetMap.org</string>
<string name="sign_in_with_open_street_map">ثبت ورود از طریق اوپن‌استریت‌مپ</string>
<string name="open_street_map_login_mode">برای آپلود تغییرات جدید باید ثبت ورود (login) کنید.
<string name="open_street_map_login_mode">برای آپلود تغییرات جدید باید وارد شوید (login).
\n
\nبرای ثبت ورود می‌توانید از روش امن OAuth یا روش نام کاربری و گذرواژه استفاده کنید.</string>
\nبرای ورود می‌توانید از روش امن OAuth یا روش نام کاربری و گذرواژه استفاده کنید.</string>
<string name="use_login_password">استفاده از نام کاربری و گذرواژه</string>
<string name="login_account">حساب</string>
<string name="user_login">ثبت ورود</string>
<string name="user_login">ورود</string>
<string name="manage_subscription">مدیریت اشتراک</string>
<string name="subscription_payment_issue_title">روی دکمه بزنید و یک شیوهٔ پرداخت در گوگل‌پلی تنظیم کنید تا اشتراک خود را اصلاح نمایید.</string>
<string name="markers_history">تاریخچهٔ نشانه‌ها</string>
@ -4006,4 +4006,35 @@
<string name="plan_route_add_new_segment">افزودن یک بخش جدید</string>
<string name="profile_type_osmand_string">نمایهٔ OsmAnd</string>
<string name="profile_type_user_string">نمایهٔ کاربر</string>
<string name="voice_prompts_timetable">زمان‌های پیام‌های گفتاری</string>
<string name="navigate_point_mgrs">MGRS</string>
<string name="navigate_point_format_mgrs">MGRS</string>
<string name="mgrs_format_descr">OsmAnd از MGRS استفاده می‌کند که شبیه قالب UTM NATO است.</string>
<string name="contour_lines_thanks">سپاسگزاریم که Contour lines را خریدید</string>
<string name="enter_text_separated">برچسب‌ها را بنویسید و با کاما جدا کنید.</string>
<string name="osm_edit_close_note">بستن یادداشت OSM</string>
<string name="osm_edit_comment_note">نظردادن به یادداشت OSM</string>
<string name="osm_login_descr">می‌توانید با روش ایمن OAuth وارد شوید یا از نام‌کاربری و گذرواژه‌تان استفاده کنید.</string>
<string name="app_mode_motorboat">قایق‌موتوری</string>
<string name="cannot_upload_image">آپلود عکس ناموفق بود، لطفاً بعداً دوباره امتحان کنید</string>
<string name="select_picture">انتخاب تصویر</string>
<string name="shared_string_resources">منابع</string>
<string name="approximate_file_size">اندازهٔ تخمینی فایل</string>
<string name="select_data_to_export">دادهٔ موردنظر برای برون‌برد در فایل را انتخاب کنید.</string>
<string name="file_size_needed_for_import">برای درون‌برد لازم است</string>
<string name="reverse_all_points">برعکس‌کردن همهٔ نقطه‌ها</string>
<string name="profile_by_default_description">پروفایلِ هنگام شروع برنامه را انتخاب کنید.</string>
<string name="shared_string_last_used">آخرین استفاده</string>
<string name="add_online_routing_engine">افزودن موتور مسیریابی آنلاین</string>
<string name="edit_online_routing_engine">ویرایش موتور مسیریابی آنلاین</string>
<string name="shared_string_vehicle">وسیله نقلیه</string>
<string name="shared_string_api_key">کلید API</string>
<string name="shared_string_enter_param">پارامتر را وارد کنید</string>
<string name="online_routing_example_hint">URL با همهٔ پارامترها شبیه این است:</string>
<string name="test_route_calculation">آزمایش محاسبهٔ مسیر</string>
<string name="routing_engine_vehicle_type_driving">رانندگی</string>
<string name="routing_engine_vehicle_type_foot">پا</string>
<string name="routing_engine_vehicle_type_bike">دوچرخه</string>
<string name="routing_engine_vehicle_type_car">خودرو</string>
<string name="message_error_recheck_parameters">خطا، پارامترها را بازبینی کنید</string>
</resources>

View file

@ -3896,8 +3896,11 @@
<string name="poi_vaccination_covid19">Vaccination : covid19</string>
<string name="poi_health_specialty_vaccination_yes">Vaccination</string>
<string name="poi_wildlife_crossing_bat_tunnel">Tunnel à chauve-souris</string>
<string name="poi_wildlife_crossing_bat_bridge">Pont à chauve-</string>
<string name="poi_wildlife_crossing">Passage à faune</string>
<string name="poi_swimming_area">Zone de</string>
<string name="poi_wildlife_crossing_bat_bridge">Pont à chauve-souris</string>
<string name="poi_wildlife_crossing">Passage de faune</string>
<string name="poi_swimming_area">Zone de baignade</string>
<string name="poi_lavoir">Lavoir</string>
<string name="poi_waste_transfer_station">Station de traitement des déchets</string>
<string name="poi_weightbridge">Pont de levage</string>
<string name="poi_ranger_station">Poste de garde forestier</string>
</resources>

View file

@ -4019,4 +4019,10 @@
<string name="routing_engine_vehicle_type_bike">Vélo</string>
<string name="routing_engine_vehicle_type_car">Automobile</string>
<string name="message_error_recheck_parameters">Erreur, vérifiez les paramètres</string>
<string name="add_online_routing_engine">Ajouter un moteur de routage en ligne</string>
<string name="edit_online_routing_engine">Modifier le moteur de routage en ligne</string>
<string name="online_routing_example_hint">L\'URL avec tous les paramètres sera de la forme :</string>
<string name="copy_address">Copier l\'adresse</string>
<string name="online_routing_engine">Moteur de routage en ligne</string>
<string name="online_routing_engines">Moteurs de routage en ligne</string>
</resources>

View file

@ -4050,4 +4050,20 @@ Lon %2$s</string>
<string name="routing_attr_allow_streams_name">Permitir regatos e cunetas</string>
<string name="routing_attr_allow_intermittent_description">Permitir canles de auga intermitentes</string>
<string name="routing_attr_allow_intermittent_name">Permitir canles de auga intermitentes</string>
<string name="add_online_routing_engine">Engadir motor de navegación en liña</string>
<string name="edit_online_routing_engine">Editar motor de navegación en liña</string>
<string name="shared_string_subtype">Subtipo</string>
<string name="shared_string_vehicle">Vehículo</string>
<string name="shared_string_api_key">Chave da API</string>
<string name="shared_string_server_url">URL do servidor</string>
<string name="shared_string_enter_param">Insire parámetro</string>
<string name="keep_it_empty_if_not">Mantenlo baleiro se non</string>
<string name="online_routing_example_hint">A URL con todos os parámetros será así:</string>
<string name="test_route_calculation">Cálculo da ruta de proba</string>
<string name="routing_engine_vehicle_type_driving">Conducindo</string>
<string name="routing_engine_vehicle_type_foot"></string>
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
<string name="routing_engine_vehicle_type_car">Coche</string>
<string name="message_error_recheck_parameters">Erro, verifica novamente os parámetros</string>
<string name="copy_address">Copiar enderezo</string>
</resources>

View file

@ -4035,4 +4035,7 @@
<string name="online_routing_example_hint">Az összes paraméterrel rendelkező URL így néz ki:</string>
<string name="test_route_calculation">Útvonaltervezés kipróbálása</string>
<string name="message_error_recheck_parameters">Hiba, ellenőrizze újra a paramétereket</string>
<string name="copy_address">Cím másolása</string>
<string name="online_routing_engine">Online útvonaltervező</string>
<string name="online_routing_engines">Online útvonaltervezők</string>
</resources>

View file

@ -286,7 +286,7 @@
<string name="poi_fuel_biogas">Lífgas</string>
<string name="poi_fuel_lh2">Fljótandi vetni</string>
<string name="poi_fuel_electricity">Rafmagn</string>
<string name="poi_electricity_combined_charging">Hleðslustöð</string>
<string name="poi_electricity_combined_charging">Hleðslustöð;Hleðslustöð fyrir rafknúin farartæki;EV-hleðslustöð;Hleðslustæði;Rafhleðslustæði;Þjónustustöð fyrir rafknúin farartæki</string>
<string name="poi_compressed_air">Loftdæla</string>
<string name="poi_motorcycle_parking">Mótorhjólastæði</string>
<string name="poi_parking_entrance">Aðgangur að bílastæði</string>
@ -3883,4 +3883,8 @@
<string name="poi_lavoir">Þvottaþró (þvottaaðstaða)</string>
<string name="poi_water_source_river">Á</string>
<string name="poi_lifeguard_base">Bækistöð öryggisvarða</string>
<string name="poi_wildlife_crossing_bat_tunnel">Göng fyrir leðurblökur</string>
<string name="poi_wildlife_crossing_bat_bridge">Brú fyrir leðurblökur</string>
<string name="poi_wildlife_crossing">Þverun villtra dýra</string>
<string name="poi_swimming_area">Sundsvæði</string>
</resources>

View file

@ -4029,4 +4029,29 @@
<string name="profile_type_user_string">Notandasnið</string>
<string name="reverse_all_points">Snúa við öllum punktum</string>
<string name="profile_type_osmand_string">OsmAnd-snið</string>
<string name="voice_prompts_timetable">Tímasetning raddskipana</string>
<string name="profile_by_default_description">Veldu sniðið sem verður notað þegar forritið er ræst.</string>
<string name="shared_string_last_used">Síðast notað</string>
<string name="routing_attr_prefer_hiking_routes_description">Velja frekar gönguleiðir</string>
<string name="routing_attr_prefer_hiking_routes_name">Velja frekar gönguleiðir</string>
<string name="routing_attr_allow_streams_description">Leyfa læki og afföll</string>
<string name="routing_attr_allow_streams_name">Leyfa læki og afföll</string>
<string name="routing_attr_allow_intermittent_description">Leyfa tímabundnar vatnaleiðir</string>
<string name="routing_attr_allow_intermittent_name">Leyfa tímabundnar vatnaleiðir</string>
<string name="add_online_routing_engine">Bæta við leiðagerð af netinu</string>
<string name="edit_online_routing_engine">Breyta nettengdri leiðagerð</string>
<string name="shared_string_subtype">Undirtegund</string>
<string name="shared_string_vehicle">Farartæki</string>
<string name="shared_string_api_key">API-lykill</string>
<string name="shared_string_server_url">Vefslóð netþjóns</string>
<string name="shared_string_enter_param">Setja inn breytu</string>
<string name="keep_it_empty_if_not">Halda þessu auðu ef ekki</string>
<string name="online_routing_example_hint">Vefslóð með öllum breytum mun líta svona út:</string>
<string name="test_route_calculation">Útreikningur prufuleiðar</string>
<string name="routing_engine_vehicle_type_driving">Akstur</string>
<string name="routing_engine_vehicle_type_foot">Gangandi</string>
<string name="routing_engine_vehicle_type_bike">Hjólandi</string>
<string name="routing_engine_vehicle_type_car">Bíll</string>
<string name="message_error_recheck_parameters">Villa, yfirfarðu breytur</string>
<string name="copy_address">Afrita heimilisfang</string>
</resources>

View file

@ -4047,4 +4047,7 @@
<string name="routing_engine_vehicle_type_bike">אופנוע</string>
<string name="routing_engine_vehicle_type_car">מכונית</string>
<string name="message_error_recheck_parameters">שגיאה, נא לבדוק את המשתנים מחדש</string>
<string name="copy_address">העתקת כתובת</string>
<string name="online_routing_engine">מנוע ניווט מקוון</string>
<string name="online_routing_engines">מנועי ניווט מקוונים</string>
</resources>

View file

@ -2350,4 +2350,10 @@
<string name="profile_type_base_string">ბაზური პროფილი</string>
<string name="profile_type_descr_string">ტიპი: %s</string>
<string name="settings_routing_mode_string">რეჟიმი: %s</string>
<string name="routing_attr_avoid_footways_description">საცალფეხო გზების არიდება</string>
<string name="routing_attr_avoid_footways_name">საცალფეხო ფზების არიდება</string>
<string name="shared_string_is_saved">შენახულია</string>
<string name="sort_last_modified">ბოლო ცვლილება</string>
<string name="sort_name_descending">სახელი: ჰ-ა</string>
<string name="sort_name_ascending">სახელი: ა-ჰ</string>
</resources>

View file

@ -121,7 +121,7 @@
<string name="poi_vehicle_inspection">Stacja diagnostyczna</string>
<string name="poi_car_wash">Myjnia samochodowa</string>
<string name="poi_fuel">Stacja benzynowa;Stacja paliw;CPN;Tanksztela</string>
<string name="poi_electricity_combined_charging">Stacja ładowania</string>
<string name="poi_electricity_combined_charging">Stacja ładująca; Stacja ładowania pojazdów elektrycznych; Stacja ładująca EV; Elektryczny punkt ładowania; Punkt ładowania; Elektroniczna stacja ładująca; Sprzęt do zasilania pojazdów elektrycznych</string>
<string name="poi_vehicle_ramp">Podnośnik</string>
<string name="poi_compressed_air">Kompresor</string>
<string name="poi_parking">Parking</string>
@ -3880,4 +3880,20 @@
<string name="poi_water_source_river">Rzeka</string>
<string name="poi_vaccination_covid19">Szczepienia: COVID19</string>
<string name="poi_health_specialty_vaccination_yes">Szczepienia</string>
<string name="poi_swimming_area">Kąpielisko</string>
<string name="poi_waste_transfer_station">Stacja przeładunkowa</string>
<string name="poi_weightbridge">Waga pomostowa</string>
<string name="poi_ranger_station">Stacja strażników</string>
<string name="poi_water_source_powered_pump">Pompa zasilana</string>
<string name="poi_water_source_water_works">Stacja uzdatniania wody</string>
<string name="poi_water_source_tube_well">Studnia rurowa</string>
<string name="poi_lifeguard_base">Baza ratowników</string>
<string name="poi_mobile_money_agent">Mobilny agent pieniędzy</string>
<string name="poi_liaison_subnational">Subnarodowe</string>
<string name="poi_liaison_representative_office">Przedstawicielstwo</string>
<string name="poi_consulate_honorary_consul">Konsul honorowy</string>
<string name="poi_consulate_consular_office">Biuro konsularne</string>
<string name="poi_embassy_interests_section">Sekcja zainteresowań</string>
<string name="poi_diplomatic_liaison">Łączność</string>
<string name="poi_liaison_filter">Łączność</string>
</resources>

View file

@ -4032,4 +4032,17 @@
<string name="routing_attr_allow_streams_name">Zezwalaj na strumienie i dreny</string>
<string name="routing_attr_allow_intermittent_description">Zezwalaj na przerywane drogi wodne</string>
<string name="routing_attr_allow_intermittent_name">Zezwalaj na przerywane drogi wodne</string>
<string name="voice_prompts_timetable">Czas monitów głosowych</string>
<string name="shared_string_subtype">Podtyp</string>
<string name="shared_string_vehicle">Pojazd</string>
<string name="shared_string_api_key">Klucz API</string>
<string name="shared_string_server_url">Adres URL serwera</string>
<string name="shared_string_enter_param">Wpisz param</string>
<string name="keep_it_empty_if_not">Jeśli nie, zostaw to puste</string>
<string name="online_routing_example_hint">Adres URL ze wszystkimi parametrami będzie wyglądał następująco:</string>
<string name="test_route_calculation">Obliczanie trasy testowej</string>
<string name="routing_engine_vehicle_type_bike">Rower</string>
<string name="routing_engine_vehicle_type_car">Samochód</string>
<string name="message_error_recheck_parameters">Błąd, ponownie sprawdź parametry</string>
<string name="copy_address">Skopiuj adres</string>
</resources>

View file

@ -4038,4 +4038,7 @@
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
<string name="routing_engine_vehicle_type_car">Carro</string>
<string name="message_error_recheck_parameters">Erro, verifique novamente os parâmetros</string>
<string name="copy_address">Copiar endereço</string>
<string name="online_routing_engine">Motor de encaminhamento online</string>
<string name="online_routing_engines">Mecanismos de roteamento online</string>
</resources>

View file

@ -3879,4 +3879,7 @@
<string name="poi_water_source_tap">Torneira</string>
<string name="poi_water_source_water_works">Estação de tratamento de água</string>
<string name="poi_ranger_station">Posto de guarda florestal</string>
<string name="poi_wildlife_crossing_bat_tunnel">Túnel de morcegos</string>
<string name="poi_wildlife_crossing_bat_bridge">Ponte de morcegos</string>
<string name="poi_swimming_area">Área de natação</string>
</resources>

View file

@ -618,7 +618,7 @@
<string name="map_online_data_descr">Imprea sas mapas in lìnia (iscàrriga e archìvia sos tasseddos in sischeda de memòria).</string>
<string name="shared_string_online_maps">Mapas in lìnia</string>
<string name="online_map_settings_descr">Ischerta sas mitzas de sas mapas in lìnia o de sos tasseddos in cache.</string>
<string name="osmand_accessibility_description">Permitit de impreare sas funtzionalidades pro s\'atzessibilidade de su dispositivu ditetamente in OsmAnd, e fatzilitat, pro nàrrere, sa modìfica de sa lestresa de sas boghes de sìntesi vocale, sa cunfiguratzione de su movimentu de s\'ischermu, simpreu de una trackball pro s\'ismanniamentu o de uninterfàtzia vocale pro cosas che s\'annùntziu de sa positzione tua.</string>
<string name="osmand_accessibility_description">Permitit de impreare sas funtzionalidades pro s\'atzessibilidade de su dispositivu diretamente in OsmAnd, e fatzìlitat, pro nàrrere, sa modìfica de sa lestresa de sas boghes de sìntesi vocale, sa cunfiguratzione de su movimentu de s\'ischermu, simpreu de una trackball pro s\'ismanniamentu o de uninterfache vocale pro cosas che s\'annùntziu de sa positzione tua.</string>
<string name="plugins_screen">Estensiones</string>
<string name="prefs_plugins_descr">Sas estensiones abìlitant funtzionalidades agiuntivas e impostatziones avantzadas.</string>
<string name="prefs_plugins">Estensiones</string>
@ -909,7 +909,7 @@
<string name="search_osm_offline">Chirca impreende sa positzione geogràfica</string>
<string name="system_locale">Sistema</string>
<string name="preferred_locale_descr">Limba de interfache de s\'aplicatzione (impreada a pustis chi as a torrare a allùghere OsmAnd).</string>
<string name="preferred_locale">Limba interfàtzia</string>
<string name="preferred_locale">Limba de interfache</string>
<string name="incomplete_locale">non cumpridu</string>
<string name="shared_string_next">Imbeniente</string>
<string name="shared_string_previous">Antepostu</string>

View file

@ -4028,4 +4028,22 @@
<string name="routing_attr_allow_intermittent_description">Povoliť dočasné vodné toky</string>
<string name="routing_attr_allow_intermittent_name">Povoliť dočasné vodné toky</string>
<string name="voice_prompts_timetable">Časy hlasových pokynov</string>
<string name="add_online_routing_engine">Pridať online navigačnú službu</string>
<string name="edit_online_routing_engine">Upraviť online navigačnú službu</string>
<string name="shared_string_subtype">Podtyp</string>
<string name="shared_string_vehicle">Vozidlo</string>
<string name="shared_string_api_key">Kľúč API</string>
<string name="shared_string_server_url">Adresa URL serveru</string>
<string name="shared_string_enter_param">Zadajte parameter</string>
<string name="keep_it_empty_if_not">Ak nie, ponechajte prázdne</string>
<string name="online_routing_example_hint">Adresa URL so všetkými parametrami bude vyzerať nasledovne:</string>
<string name="test_route_calculation">Vyskúšať výpočet trasy</string>
<string name="routing_engine_vehicle_type_driving">Vedenie vozidla</string>
<string name="routing_engine_vehicle_type_foot">Chôdza</string>
<string name="routing_engine_vehicle_type_bike">Bicykel</string>
<string name="routing_engine_vehicle_type_car">Auto</string>
<string name="message_error_recheck_parameters">Chyba, skontrolujte parametre</string>
<string name="copy_address">Kopírovať adresu</string>
<string name="online_routing_engine">Online navigačná služba</string>
<string name="online_routing_engines">Online navigačné služby</string>
</resources>

View file

@ -3998,4 +3998,7 @@
<string name="routing_engine_vehicle_type_bike">Bisiklet</string>
<string name="routing_engine_vehicle_type_car">Araba</string>
<string name="message_error_recheck_parameters">Hata, parametreleri tekrar gözden geçirin</string>
<string name="copy_address">Adresi kopyala</string>
<string name="online_routing_engine">Çevrim içi yönlendirme motoru</string>
<string name="online_routing_engines">Çevrim içi yönlendirme motorları</string>
</resources>

View file

@ -4031,7 +4031,7 @@
<string name="shared_string_api_key">Ключ API</string>
<string name="shared_string_server_url">URL-адреса сервера</string>
<string name="shared_string_enter_param">Введіть параметр</string>
<string name="keep_it_empty_if_not">Залиште порожнім, якщо ні</string>
<string name="keep_it_empty_if_not">Залиште порожнім, якщо не маєте ключа API</string>
<string name="online_routing_example_hint">URL-адреса з усіма параметрами виглядатиме так:</string>
<string name="test_route_calculation">Тестове обчислення маршруту</string>
<string name="routing_engine_vehicle_type_driving">Водіння</string>
@ -4039,4 +4039,7 @@
<string name="routing_engine_vehicle_type_bike">Велосипед</string>
<string name="routing_engine_vehicle_type_car">Автомобіль</string>
<string name="message_error_recheck_parameters">Помилка, повторно перевірте параметри</string>
<string name="copy_address">Копіювати адресу</string>
<string name="online_routing_engine">Мережний рушій маршрутизації</string>
<string name="online_routing_engines">Мережні рушії маршрутизації</string>
</resources>

View file

@ -4023,4 +4023,22 @@
<string name="routing_attr_allow_intermittent_description">允許間歇水路</string>
<string name="routing_attr_allow_intermittent_name">允許間歇水路</string>
<string name="voice_prompts_timetable">語音提示時間</string>
<string name="add_online_routing_engine">新增線上路線引擎</string>
<string name="edit_online_routing_engine">編輯線上路線引擎</string>
<string name="shared_string_subtype">子類型</string>
<string name="shared_string_vehicle">車輛</string>
<string name="shared_string_api_key">API 金鑰</string>
<string name="shared_string_server_url">伺服器 URL</string>
<string name="shared_string_enter_param">輸入參數</string>
<string name="keep_it_empty_if_not">否則請保持空白</string>
<string name="online_routing_example_hint">帶有所有參數的 URL 如下所示:</string>
<string name="test_route_calculation">測試路線計算</string>
<string name="routing_engine_vehicle_type_driving">駕駛</string>
<string name="routing_engine_vehicle_type_foot">步行</string>
<string name="routing_engine_vehicle_type_bike">自行車</string>
<string name="routing_engine_vehicle_type_car">汽車</string>
<string name="message_error_recheck_parameters">錯誤,重新檢查參數</string>
<string name="copy_address">複製地址</string>
<string name="online_routing_engine">線上路線計算引擎</string>
<string name="online_routing_engines">線上路線計算引擎</string>
</resources>

View file

@ -11,6 +11,10 @@
Thx - Hardy
-->
<string name="online_routing_engines">Online routing engines</string>
<string name="online_routing_engine">Online routing engine</string>
<string name="copy_address">Copy address</string>
<string name="message_error_recheck_parameters">Error, recheck parameters</string>
<string name="routing_engine_vehicle_type_car">Car</string>
<string name="routing_engine_vehicle_type_bike">Bike</string>
@ -4026,5 +4030,4 @@
<string name="routing_attr_freeride_policy_description">\'Freeride\' and \'Off-piste\' are unofficial routes and passages. Typically ungroomed, unmaintained and not checked in the evening. Enter at your own risk.</string>
<string name="voice_prompts_timetable">Voice prompts times</string>
</resources>

View file

@ -23,12 +23,13 @@ import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import net.osmand.plus.widgets.WebViewEx;
/**
* WebView that its scroll position can be observed.
*/
public class ObservableWebView extends WebView implements Scrollable {
public class ObservableWebView extends WebViewEx implements Scrollable {
// Fields that should be saved onSaveInstanceState
private int mPrevScrollY;

View file

@ -673,15 +673,15 @@ public class OsmAndLocationProvider implements SensorEventListener {
private void stopLocationRequests() {
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
if(gpsStatusListener != null) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (gpsStatusListener != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
service.unregisterGnssStatusCallback((GnssStatus.Callback) gpsStatusListener);
} else {
service.removeGpsStatusListener((Listener) gpsStatusListener);
}
}
service.removeUpdates(gpsListener);
while(!networkListeners.isEmpty()) {
while (!networkListeners.isEmpty()) {
service.removeUpdates(networkListeners.poll());
}
}
@ -812,8 +812,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
setLocation(location);
}
private void setLocation(net.osmand.Location location) {
if (location == null) {
private void setLocation(net.osmand.Location location) { if (location == null) {
updateGPSInfo(null);
}

View file

@ -3,7 +3,6 @@
*/
package net.osmand.plus.activities;
import android.view.Window;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import android.annotation.SuppressLint;

View file

@ -29,20 +29,29 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.*;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.FontCache;
@ -51,6 +60,7 @@ import net.osmand.plus.mapcontextmenu.builders.cards.CardsRowBuilder;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask;
import net.osmand.plus.mapcontextmenu.builders.cards.NoImagesCard;
import net.osmand.plus.mapcontextmenu.controllers.AmenityMenuController;
import net.osmand.plus.mapcontextmenu.controllers.TransportStopController;
import net.osmand.plus.openplacereviews.AddPhotosBottomSheetDialogFragment;
import net.osmand.plus.openplacereviews.OPRConstants;
@ -65,6 +75,7 @@ import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.widgets.tools.ClickableSpanTouchListener;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
@ -72,7 +83,13 @@ import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
@ -91,13 +108,15 @@ public class MenuBuilder {
private boolean firstRow;
protected boolean matchWidthDivider;
protected boolean light;
private long objectId;
private Amenity amenity;
private LatLon latLon;
private boolean hidden;
private boolean showTitleIfTruncated = true;
private boolean showNearestWiki = false;
private boolean showNearestPoi = false;
private boolean showOnlinePhotos = true;
protected List<Amenity> nearestWiki = new ArrayList<>();
protected List<Amenity> nearestPoi = new ArrayList<>();
private List<OsmandPlugin> menuPlugins = new ArrayList<>();
@Nullable
private CardsRowBuilder onlinePhotoCardsRow;
@ -208,10 +227,18 @@ public class MenuBuilder {
return showNearestWiki;
}
public boolean isShowNearestPoi() {
return showNearestPoi;
}
public void setShowNearestWiki(boolean showNearestWiki) {
this.showNearestWiki = showNearestWiki;
}
public void setShowNearestPoi(boolean showNearestPoi) {
this.showNearestPoi = showNearestPoi;
}
public void setShowTitleIfTruncated(boolean showTitleIfTruncated) {
this.showTitleIfTruncated = showTitleIfTruncated;
}
@ -224,9 +251,8 @@ public class MenuBuilder {
this.showOnlinePhotos = showOnlinePhotos;
}
public void setShowNearestWiki(boolean showNearestWiki, long objectId) {
this.objectId = objectId;
this.showNearestWiki = showNearestWiki;
public void setAmenity(Amenity amenity) {
this.amenity = amenity;
}
public void addMenuPlugin(OsmandPlugin plugin) {
@ -246,6 +272,7 @@ public class MenuBuilder {
buildTitleRow(view);
}
buildNearestWikiRow(view);
buildNearestPoiRow(view);
if (needBuildPlainMenuItems()) {
buildPlainMenuItems(view);
}
@ -325,10 +352,20 @@ public class MenuBuilder {
}
protected void buildNearestWikiRow(View view) {
if (processNearestWiki() && nearestWiki.size() > 0) {
buildRow(view, R.drawable.ic_action_wikipedia, null, app.getString(R.string.wiki_around) + " (" + nearestWiki.size() + ")", 0,
true, getCollapsableWikiView(view.getContext(), true),
false, 0, false, null, false);
buildNearestRow(view, nearestWiki, processNearestWiki(),
R.drawable.ic_action_wikipedia, app.getString(R.string.wiki_around));
}
protected void buildNearestPoiRow(View view) {
buildNearestRow(view, nearestPoi, processNearestPoi(),
nearestPoi.isEmpty() ? 0 : AmenityMenuController.getRightIconId(nearestPoi.get(0)),
app.getString(R.string.speak_poi));
}
protected void buildNearestRow(View view, List<Amenity> nearestAmenities, boolean process, int iconId, String text) {
if (process && nearestAmenities.size() > 0) {
buildRow(view, iconId, null, text + " (" + nearestAmenities.size() + ")", 0, true,
getCollapsableView(view.getContext(), true, nearestAmenities), false, 0, false, null, false);
}
}
@ -1118,20 +1155,23 @@ public class MenuBuilder {
return new CollapsableView(textView, this, collapsed);
}
protected CollapsableView getCollapsableWikiView(Context context, boolean collapsed) {
protected CollapsableView getCollapsableView(Context context, boolean collapsed, List<Amenity> nearestAmenities) {
LinearLayout view = (LinearLayout) buildCollapsableContentView(context, collapsed, true);
for (final Amenity wiki : nearestWiki) {
for (final Amenity poi : nearestAmenities) {
TextViewEx button = buildButtonInCollapsableView(context, false, false);
String name = wiki.getName(preferredMapAppLang, transliterateNames);
String name = poi.getName(preferredMapAppLang, transliterateNames);
if (Algorithms.isBlank(name)) {
name = AmenityMenuController.getTypeStr(poi);
}
button.setText(name);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LatLon latLon = new LatLon(wiki.getLocation().getLatitude(), wiki.getLocation().getLongitude());
PointDescription pointDescription = mapActivity.getMapLayers().getPoiMapLayer().getObjectName(wiki);
mapActivity.getContextMenu().show(latLon, pointDescription, wiki);
LatLon latLon = new LatLon(poi.getLocation().getLatitude(), poi.getLocation().getLongitude());
PointDescription pointDescription = mapActivity.getMapLayers().getPoiMapLayer().getObjectName(poi);
mapActivity.getContextMenu().show(latLon, pointDescription, poi);
}
});
view.addView(button);
@ -1191,35 +1231,48 @@ public class MenuBuilder {
}
protected boolean processNearestWiki() {
if (showNearestWiki && latLon != null) {
QuadRect rect = MapUtils.calculateLatLonBbox(
latLon.getLatitude(), latLon.getLongitude(), 250);
PoiUIFilter wikiPoiFilter = app.getPoiFilters().getTopWikiPoiFilter();
nearestWiki = getAmenities(rect, wikiPoiFilter);
Collections.sort(nearestWiki, new Comparator<Amenity>() {
@Override
public int compare(Amenity o1, Amenity o2) {
double d1 = MapUtils.getDistance(latLon, o1.getLocation());
double d2 = MapUtils.getDistance(latLon, o2.getLocation());
return Double.compare(d1, d2);
}
});
Long id = objectId;
List<Amenity> wikiList = new ArrayList<>();
for (Amenity wiki : nearestWiki) {
if (wiki.getId().equals(id)) {
wikiList.add(wiki);
}
if (showNearestWiki && latLon != null && amenity != null) {
PoiUIFilter filter = app.getPoiFilters().getTopWikiPoiFilter();
if (filter != null) {
nearestWiki = getSortedAmenities(filter, latLon);
return true;
}
nearestWiki.removeAll(wikiList);
return true;
}
return false;
}
protected boolean processNearestPoi() {
if (showNearestPoi && latLon != null && amenity != null) {
PoiCategory pc = amenity.getType();
PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType());
PoiUIFilter filter = app.getPoiFilters().getFilterById(PoiUIFilter.STD_PREFIX + pt.getKeyName());
if (filter != null) {
nearestPoi = getSortedAmenities(filter, latLon);
return true;
}
}
return false;
}
private List<Amenity> getSortedAmenities(PoiUIFilter filter, final LatLon latLon) {
QuadRect rect = MapUtils.calculateLatLonBbox(latLon.getLatitude(), latLon.getLongitude(), 250);
List<Amenity> nearestAmenities = getAmenities(rect, filter);
nearestAmenities.remove(amenity);
Collections.sort(nearestAmenities, new Comparator<Amenity>() {
@Override
public int compare(Amenity o1, Amenity o2) {
double d1 = MapUtils.getDistance(latLon, o1.getLocation());
double d2 = MapUtils.getDistance(latLon, o2.getLocation());
return Double.compare(d1, d2);
}
});
return nearestAmenities;
}
private List<Amenity> getAmenities(QuadRect rect, PoiUIFilter wikiPoiFilter) {
return wikiPoiFilter.searchAmenities(rect.top, rect.left,
rect.bottom, rect.right, -1, null);

View file

@ -35,6 +35,7 @@ import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.mapcontextmenu.CollapsableView;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.controllers.AmenityMenuController;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.views.layers.POIMapLayer;
@ -78,7 +79,9 @@ public class AmenityMenuBuilder extends MenuBuilder {
public AmenityMenuBuilder(@NonNull MapActivity mapActivity, final @NonNull Amenity amenity) {
super(mapActivity);
this.amenity = amenity;
setShowNearestWiki(true, amenity.getId());
setAmenity(amenity);
setShowNearestWiki(true);
setShowNearestPoi(!amenity.getType().isWiki());
metricSystem = mapActivity.getMyApplication().getSettings().METRIC_SYSTEM.get();
}
@ -86,6 +89,10 @@ public class AmenityMenuBuilder extends MenuBuilder {
protected void buildNearestWikiRow(View view) {
}
@Override
protected void buildNearestPoiRow(View view) {
}
private void buildRow(View view, int iconId, String text, String textPrefix,
boolean collapsable, final CollapsableView collapsableView,
int textColor, boolean isWiki, boolean isText, boolean needLinks,
@ -664,11 +671,19 @@ public class AmenityMenuBuilder extends MenuBuilder {
if (processNearestWiki() && nearestWiki.size() > 0) {
AmenityInfoRow wikiInfo = new AmenityInfoRow(
"nearest_wiki", R.drawable.ic_plugin_wikipedia, null, app.getString(R.string.wiki_around) + " (" + nearestWiki.size() + ")", true,
getCollapsableWikiView(view.getContext(), true),
getCollapsableView(view.getContext(), true, nearestWiki),
0, false, false, false, 1000, null, false, false, false, 0);
buildAmenityRow(view, wikiInfo);
}
if (processNearestPoi() && nearestPoi.size() > 0) {
AmenityInfoRow poiInfo = new AmenityInfoRow(
"nearest_poi", AmenityMenuController.getRightIconId(amenity), null, app.getString(R.string.speak_poi) + " (" + nearestPoi.size() + ")", true,
getCollapsableView(view.getContext(), true, nearestPoi),
0, false, false, false, 1000, null, false, false, false, 0);
buildAmenityRow(view, poiInfo);
}
if (osmEditingEnabled && amenity.getId() != null
&& amenity.getId() > 0 &&
(amenity.getId() % 2 == 0 || (amenity.getId() >> 1) < Integer.MAX_VALUE)) {

View file

@ -59,9 +59,9 @@ public class FavouritePointMenuBuilder extends MenuBuilder {
}
@Override
protected void buildNearestWikiRow(View view) {
protected void buildNearestRow(View view, List<Amenity> nearestAmenities, boolean process, int iconId, String text) {
if (originObject == null || !(originObject instanceof Amenity)) {
super.buildNearestWikiRow(view);
super.buildNearestRow(view, nearestAmenities, process, iconId, text);
}
}

View file

@ -1,6 +1,7 @@
package net.osmand.plus.mapcontextmenu.builders.cards;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
@ -23,6 +24,7 @@ import androidx.core.content.ContextCompat;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.widgets.WebViewEx;
public abstract class AbstractCard {
@ -55,7 +57,7 @@ public abstract class AbstractCard {
@SuppressLint("SetJavaScriptEnabled")
@SuppressWarnings("deprecation")
protected static void openUrl(@NonNull Context ctx,
protected static void openUrl(@NonNull Activity ctx,
@NonNull OsmandApplication app,
@Nullable String title,
@NonNull String url,
@ -90,7 +92,7 @@ public abstract class AbstractCard {
}
});
final WebView wv = new WebView(ctx);
final WebView wv = new WebViewEx(ctx);
wv.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {

View file

@ -116,7 +116,7 @@ public class AmenityMenuController extends MenuController {
return getRightIconId(amenity);
}
private static int getRightIconId(Amenity amenity) {
public static int getRightIconId(Amenity amenity) {
String id = null;
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) {

View file

@ -36,6 +36,7 @@ public class ShareMenu extends BaseMenuController {
public enum ShareItem {
MESSAGE(R.drawable.ic_action_message, R.string.shared_string_send),
CLIPBOARD(R.drawable.ic_action_copy, R.string.shared_string_copy),
ADDRESS(R.drawable.ic_action_copy, R.string.copy_address),
NAME(R.drawable.ic_action_copy, R.string.copy_location_name),
COORDINATES(R.drawable.ic_action_copy, R.string.copy_coordinates),
GEO(R.drawable.ic_world_globe_dark, R.string.share_geo),
@ -66,6 +67,7 @@ public class ShareMenu extends BaseMenuController {
List<ShareItem> list = new LinkedList<>();
list.add(ShareItem.MESSAGE);
list.add(ShareItem.CLIPBOARD);
list.add(ShareItem.ADDRESS);
list.add(ShareItem.NAME);
list.add(ShareItem.COORDINATES);
list.add(ShareItem.GEO);
@ -121,6 +123,15 @@ public class ShareMenu extends BaseMenuController {
case CLIPBOARD:
ShareDialog.sendToClipboard(mapActivity, sms);
break;
case ADDRESS:
if (!Algorithms.isEmpty(address)) {
ShareDialog.sendToClipboard(mapActivity, address);
} else {
Toast.makeText(mapActivity,
R.string.no_address_found,
Toast.LENGTH_LONG).show();
}
break;
case NAME:
if (!Algorithms.isEmpty(title)) {
ShareDialog.sendToClipboard(mapActivity, title);

View file

@ -19,6 +19,7 @@ import com.google.android.material.appbar.AppBarLayout;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.widgets.WebViewEx;
public class GpxDescriptionDialogFragment extends BaseOsmAndDialogFragment {
@ -48,7 +49,7 @@ public class GpxDescriptionDialogFragment extends BaseOsmAndDialogFragment {
AppBarLayout appBar = new AppBarLayout(ctx);
appBar.addView(topBar);
WebView webView = new WebView(ctx);
WebView webView = new WebViewEx(ctx);
webView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
webView.getSettings().setTextZoom((int) (getResources().getConfiguration().fontScale * 100f));
Bundle args = getArguments();

View file

@ -3,6 +3,7 @@ package net.osmand.plus.onlinerouting;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.data.LatLon;
import net.osmand.plus.R;
@ -33,9 +34,11 @@ public class OnlineRoutingEngine {
public OnlineRoutingEngine(@NonNull String stringKey,
@NonNull EngineType type,
@NonNull String vehicleKey,
Map<String, String> params) {
@Nullable Map<String, String> params) {
this(stringKey, type, vehicleKey);
this.params = params;
if (!Algorithms.isEmpty(params)) {
this.params.putAll(params);
}
}
public OnlineRoutingEngine(@NonNull String stringKey,
@ -109,8 +112,9 @@ public class OnlineRoutingEngine {
}
public static OnlineRoutingEngine createNewEngine(@NonNull EngineType type,
@NonNull String vehicleKey) {
return new OnlineRoutingEngine(generateKey(), type, vehicleKey);
@NonNull String vehicleKey,
@Nullable Map<String, String> params) {
return new OnlineRoutingEngine(generateKey(), type, vehicleKey, params);
}
public static OnlineRoutingEngine createTmpEngine(@NonNull EngineType type,

View file

@ -412,7 +412,7 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
if (isEditingMode()) {
engineToSave = new OnlineRoutingEngine(editedEngineKey, engine.type, engine.getVehicleKey());
} else {
engineToSave = OnlineRoutingEngine.createNewEngine(engine.type, engine.getVehicleKey());
engineToSave = OnlineRoutingEngine.createNewEngine(engine.type, engine.getVehicleKey(), null);
}
engineToSave.putParameter(EngineParameter.CUSTOM_NAME, engine.customName);

View file

@ -114,7 +114,7 @@ public class OnlineRoutingHelper {
JSONObject json = new JSONObject(jsonString);
readFromJson(json, engines);
} catch (JSONException e) {
LOG.debug("Error when create a new JSONObject: " + e.toString());
LOG.debug("Error when reading engines from JSON ", e);
}
}
return engines;
@ -122,57 +122,50 @@ public class OnlineRoutingHelper {
private void saveToSettings() {
if (!Algorithms.isEmpty(cachedEngines)) {
JSONObject json = new JSONObject();
if (writeToJson(json, getEngines())) {
try {
JSONObject json = new JSONObject();
writeToJson(json, getEngines());
settings.ONLINE_ROUTING_ENGINES.set(json.toString());
} catch (JSONException e) {
LOG.debug("Error when writing engines to JSON ", e);
}
} else {
settings.ONLINE_ROUTING_ENGINES.set(null);
}
}
private static void readFromJson(JSONObject json, List<OnlineRoutingEngine> engines) {
try {
if (!json.has("items")) {
return;
}
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
JSONArray itemsJson = json.getJSONArray("items");
for (int i = 0; i < itemsJson.length(); i++) {
JSONObject object = itemsJson.getJSONObject(i);
String key = object.getString("key");
String vehicleKey = object.getString("vehicle");
EngineType engineType = EngineType.valueOf(object.getString("type"));
String paramsString = object.getString("params");
HashMap<String, String> params = gson.fromJson(paramsString, type);
engines.add(new OnlineRoutingEngine(key, engineType, vehicleKey, params));
}
} catch (JSONException e) {
LOG.debug("Error when reading engines from JSON: " + e.toString());
public static void readFromJson(JSONObject json, List<OnlineRoutingEngine> engines) throws JSONException {
if (!json.has("items")) {
return;
}
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
JSONArray itemsJson = json.getJSONArray("items");
for (int i = 0; i < itemsJson.length(); i++) {
JSONObject object = itemsJson.getJSONObject(i);
String key = object.getString("key");
String vehicleKey = object.getString("vehicle");
EngineType engineType = EngineType.valueOf(object.getString("type"));
String paramsString = object.getString("params");
HashMap<String, String> params = gson.fromJson(paramsString, type);
engines.add(new OnlineRoutingEngine(key, engineType, vehicleKey, params));
}
}
private static boolean writeToJson(JSONObject json, List<OnlineRoutingEngine> engines) {
public static void writeToJson(JSONObject json, List<OnlineRoutingEngine> engines) throws JSONException {
JSONArray jsonArray = new JSONArray();
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
try {
for (OnlineRoutingEngine engine : engines) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", engine.getStringKey());
jsonObject.put("type", engine.getType().getStringKey());
jsonObject.put("vehicle", engine.getVehicleKey());
jsonObject.put("params", gson.toJson(engine.getParams(), type));
jsonArray.put(jsonObject);
}
json.put("items", jsonArray);
return true;
} catch (JSONException e) {
LOG.debug("Error when writing engines to JSON: " + e.toString());
return false;
for (OnlineRoutingEngine engine : engines) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", engine.getStringKey());
jsonObject.put("type", engine.getType().getStringKey());
jsonObject.put("vehicle", engine.getVehicleKey());
jsonObject.put("params", gson.toJson(engine.getParams(), type));
jsonArray.put(jsonObject);
}
json.put("items", jsonArray);
}
}

View file

@ -138,7 +138,11 @@ public class OsmOAuthAuthorizationAdapter {
@Override
protected void onPostExecute(@NonNull OAuth1RequestToken requestToken) {
loadWebView(rootLayout, nightMode, client.getService().getAuthorizationUrl(requestToken));
if (requestToken != null) {
loadWebView(rootLayout, nightMode, client.getService().getAuthorizationUrl(requestToken));
} else {
app.showShortToastMessage(app.getString(R.string.internet_not_available));
}
}
}

View file

@ -45,7 +45,11 @@ public class OsmOAuthHelper {
}
public void authorize(@NonNull String oauthVerifier) {
authorizationAdapter.authorize(oauthVerifier, this);
if (oauthVerifier != null) {
authorizationAdapter.authorize(oauthVerifier, this);
} else {
updateAdapter();
}
}
public void resetAuthorization() {

View file

@ -73,7 +73,7 @@ public class AnnounceTimeDistances {
// Do not play prepare: for pedestrian and slow transport
// same check as speed < 150/(90-22) m/s = 2.2 m/s = 8 km/h
// if (DEFAULT_SPEED < 2.3) {
// if (DEFAULT_SPEED < 2.3) {
if (PREPARE_DISTANCE_END - TURN_IN_DISTANCE < 150) {
PREPARE_DISTANCE_END = PREPARE_DISTANCE * 2;
}

View file

@ -24,7 +24,8 @@ public enum ExportSettingsType {
MAP_SOURCES(R.string.quick_action_map_source_title, R.drawable.ic_map),
OFFLINE_MAPS(R.string.shared_string_maps, R.drawable.ic_map),
TTS_VOICE(R.string.local_indexes_cat_tts, R.drawable.ic_action_volume_up),
VOICE(R.string.local_indexes_cat_voice, R.drawable.ic_action_volume_up);
VOICE(R.string.local_indexes_cat_voice, R.drawable.ic_action_volume_up),
ONLINE_ROUTING_ENGINES(R.string.online_routing_engines, R.drawable.ic_world_globe_dark);
@StringRes
private final int titleId;
@ -59,6 +60,6 @@ public enum ExportSettingsType {
public boolean isResourcesCategory() {
return this == CUSTOM_RENDER_STYLE || this == CUSTOM_ROUTING || this == MAP_SOURCES
|| this == OFFLINE_MAPS || this == VOICE || this == TTS_VOICE;
|| this == OFFLINE_MAPS || this == VOICE || this == TTS_VOICE || this == ONLINE_ROUTING_ENGINES;
}
}

View file

@ -1015,7 +1015,7 @@ public class OsmandSettings {
ROUTE_SERVICE.setModeDefaultValue(ApplicationMode.AIRCRAFT, RouteService.STRAIGHT);
}
public final CommonPreference<String> ONLINE_ROUTING_ENGINES = new StringPreference(this, "online_routing_engines", null);
public final CommonPreference<String> ONLINE_ROUTING_ENGINES = new StringPreference(this, "online_routing_engines", null).makeGlobal();
public final CommonPreference<NavigationIcon> NAVIGATION_ICON = new EnumStringPreference<>(this, "navigation_icon", NavigationIcon.DEFAULT, NavigationIcon.values()).makeProfile().cache();

View file

@ -92,11 +92,6 @@ public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidRoadInfo
return false;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@Override
public boolean shouldShowDuplicates() {
return false;

View file

@ -72,6 +72,11 @@ public abstract class CollectionSettingsItem<T> extends SettingsItem {
return true;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
public abstract boolean isDuplicate(@NonNull T item);
@NonNull

View file

@ -109,11 +109,6 @@ public class FavoritesSettingsItem extends CollectionSettingsItem<FavoriteGroup>
return false;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public FavoriteGroup renameItem(@NonNull FavoriteGroup item) {

View file

@ -103,11 +103,6 @@ public class HistoryMarkersSettingsItem extends CollectionSettingsItem<MapMarker
return false;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public MapMarker renameItem(@NonNull MapMarker item) {

View file

@ -130,11 +130,6 @@ public class MapSourcesSettingsItem extends CollectionSettingsItem<ITileSource>
return "map_sources";
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@Override
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
try {

View file

@ -103,11 +103,6 @@ public class MarkersSettingsItem extends CollectionSettingsItem<MapMarker> {
return false;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public MapMarker renameItem(@NonNull MapMarker item) {

View file

@ -0,0 +1,137 @@
package net.osmand.plus.settings.backend.backup;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameterType;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class OnlineRoutingSettingsItem extends CollectionSettingsItem<OnlineRoutingEngine> {
private OnlineRoutingHelper onlineRoutingHelper;
public OnlineRoutingSettingsItem(@NonNull OsmandApplication app, @NonNull List<OnlineRoutingEngine> items) {
super(app, null, items);
}
public OnlineRoutingSettingsItem(@NonNull OsmandApplication app, @Nullable OnlineRoutingSettingsItem baseItem, @NonNull List<OnlineRoutingEngine> items) {
super(app, baseItem, items);
}
public OnlineRoutingSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
super(app, json);
}
@Override
protected void init() {
super.init();
onlineRoutingHelper = app.getOnlineRoutingHelper();
existingItems = new ArrayList<>(onlineRoutingHelper.getEngines());
}
@NonNull
@Override
public SettingsItemType getType() {
return SettingsItemType.ONLINE_ROUTING_ENGINES;
}
@NonNull
@Override
public String getName() {
return "online_routing_engines";
}
@NonNull
@Override
public String getPublicName(@NonNull Context ctx) {
return ctx.getString(R.string.online_routing_engine);
}
@Override
public void apply() {
List<OnlineRoutingEngine> newItems = getNewItems();
if (!newItems.isEmpty() || !duplicateItems.isEmpty()) {
appliedItems = new ArrayList<>(newItems);
for (OnlineRoutingEngine duplicate : duplicateItems) {
if (shouldReplace) {
onlineRoutingHelper.deleteEngine(duplicate.getStringKey());
}
appliedItems.add(shouldReplace ? duplicate : renameItem(duplicate));
}
for (OnlineRoutingEngine engine : appliedItems) {
onlineRoutingHelper.saveEngine(engine);
}
}
}
@Override
public boolean isDuplicate(@NonNull OnlineRoutingEngine routingEngine) {
for (OnlineRoutingEngine engine : existingItems) {
if (engine.getStringKey().equals(routingEngine.getStringKey())
|| engine.getName(app).equals(routingEngine.getName(app))) {
return true;
}
}
return false;
}
@NonNull
@Override
public OnlineRoutingEngine renameItem(@NonNull OnlineRoutingEngine item) {
int number = 0;
while (true) {
number++;
OnlineRoutingEngine renamedItem = OnlineRoutingEngine.createNewEngine(item.getServerType(), item.getVehicleKey(), item.getParams());
renamedItem.putParameter(EngineParameterType.CUSTOM_NAME, renamedItem.getName(app) + "_" + number);
if (!isDuplicate(renamedItem)) {
return renamedItem;
}
}
}
@Override
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
try {
OnlineRoutingHelper.readFromJson(json, items);
} catch (JSONException e) {
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
throw new IllegalArgumentException("Json parse error", e);
}
}
@Override
void writeItemsToJson(@NonNull JSONObject json) {
if (!items.isEmpty()) {
try {
OnlineRoutingHelper.writeToJson(json, items);
} catch (JSONException e) {
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
SettingsHelper.LOG.error("Failed write to json", e);
}
}
}
@Nullable
@Override
SettingsItemReader<? extends SettingsItem> getReader() {
return getJsonReader();
}
@Nullable
@Override
SettingsItemWriter<? extends SettingsItem> getWriter() {
return getJsonWriter();
}
}

View file

@ -113,11 +113,6 @@ public class OsmEditsSettingsItem extends CollectionSettingsItem<OpenstreetmapPo
return ctx.getString(R.string.osm_edits);
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@Override
public boolean shouldShowDuplicates() {
return false;

View file

@ -106,11 +106,6 @@ public class OsmNotesSettingsItem extends CollectionSettingsItem<OsmNotesPoint>
return ctx.getString(R.string.osm_notes);
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@Override
public boolean shouldShowDuplicates() {
return false;

View file

@ -105,11 +105,6 @@ public class PoiUiFiltersSettingsItem extends CollectionSettingsItem<PoiUIFilter
return "poi_ui_filters";
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@Override
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
try {

View file

@ -89,11 +89,6 @@ public class QuickActionsSettingsItem extends CollectionSettingsItem<QuickAction
}
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public String getName() {

View file

@ -148,11 +148,6 @@ public class SearchHistorySettingsItem extends CollectionSettingsItem<HistoryEnt
return false;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public HistoryEntry renameItem(@NonNull HistoryEntry item) {

View file

@ -33,6 +33,7 @@ import net.osmand.plus.helpers.SearchHistoryHelper;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.osmedit.OsmNotesPoint;
@ -624,6 +625,10 @@ public class SettingsHelper {
resourcesItems.put(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl));
}
}
List<OnlineRoutingEngine> onlineRoutingEngines = app.getOnlineRoutingHelper().getEngines();
if (!Algorithms.isEmpty(onlineRoutingEngines)) {
resourcesItems.put(ExportSettingsType.ONLINE_ROUTING_ENGINES, onlineRoutingEngines);
}
List<ITileSource> iTileSources = new ArrayList<>();
Set<String> tileSourceNames = app.getSettings().getTileSourceEntries(true).keySet();
for (String name : tileSourceNames) {
@ -701,6 +706,7 @@ public class SettingsHelper {
List<MapMarkersGroup> markersGroups = new ArrayList<>();
List<MapMarkersGroup> markersHistoryGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
List<OnlineRoutingEngine> onlineRoutingEngines = new ArrayList<>();
for (Object object : data) {
if (object instanceof QuickAction) {
@ -741,6 +747,8 @@ public class SettingsHelper {
historyEntries.add((HistoryEntry) object);
} else if (object instanceof GlobalSettingsItem) {
settingsItems.add((GlobalSettingsItem) object);
} else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object);
}
}
if (!quickActions.isEmpty()) {
@ -793,6 +801,9 @@ public class SettingsHelper {
if (!historyEntries.isEmpty()) {
settingsItems.add(new SearchHistorySettingsItem(app, historyEntries));
}
if (!onlineRoutingEngines.isEmpty()) {
settingsItems.add(new OnlineRoutingSettingsItem(app, onlineRoutingEngines));
}
return settingsItems;
}
@ -848,6 +859,7 @@ public class SettingsHelper {
List<MapMarkersGroup> markersGroups = new ArrayList<>();
List<MapMarkersGroup> markersHistoryGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
List<OnlineRoutingEngine> onlineRoutingEngines = new ArrayList<>();
for (SettingsItem item : settingsItems) {
switch (item.getType()) {
@ -942,6 +954,10 @@ public class SettingsHelper {
case GPX:
tracksFilesList.add((GpxSettingsItem) item);
break;
case ONLINE_ROUTING_ENGINES:
OnlineRoutingSettingsItem onlineRoutingSettingsItem = (OnlineRoutingSettingsItem) item;
onlineRoutingEngines.addAll(onlineRoutingSettingsItem.getItems());
break;
default:
break;
}
@ -1004,6 +1020,9 @@ public class SettingsHelper {
if (!historyEntries.isEmpty()) {
settingsToOperate.put(ExportSettingsType.SEARCH_HISTORY, historyEntries);
}
if (!onlineRoutingEngines.isEmpty()) {
settingsToOperate.put(ExportSettingsType.ONLINE_ROUTING_ENGINES, onlineRoutingEngines);
}
return settingsToOperate;
}

View file

@ -19,5 +19,6 @@ public enum SettingsItemType {
FAVOURITES,
ACTIVE_MARKERS,
HISTORY_MARKERS,
SEARCH_HISTORY
SEARCH_HISTORY,
ONLINE_ROUTING_ENGINES
}

View file

@ -146,6 +146,9 @@ class SettingsItemsFactory {
case GPX:
item = new GpxSettingsItem(app, json);
break;
case ONLINE_ROUTING_ENGINES:
item = new OnlineRoutingSettingsItem(app, json);
break;
}
return item;
}

View file

@ -23,6 +23,7 @@ import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.ProfileIconColors;
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
@ -163,6 +164,9 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter<RecyclerView
itemHolder.icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_flag, activeColorRes));
} else if (currentItem instanceof HistoryEntry) {
itemHolder.title.setText(((HistoryEntry) currentItem).getName().getName());
} else if (currentItem instanceof OnlineRoutingEngine) {
itemHolder.title.setText(((OnlineRoutingEngine) currentItem).getName(app));
itemHolder.icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_world_globe_dark, activeColorRes));
}
itemHolder.divider.setVisibility(shouldShowDivider(position) ? View.VISIBLE : View.GONE);
}

View file

@ -40,6 +40,7 @@ import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.osmedit.OsmNotesPoint;
@ -362,6 +363,10 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
HistoryEntry historyEntry = (HistoryEntry) object;
builder.setTitle(historyEntry.getName().getName());
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes));
} else if (object instanceof OnlineRoutingEngine) {
OnlineRoutingEngine onlineRoutingEngine = (OnlineRoutingEngine) object;
builder.setTitle(onlineRoutingEngine.getName(app));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_world_globe_dark, activeColorRes));
}
}

View file

@ -24,6 +24,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.dialogs.SelectMapStyleBottomSheetDialogFragment;
@ -36,6 +37,7 @@ import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.backend.backup.SettingsItem;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import java.util.List;
@ -150,12 +152,11 @@ public class ImportCompleteFragment extends BaseOsmAndFragment {
dismissFragment();
fm.popBackStack(DRAWER_SETTINGS_ID + ".new", FragmentManager.POP_BACK_STACK_INCLUSIVE);
switch (type) {
case CUSTOM_ROUTING:
case GLOBAL:
case PROFILE:
BaseSettingsFragment.showInstance(
requireActivity(),
BaseSettingsFragment.SettingsScreenType.MAIN_SETTINGS
);
case CUSTOM_ROUTING:
case ONLINE_ROUTING_ENGINES:
BaseSettingsFragment.showInstance(requireActivity(), SettingsScreenType.MAIN_SETTINGS);
break;
case QUICK_ACTIONS:
fm.beginTransaction()
@ -190,19 +191,13 @@ public class ImportCompleteFragment extends BaseOsmAndFragment {
case AVOID_ROADS:
new AvoidRoadsBottomSheetDialogFragment().show(fm, AvoidRoadsBottomSheetDialogFragment.TAG);
break;
case TRACKS:
case OSM_NOTES:
case OSM_EDITS:
OsmAndAppCustomization appCustomization = app.getAppCustomization();
final Intent favorites = new Intent(activity, appCustomization.getFavoritesActivity());
favorites.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
app.getSettings().FAVORITES_TAB.set(OsmEditingPlugin.OSM_EDIT_TAB);
startActivity(favorites);
break;
case FAVORITES:
Intent favoritesActivity = new Intent(activity, app.getAppCustomization().getFavoritesActivity());
favoritesActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
app.getSettings().FAVORITES_TAB.set(FavoritesActivity.FAV_TAB);
startActivity(favoritesActivity);
case MULTIMEDIA_NOTES:
int tabId = getFavoritesTabId(type);
openFavouritesActivity(activity, tabId);
break;
case SEARCH_HISTORY:
if (activity instanceof MapActivity) {
@ -221,6 +216,29 @@ public class ImportCompleteFragment extends BaseOsmAndFragment {
}
}
private void openFavouritesActivity(Activity activity, int tabType) {
OsmAndAppCustomization appCustomization = app.getAppCustomization();
Intent favoritesActivity = new Intent(activity, appCustomization.getFavoritesActivity());
favoritesActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
app.getSettings().FAVORITES_TAB.set(tabType);
startActivity(favoritesActivity);
}
private int getFavoritesTabId(ExportSettingsType type) {
switch (type) {
case OSM_NOTES:
case OSM_EDITS:
return OsmEditingPlugin.OSM_EDIT_TAB;
case MULTIMEDIA_NOTES:
return AudioVideoNotesPlugin.NOTES_TAB;
case TRACKS:
return FavoritesActivity.GPX_TAB;
case FAVORITES:
default:
return FavoritesActivity.FAV_TAB;
}
}
@Override
public int getStatusBarColorId() {
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;

View file

@ -34,6 +34,7 @@ import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmNotesPoint;
import net.osmand.plus.poi.PoiUIFilter;
@ -205,6 +206,7 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
List<MapMarker> mapMarkers = new ArrayList<>();
List<MapMarker> mapMarkersGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
List<OnlineRoutingEngine> onlineRoutingEngines = new ArrayList<>();
for (Object object : duplicatesList) {
if (object instanceof ApplicationMode.ApplicationModeBean) {
@ -250,6 +252,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
}
} else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object);
} else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object);
}
}
if (!profiles.isEmpty()) {
@ -320,6 +324,10 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment {
duplicates.add(getString(R.string.markers_history));
duplicates.addAll(mapMarkersGroups);
}
if (!onlineRoutingEngines.isEmpty()) {
duplicates.add(getString(R.string.online_routing_engines));
duplicates.addAll(onlineRoutingEngines);
}
return duplicates;
}

View file

@ -36,6 +36,7 @@ import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmNotesPoint;
import net.osmand.plus.poi.PoiUIFilter;
@ -50,6 +51,7 @@ import net.osmand.plus.settings.backend.backup.GpxSettingsItem;
import net.osmand.plus.settings.backend.backup.HistoryMarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
import net.osmand.plus.settings.backend.backup.MarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.OnlineRoutingSettingsItem;
import net.osmand.plus.settings.backend.backup.OsmEditsSettingsItem;
import net.osmand.plus.settings.backend.backup.OsmNotesSettingsItem;
import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem;
@ -347,6 +349,7 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
List<MapMarkersGroup> markersGroups = new ArrayList<>();
List<MapMarkersGroup> markersHistoryGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
List<OnlineRoutingEngine> onlineRoutingEngines = new ArrayList<>();
for (Object object : data) {
if (object instanceof ApplicationModeBean) {
appModeBeans.add((ApplicationModeBean) object);
@ -384,6 +387,8 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
}
} else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object);
} else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object);
}
}
if (!appModeBeans.isEmpty()) {
@ -435,6 +440,10 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
SearchHistorySettingsItem baseItem = getBaseItem(SettingsItemType.SEARCH_HISTORY, SearchHistorySettingsItem.class);
settingsItems.add(new SearchHistorySettingsItem(app, baseItem, historyEntries));
}
if (!onlineRoutingEngines.isEmpty()) {
OnlineRoutingSettingsItem baseItem = getBaseItem(SettingsItemType.ONLINE_ROUTING_ENGINES, OnlineRoutingSettingsItem.class);
settingsItems.add(new OnlineRoutingSettingsItem(app, baseItem, onlineRoutingEngines));
}
return settingsItems;
}

View file

@ -16,7 +16,6 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.ExportSettingsType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -33,7 +32,7 @@ public class ImportedSettingsItemsAdapter extends
private OnItemClickListener listener;
ImportedSettingsItemsAdapter(@NonNull OsmandApplication app, Map<ExportSettingsType, List<?>> itemsMap,
boolean nightMode, OnItemClickListener listener) {
boolean nightMode, OnItemClickListener listener) {
this.app = app;
this.itemsMap = itemsMap;
this.nightMode = nightMode;
@ -154,6 +153,10 @@ public class ImportedSettingsItemsAdapter extends
holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_history, activeColorRes));
holder.title.setText(R.string.shared_string_search_history);
break;
case ONLINE_ROUTING_ENGINES:
holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_world_globe_dark, activeColorRes));
holder.title.setText(R.string.online_routing_engines);
break;
}
}

View file

@ -0,0 +1,49 @@
package net.osmand.plus.widgets;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.AttributeSet;
import android.webkit.WebView;
import net.osmand.plus.OsmandApplication;
public class WebViewEx extends WebView {
public WebViewEx(Context context) {
super(context);
fixWebViewResetsLocaleToUserDefault(context);
}
public WebViewEx(Context context, AttributeSet attrs) {
super(context, attrs);
fixWebViewResetsLocaleToUserDefault(context);
}
public WebViewEx(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
fixWebViewResetsLocaleToUserDefault(context);
}
public WebViewEx(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
fixWebViewResetsLocaleToUserDefault(context);
}
public WebViewEx(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(context, attrs, defStyleAttr, privateBrowsing);
fixWebViewResetsLocaleToUserDefault(context);
}
public void fixWebViewResetsLocaleToUserDefault(Context ctx) {
// issue details: https://issuetracker.google.com/issues/37113860
// also see: https://gist.github.com/amake/0ac7724681ac1c178c6f95a5b09f03ce
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
OsmandApplication app = (OsmandApplication) ctx.getApplicationContext();
app.checkPreferredLocale();
ctx.getResources().updateConfiguration(
new Configuration(app.getResources().getConfiguration()),
ctx.getResources().getDisplayMetrics());
}
}
}

View file

@ -17,7 +17,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.TextView;
@ -28,7 +27,6 @@ import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;
import androidx.core.view.MotionEventCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

View file

@ -508,7 +508,7 @@ public class TravelLocalDataHelper {
BOOKMARKS_COL_ROUTE_ID + " = ?, " +
BOOKMARKS_COL_CONTENT_JSON + " = ?, " +
BOOKMARKS_COL_CONTENT + " = ?, " +
BOOKMARKS_COL_LAST_MODIFIED + " = ?, " +
BOOKMARKS_COL_LAST_MODIFIED + " = ? " +
"WHERE " + BOOKMARKS_COL_ARTICLE_TITLE + " = ? " +
" AND " + BOOKMARKS_COL_ROUTE_ID + " = ?" +
" AND " + BOOKMARKS_COL_LANG + " = ?" +

View file

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.Collator;
import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.IndexConstants;
@ -21,6 +22,7 @@ import net.osmand.data.QuadRect;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier;
import net.osmand.search.core.SearchPhrase.NameStringMatcher;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
@ -81,7 +83,7 @@ public class TravelObfHelper implements TravelHelper {
}
@NonNull
public List<TravelArticle> loadPopularArticles() {
public synchronized List<TravelArticle> loadPopularArticles() {
String lang = app.getLanguage();
List<TravelArticle> popularArticles = new ArrayList<>();
for (BinaryMapIndexReader reader : getReaders()) {
@ -188,13 +190,27 @@ public class TravelObfHelper implements TravelHelper {
@NonNull
@Override
public List<WikivoyageSearchResult> search(@NonNull String searchQuery) {
public synchronized List<WikivoyageSearchResult> search(@NonNull String searchQuery) {
List<WikivoyageSearchResult> res = new ArrayList<>();
Map<File, List<Amenity>> amenityMap = new HashMap<>();
final String appLang = app.getLanguage();
final NameStringMatcher nm = new NameStringMatcher(searchQuery, StringMatcherMode.CHECK_STARTS_FROM_SPACE);
for (BinaryMapIndexReader reader : getReaders()) {
try {
SearchRequest<Amenity> searchRequest = BinaryMapIndexReader.buildSearchPoiRequest(0, 0, searchQuery,
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchRouteArticleFilter(), null, null);
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchRouteArticleFilter(), new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity object) {
List<String> otherNames = object.getAllNames(false);
String localeName = object.getName(appLang);
return nm.matches(localeName) || nm.matches(otherNames);
}
@Override
public boolean isCancelled() {
return false;
}
}, null);
List<Amenity> amenities = reader.searchPoiByName(searchRequest);
if (!Algorithms.isEmpty(amenities)) {
@ -205,14 +221,35 @@ public class TravelObfHelper implements TravelHelper {
}
}
if (!Algorithms.isEmpty(amenityMap)) {
String appLang = app.getLanguage();
final boolean appLangEn = "en".equals(appLang);
for (Entry<File, List<Amenity>> entry : amenityMap.entrySet()) {
File file = entry.getKey();
for (Amenity amenity : entry.getValue()) {
Set<String> nameLangs = getLanguages(amenity);
if (nameLangs.contains(appLang)) {
TravelArticle article = readArticle(file, amenity, appLang);
WikivoyageSearchResult r = new WikivoyageSearchResult(article, new ArrayList<>(nameLangs));
ArrayList<String> langs = new ArrayList<>(nameLangs);
Collections.sort(langs, new Comparator<String>() {
@Override
public int compare(String l1, String l2) {
if (l1.equals(appLang)) {
l1 = "1";
}
if (l2.equals(appLang)) {
l2 = "1";
}
if (!appLangEn) {
if (l1.equals("en")) {
l1 = "2";
}
if (l2.equals("en")) {
l2 = "2";
}
}
return l1.compareTo(l2);
}
});
WikivoyageSearchResult r = new WikivoyageSearchResult(article, langs);
res.add(r);
}
}
@ -455,7 +492,7 @@ public class TravelObfHelper implements TravelHelper {
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang) {
TravelArticle article = null;
List<Amenity> amenities = null;
final List<Amenity> amenities = new ArrayList<>();
int x = 0;
int y = 0;
int left = 0;
@ -473,8 +510,25 @@ public class TravelObfHelper implements TravelHelper {
for (BinaryMapIndexReader reader : getReaders()) {
try {
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
x, y, title, left, right, top, bottom, getSearchRouteArticleFilter(), null, null);
amenities = reader.searchPoiByName(req);
x, y, title, left, right, top, bottom, getSearchRouteArticleFilter(),
new ResultMatcher<Amenity>() {
boolean done = false;
@Override
public boolean publish(Amenity amenity) {
if (Algorithms.stringsEqual(title, Algorithms.emptyIfNull(amenity.getName(lang)))) {
amenities.add(amenity);
done = true;
}
return false;
}
@Override
public boolean isCancelled() {
return done;
}
}, null);
reader.searchPoiByName(req);
} catch (IOException e) {
LOG.error(e.getMessage());
}

View file

@ -27,13 +27,14 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomnavigation.BottomNavigationView.OnNavigationItemSelectedListener;
import net.osmand.AndroidUtils;
import net.osmand.plus.AppInitializer;
import net.osmand.plus.LockableViewPager;
import net.osmand.plus.OnDialogFragmentResultListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.TabActivity;
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
import net.osmand.plus.wikivoyage.data.TravelArticle;
@ -314,7 +315,24 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
public void populateData() {
switchProgressBarVisibility(true);
new LoadWikivoyageData(this).execute();
if (app.isApplicationInitializing()) {
final WeakReference<WikivoyageExploreActivity> activityRef = new WeakReference<>(this);
app.getAppInitializer().addListener(new AppInitializer.AppInitializeListener() {
@Override
public void onProgress(AppInitializer init, AppInitializer.InitEvents event) {
}
@Override
public void onFinish(AppInitializer init) {
WikivoyageExploreActivity activity = activityRef.get();
if (AndroidUtils.isActivityNotDestroyed(activity)) {
new LoadWikivoyageData(activity).execute();
}
}
});
} else {
new LoadWikivoyageData(this).execute();
}
}
private void onDataLoaded() {
@ -364,8 +382,8 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
private static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {
private WeakReference<WikivoyageExploreActivity> activityRef;
private TravelHelper travelHelper;
private final WeakReference<WikivoyageExploreActivity> activityRef;
private final TravelHelper travelHelper;
LoadWikivoyageData(WikivoyageExploreActivity activity) {
travelHelper = activity.getMyApplication().getTravelHelper();
@ -381,7 +399,7 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
@Override
protected void onPostExecute(Void result) {
WikivoyageExploreActivity activity = activityRef.get();
if (activity != null) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
activity.onDataLoaded();
}
}