Merge pull request #10001 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2020-10-10 21:34:20 +02:00 committed by GitHub
commit 2c7f2ce56a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
227 changed files with 6443 additions and 4587 deletions

View file

@ -1,6 +1,6 @@
apply plugin: 'java'
apply plugin: 'maven-publish'
configurations {
android
}
@ -104,6 +104,9 @@ dependencies {
implementation 'com.moparisthebest:junidecode:0.1.1'
implementation 'com.vividsolutions:jts-core:1.14.0'
implementation 'com.google.openlocationcode:openlocationcode:1.0.4'
implementation ('com.github.scribejava:scribejava-apis:7.1.1') {
exclude group: "com.fasterxml.jackson.core"
}
// turn off for now
//implementation 'com.atilika.kuromoji:kuromoji-ipadic:0.9.0'
implementation 'net.sf.kxml:kxml2:2.1.8'

View file

@ -14,7 +14,8 @@ public class IndexConstants {
public static final String TEMP_SOURCE_TO_LOAD = "temp";
public static final String POI_INDEX_EXT = ".poi.odb"; //$NON-NLS-1$
public static final String ZIP_EXT = ".zip"; //$NON-NLS-1$
public static final String BINARY_MAP_INDEX_EXT = ".obf"; //$NON-NLS-1$
public static final String BINARY_MAP_INDEX_EXT_ZIP = ".obf.zip"; //$NON-NLS-1$
@ -71,7 +72,7 @@ public class IndexConstants {
public static final String FONT_INDEX_DIR = "fonts/"; //$NON-NLS-1$
public static final String VOICE_INDEX_DIR = "voice/"; //$NON-NLS-1$
public static final String RENDERERS_DIR = "rendering/"; //$NON-NLS-1$
public static final String ROUTING_XML_FILE= "routing.xml";
public static final String ROUTING_XML_FILE = "routing.xml";
public static final String SETTINGS_DIR = "settings/"; //$NON-NLS-1$
public static final String TEMP_DIR = "temp/";
public static final String ROUTING_PROFILES_DIR = "routing/";

View file

@ -27,7 +27,7 @@ public abstract class MapRenderingTypes {
private static final Log log = PlatformUtil.getLog(MapRenderingTypes.class);
public static final String[] langs = new String[] { "af", "als", "ar", "az", "be", "bg", "bn", "bpy", "br", "bs", "ca", "ceb", "cs", "cy", "da", "de", "el", "eo", "es", "et", "eu", "fa", "fi", "fr", "fy", "ga", "gl", "he", "hi", "hsb",
"hr", "ht", "hu", "hy", "id", "is", "it", "ja", "ka", "ko", "ku", "la", "lb", "lo", "lt", "lv", "mk", "ml", "mr", "ms", "nds", "new", "nl", "nn", "no", "nv", "os", "pl", "pms", "pt", "ro", "ru", "sc", "sh", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", "tl", "tr", "uk", "vi", "vo", "zh", "zh-hans", "zh-hant", };
"hr", "ht", "hu", "hy", "id", "is", "it", "ja", "ka", "kn", "ko", "ku", "la", "lb", "lo", "lt", "lv", "mk", "ml", "mr", "ms", "nds", "new", "nl", "nn", "no", "nv", "os", "pl", "pms", "pt", "ro", "ru", "sc", "sh", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", "tl", "tr", "uk", "vi", "vo", "zh", "zh-hans", "zh-hant", };
public final static byte RESTRICTION_NO_RIGHT_TURN = 1;

View file

@ -1,30 +1,22 @@
package net.osmand.osm.io;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import com.github.scribejava.core.model.OAuthRequest;
import com.github.scribejava.core.model.Response;
import com.github.scribejava.core.model.Verb;
import net.osmand.PlatformUtil;
import net.osmand.osm.oauth.OsmOAuthAuthorizationClient;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.*;
import java.net.*;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.zip.GZIPOutputStream;
public class NetworkUtils {
private static final Log log = PlatformUtil.getLog(NetworkUtils.class);
private static final String GPX_UPLOAD_USER_AGENT = "OsmGPXUploadAgent";
private static Proxy proxy = null;
public static String sendGetRequest(String urlText, String userNamePassword, StringBuilder responseBody){
@ -55,7 +47,6 @@ public class NetworkUtils {
responseBody.append("\n"); //$NON-NLS-1$
}
responseBody.append(s);
}
is.close();
}
@ -65,9 +56,10 @@ public class NetworkUtils {
return e.getMessage();
}
}
private static final String BOUNDARY = "CowMooCowMooCowCowCow"; //$NON-NLS-1$
public static String uploadFile(String urlText, File fileToUpload, String userNamePassword, String formName, boolean gzip, Map<String, String> additionalMapData){
public static String uploadFile(String urlText, File fileToUpload, String userNamePassword,
OsmOAuthAuthorizationClient client,
String formName, boolean gzip, Map<String, String> additionalMapData){
URL url;
try {
boolean firstPrm =!urlText.contains("?");
@ -77,34 +69,48 @@ public class NetworkUtils {
}
log.info("Start uploading file to " + urlText + " " +fileToUpload.getName());
url = new URL(urlText);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
if(userNamePassword != null) {
conn.setRequestProperty("Authorization", "Basic " + Base64.encode(userNamePassword)); //$NON-NLS-1$ //$NON-NLS-2$
HttpURLConnection conn;
if (client != null && client.isValidToken()){
OAuthRequest req = new OAuthRequest(Verb.POST, urlText);
client.getService().signRequest(client.getAccessToken(), req);
req.addHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
try {
Response r = client.getHttpClient().execute(GPX_UPLOAD_USER_AGENT, req.getHeaders(), req.getVerb(),
req.getCompleteUrl(), fileToUpload);
if (r.getCode() != 200) {
return r.getBody();
}
return null;
} catch (InterruptedException e) {
log.error(e);
} catch (ExecutionException e) {
log.error(e);
}
return null;
}
else {
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
if(userNamePassword != null) {
conn.setRequestProperty("Authorization", "Basic " + Base64.encode(userNamePassword)); //$NON-NLS-1$ //$NON-NLS-2$
}
}
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //$NON-NLS-1$ //$NON-NLS-2$
conn.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$
OutputStream ous = conn.getOutputStream();
// for (String key : additionalMapData.keySet()) {
// ous.write(("--" + BOUNDARY + "\r\n").getBytes());
// ous.write(("content-disposition: form-data; name=\"" + key + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
// ous.write((additionalMapData.get(key) + "\r\n").getBytes());
// }
ous.write(("--" + BOUNDARY+"\r\n").getBytes());
ous.write(("--" + BOUNDARY + "\r\n").getBytes());
String filename = fileToUpload.getName();
if(gzip){
filename+=".gz";
if (gzip) {
filename += ".gz";
}
ous.write(("content-disposition: form-data; name=\""+formName+"\"; filename=\"" + filename + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$
InputStream fis = new FileInputStream(fileToUpload);
ous.write(("content-disposition: form-data; name=\"" + formName + "\"; filename=\"" + filename + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$
InputStream fis = new FileInputStream(fileToUpload);
BufferedInputStream bis = new BufferedInputStream(fis, 20 * 1024);
ous.flush();
if(gzip){
if (gzip) {
GZIPOutputStream gous = new GZIPOutputStream(ous, 1024);
Algorithms.streamCopy(bis, gous);
gous.flush();
@ -112,8 +118,7 @@ public class NetworkUtils {
} else {
Algorithms.streamCopy(bis, ous);
}
ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
ous.flush();
Algorithms.closeStream(bis);
Algorithms.closeStream(ous);
@ -136,7 +141,6 @@ public class NetworkUtils {
responseBody.append("\n"); //$NON-NLS-1$
}
responseBody.append(s);
}
is.close();
}
@ -157,7 +161,6 @@ public class NetworkUtils {
proxy = null;
}
}
public static Proxy getProxy() {
return proxy;
}

View file

@ -0,0 +1,259 @@
package net.osmand.osm.oauth;
import com.github.scribejava.core.exceptions.OAuthException;
import com.github.scribejava.core.httpclient.HttpClient;
import com.github.scribejava.core.httpclient.jdk.JDKHttpClientConfig;
import com.github.scribejava.core.httpclient.jdk.JDKHttpFuture;
import com.github.scribejava.core.httpclient.multipart.MultipartPayload;
import com.github.scribejava.core.httpclient.multipart.MultipartUtils;
import com.github.scribejava.core.model.*;
import net.osmand.util.Algorithms;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class OsmAndJDKHttpClient implements HttpClient {
private static final String BOUNDARY = "CowMooCowMooCowCowCow";
private final JDKHttpClientConfig config;
public OsmAndJDKHttpClient() {
this(JDKHttpClientConfig.defaultConfig());
}
public OsmAndJDKHttpClient(JDKHttpClientConfig clientConfig) {
config = clientConfig;
}
@Override
public void close() {
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
byte[] bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents, callback,
converter);
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
MultipartPayload bodyContents, OAuthAsyncRequestCallback<T> callback,
OAuthRequest.ResponseConverter<T> converter) {
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.MULTIPART, bodyContents, callback,
converter);
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
String bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents, callback,
converter);
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
File bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.STREAM, bodyContents, callback,
converter);
}
private <T> Future<T> doExecuteAsync(String userAgent, Map<String, String> headers, Verb httpVerb,
String completeUrl, BodyType bodyType, Object bodyContents, OAuthAsyncRequestCallback<T> callback,
OAuthRequest.ResponseConverter<T> converter) {
try {
final Response response = doExecute(userAgent, headers, httpVerb, completeUrl, bodyType, bodyContents);
@SuppressWarnings("unchecked") final T t = converter == null ? (T) response : converter.convert(response);
if (callback != null) {
callback.onCompleted(t);
}
return new JDKHttpFuture<>(t);
} catch (IOException | RuntimeException e) {
if (callback != null) {
callback.onThrowable(e);
}
return new JDKHttpFuture<>(e);
}
}
@Override
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
byte[] bodyContents) throws InterruptedException, ExecutionException, IOException {
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents);
}
@Override
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
MultipartPayload multipartPayloads) throws InterruptedException, ExecutionException, IOException {
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.MULTIPART, multipartPayloads);
}
@Override
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
String bodyContents) throws InterruptedException, ExecutionException, IOException {
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents);
}
@Override
public Response execute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
File bodyContents) throws InterruptedException, ExecutionException, IOException {
return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.STREAM, bodyContents);
}
private Response doExecute(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
BodyType bodyType, Object bodyContents) throws IOException {
final URL url = new URL(completeUrl);
final HttpURLConnection connection;
if (config.getProxy() == null) {
connection = (HttpURLConnection) url.openConnection();
} else {
connection = (HttpURLConnection) url.openConnection(config.getProxy());
}
connection.setInstanceFollowRedirects(config.isFollowRedirects());
connection.setRequestMethod(httpVerb.name());
if (config.getConnectTimeout() != null) {
connection.setConnectTimeout(config.getConnectTimeout());
}
if (config.getReadTimeout() != null) {
connection.setReadTimeout(config.getReadTimeout());
}
addHeaders(connection, headers, userAgent);
if (httpVerb.isPermitBody()) {
bodyType.setBody(connection, bodyContents, httpVerb.isRequiresBody());
}
try {
connection.connect();
final int responseCode = connection.getResponseCode();
return new Response(responseCode, connection.getResponseMessage(), parseHeaders(connection),
responseCode >= 200 && responseCode < 400 ? connection.getInputStream()
: connection.getErrorStream());
} catch (UnknownHostException e) {
throw new OAuthException("The IP address of a host could not be determined.", e);
}
}
private enum BodyType {
BYTE_ARRAY {
@Override
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
addBody(connection, (byte[]) bodyContents, requiresBody);
}
},
STREAM {
@Override
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
addBody(connection, (File) bodyContents, requiresBody);
}
},
MULTIPART {
@Override
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
addBody(connection, (MultipartPayload) bodyContents, requiresBody);
}
},
STRING {
@Override
void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException {
addBody(connection, ((String) bodyContents).getBytes(), requiresBody);
}
};
abstract void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody)
throws IOException;
}
private static Map<String, String> parseHeaders(HttpURLConnection conn) {
final Map<String, String> headers = new HashMap<>();
for (Map.Entry<String, List<String>> headerField : conn.getHeaderFields().entrySet()) {
final String key = headerField.getKey();
final String value = headerField.getValue().get(0);
if ("Content-Encoding".equalsIgnoreCase(key)) {
headers.put("Content-Encoding", value);
} else {
headers.put(key, value);
}
}
return headers;
}
private static void addHeaders(HttpURLConnection connection, Map<String, String> headers, String userAgent) {
for (Map.Entry<String, String> header : headers.entrySet()) {
connection.setRequestProperty(header.getKey(), header.getValue());
}
if (userAgent != null) {
connection.setRequestProperty(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent);
}
}
private static void addBody(HttpURLConnection connection, File file, boolean requiresBody) throws IOException {
if (requiresBody) {
String filename = file.getName();
String formName = "file";
InputStream stream = new FileInputStream(file);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //$NON-NLS-1$ //$NON-NLS-2$
connection.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$
final OutputStream ous = connection.getOutputStream();
ous.write(("--" + BOUNDARY + "\r\n").getBytes());
ous.write(("content-disposition: form-data; name=\"" + formName + "\"; filename=\"" + filename + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$
BufferedInputStream bis = new BufferedInputStream(stream, 20 * 1024);
ous.flush();
Algorithms.streamCopy(bis, ous);
ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
ous.flush();
Algorithms.closeStream(bis);
}
}
private static void addBody(HttpURLConnection connection, byte[] content, boolean requiresBody) throws IOException {
final int contentLength = content.length;
if (requiresBody || contentLength > 0) {
connection.setDoOutput(true);
final OutputStream outputStream = prepareConnectionForBodyAndGetOutputStream(connection, contentLength);
if (contentLength > 0) {
outputStream.write(content);
}
}
}
private static void addBody(HttpURLConnection connection, MultipartPayload multipartPayload, boolean requiresBody)
throws IOException {
for (Map.Entry<String, String> header : multipartPayload.getHeaders().entrySet()) {
connection.setRequestProperty(header.getKey(), header.getValue());
}
if (requiresBody) {
final ByteArrayOutputStream os = MultipartUtils.getPayload(multipartPayload);
final int contentLength = os.size();
connection.setDoOutput(true);
final OutputStream outputStream = prepareConnectionForBodyAndGetOutputStream(connection, contentLength);
if (contentLength > 0) {
os.writeTo(outputStream);
}
}
}
private static OutputStream prepareConnectionForBodyAndGetOutputStream(HttpURLConnection connection,
int contentLength) throws IOException {
connection.setRequestProperty(CONTENT_LENGTH, String.valueOf(contentLength));
if (connection.getRequestProperty(CONTENT_TYPE) == null) {
connection.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
}
return connection.getOutputStream();
}
}

View file

@ -0,0 +1,149 @@
// License: GPL. For details, see LICENSE file.
package net.osmand.osm.oauth;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.builder.api.DefaultApi10a;
import com.github.scribejava.core.builder.api.OAuth1SignatureType;
import com.github.scribejava.core.httpclient.jdk.JDKHttpClientConfig;
import com.github.scribejava.core.model.*;
import com.github.scribejava.core.oauth.OAuth10aService;
import net.osmand.PlatformUtil;
import org.apache.commons.logging.Log;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
/**
* An OAuth 1.0 authorization client.
*
* @since 2746
*/
public class OsmOAuthAuthorizationClient {
private OAuth1RequestToken requestToken;
private OAuth1AccessToken accessToken;
private final OAuth10aService service;
private final OsmAndJDKHttpClient httpClient;
public final static Log log = PlatformUtil.getLog(OsmOAuthAuthorizationClient.class);
public OsmOAuthAuthorizationClient(String key, String secret) {
httpClient = new OsmAndJDKHttpClient(JDKHttpClientConfig.defaultConfig());
service = new ServiceBuilder(key)
.apiSecret(secret)
.httpClient(httpClient)
.callback("osmand-oauth://example.com/oauth")
.build(new OsmApi());
}
static class OsmApi extends DefaultApi10a {
@Override
public OAuth1SignatureType getSignatureType() {
return OAuth1SignatureType.QUERY_STRING;
}
@Override
public String getRequestTokenEndpoint() {
return "https://www.openstreetmap.org/oauth/request_token";
}
@Override
public String getAccessTokenEndpoint() {
return "https://www.openstreetmap.org/oauth/access_token";
}
@Override
protected String getAuthorizationBaseUrl() {
return "https://www.openstreetmap.org/oauth/authorize";
}
}
public OsmAndJDKHttpClient getHttpClient() {
return httpClient;
}
public OAuth10aService getService() {
return service;
}
public void setAccessToken(OAuth1AccessToken accessToken) {
this.accessToken = accessToken;
}
public OAuth1AccessToken getAccessToken() {
return accessToken;
}
public Response performRequestWithoutAuth(String url, String requestMethod, String requestBody)
throws InterruptedException, ExecutionException, IOException {
Verb verb = parseRequestMethod(requestMethod);
OAuthRequest req = new OAuthRequest(verb, url);
req.setPayload(requestBody);
return service.execute(req);
}
public void performGetRequest(String url, OAuthAsyncRequestCallback<Response> callback) {
if (accessToken == null) {
throw new IllegalStateException("Access token is null");
}
OAuthRequest req = new OAuthRequest(Verb.GET, url);
service.signRequest(accessToken, req);
service.execute(req, callback);
}
public Response performRequest(String url, String method, String body)
throws InterruptedException, ExecutionException, IOException {
service.getApi().getSignatureType();
if (accessToken == null) {
throw new IllegalStateException("Access token is null");
}
Verb verbMethod = parseRequestMethod(method);
OAuthRequest req = new OAuthRequest(verbMethod, url);
req.setPayload(body);
service.signRequest(accessToken, req);
req.addHeader("Content-Type", "application/xml");
return service.execute(req);
}
public OAuth1RequestToken startOAuth() {
try {
requestToken = service.getRequestToken();
} catch (IOException e) {
log.error(e);
} catch (InterruptedException e) {
log.error(e);
} catch (ExecutionException e) {
log.error(e);
}
return requestToken;
}
public OAuth1AccessToken authorize(String oauthVerifier) {
try {
setAccessToken(service.getAccessToken(requestToken, oauthVerifier));
} catch (IOException e) {
log.error(e);
} catch (InterruptedException e) {
log.error(e);
} catch (ExecutionException e) {
log.error(e);
}
return accessToken;
}
public boolean isValidToken() {
return !(accessToken == null);
}
private Verb parseRequestMethod(String method) {
Verb m = Verb.GET;
if (method.equals("POST")) {
m = Verb.POST;
}
if (method.equals("PUT")) {
m = Verb.PUT;
}
if (method.equals("DELETE")) {
m = Verb.DELETE;
}
return m;
}
}

View file

@ -49,6 +49,11 @@ public class Algorithms {
private static char[] CHARS_TO_NORMALIZE_KEY = new char[''];
private static char[] CHARS_TO_NORMALIZE_VALUE = new char['\''];
public static final int ZIP_FILE_SIGNATURE = 0x504b0304;
public static final int XML_FILE_SIGNATURE = 0x3c3f786d;
public static final int OBF_FILE_SIGNATURE = 0x08029001;
public static final int SQLITE_FILE_SIGNATURE = 0x53514C69;
public static String normalizeSearchText(String s) {
boolean norm = false;
for (int i = 0; i < s.length() && !norm; i++) {
@ -293,7 +298,7 @@ public class Algorithms {
FileInputStream in = new FileInputStream(file);
int test = readInt(in);
in.close();
return test == 0x504b0304;
return test == ZIP_FILE_SIGNATURE;
}
/**
@ -322,7 +327,7 @@ public class Algorithms {
return false;
}
private static int readInt(InputStream in) throws IOException {
public static int readInt(InputStream in) throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
@ -942,4 +947,20 @@ public class Algorithms {
}
return res;
}
public static boolean isValidMessageFormat(CharSequence sequence) {
if (!isEmpty(sequence)) {
int counter = 0;
for (int i = 0; i < sequence.length(); i++) {
char ch = sequence.charAt(i);
if (ch == '{') {
counter++;
} else if (ch == '}') {
counter--;
}
}
return counter == 0;
}
return false;
}
}

View file

@ -267,4 +267,8 @@
<string name="status_widget_title">تتبع حالة أوسماند</string>
<string name="back_to_osmand">العودة إلى OsmAnd</string>
<string name="duration_ago">%1$s منذ</string>
<string name="send_report">إرسال التقرير</string>
<string name="shared_string_export">تصدير</string>
<string name="logcat_buffer">سجل الاستخدام</string>
<string name="logcat_buffer_descr">التحقق من السجلات التفصيلية للتطبيق ومشاركتها</string>
</resources>

View file

@ -268,4 +268,8 @@
<string name="last_response_duration">Última respuesta: Hace %1$s</string>
<string name="duration_ago">Hace %1$s</string>
<string name="shared_string_error_short">ERR</string>
<string name="shared_string_export">Exportar</string>
<string name="logcat_buffer">Búfer de Logcat</string>
<string name="logcat_buffer_descr">Comprueba y comparte los registros detallados de la aplicación</string>
<string name="send_report">Enviar informe</string>
</resources>

View file

@ -268,4 +268,8 @@
<string name="time_zone_descr">Escolle a zona horaria que desexas amosar nas mensaxes de localización.</string>
<string name="buffer_time">Tempo de caducidade do búfer</string>
<string name="buffer_time_descr">Tempo máximo para almacenar puntos no búfer</string>
<string name="shared_string_export">Exportar</string>
<string name="logcat_buffer">Búfer de Logcat</string>
<string name="logcat_buffer_descr">Verifica e comparte rexistros detallados da aplicación</string>
<string name="send_report">Enviar denuncia</string>
</resources>

View file

@ -267,4 +267,8 @@
<string name="last_response_duration">Siste respons: %1$s siden</string>
<string name="duration_ago">%1$s siden</string>
<string name="shared_string_error_short">FEIL</string>
<string name="logcat_buffer">Logcat-mellomlager</string>
<string name="shared_string_export">Eksporter</string>
<string name="logcat_buffer_descr">Sjekk og del detaljert loggføring fra programmet</string>
<string name="send_report">Send rapport</string>
</resources>

View file

@ -267,4 +267,8 @@
<string name="last_response_date">Última resposta: %1$s</string>
<string name="last_update_from_telegram_date">Última atualização do Telegram: %1$s</string>
<string name="shared_string_error_short">ERR</string>
<string name="send_report">Enviar o relatório</string>
<string name="shared_string_export">Exportar</string>
<string name="logcat_buffer">Buffer de logcat</string>
<string name="logcat_buffer_descr">Verifique e compartilhe registos detalhados da app</string>
</resources>

View file

@ -110,7 +110,7 @@ private const val PROXY_ENABLED = "proxy_enabled"
private const val PROXY_PREFERENCES_KEY = "proxy_preferences"
private const val SHARING_INITIALIZATION_TIME = 60 * 2L // 2 minutes
private const val WAITING_TDLIB_TIME = 3 // 3 seconds
private const val WAITING_TDLIB_TIME = 7 // 7 seconds
private const val GPS_UPDATE_EXPIRED_TIME = 60 * 3L // 3 minutes

View file

@ -7,7 +7,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
@ -52,7 +52,7 @@
<application android:allowBackup="true" android:backupAgent="net.osmand.plus.OsmandBackupAgent"
android:icon="@mipmap/icon" android:label="@string/app_name"
android:name="net.osmand.plus.OsmandApplication" android:configChanges="locale"
android:theme="@style/OsmandDarkTheme" android:restoreAnyVersion="true" android:largeHeap="true"
android:theme="@style/OsmandDarkTheme" android:restoreAnyVersion="true" android:largeHeap="true"
android:supportsRtl="true" android:usesCleartextTraffic="true">
<meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIqF3tNGT66etVBn_vgzpfAY1wmIzKV1Ss6Ku-2A" />
@ -65,7 +65,7 @@
<meta-data android:name="com.sec.minimode.icon.landscape.normal" android:resource="@mipmap/icon" android:value="" />
<activity android:name="net.osmand.plus.activities.HelpActivity" />
<activity android:name="net.osmand.plus.activities.ExitActivity" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="net.osmand.plus.fileprovider"
@ -479,7 +479,16 @@
<activity android:name="net.osmand.plus.activities.SettingsNavigationActivity" android:configChanges="keyboardHidden|orientation" />
<activity android:name="net.osmand.plus.monitoring.SettingsMonitoringActivity" android:configChanges="keyboardHidden|orientation" />
<activity android:name="net.osmand.plus.osmedit.SettingsOsmEditingActivity" android:configChanges="keyboardHidden|orientation" />
<activity android:name="net.osmand.plus.osmedit.SettingsOsmEditingActivity"
android:launchMode="singleInstance"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="osmand-oauth" />
</intent-filter>
</activity>
<activity android:name="net.osmand.plus.development.SettingsDevelopmentActivity" android:configChanges="keyboardHidden|orientation" />
<activity android:name="net.osmand.plus.audionotes.SettingsAudioVideoActivity" android:configChanges="keyboardHidden|orientation" />
<activity android:name="net.osmand.access.SettingsAccessibilityActivity" android:configChanges="keyboardHidden|orientation" />
@ -1025,7 +1034,7 @@
<!-- keep android:process on a separate line !! -->
<service
android:process="net.osmand.plus"
android:process="net.osmand.plus"
android:label="@string/process_navigation_service"
android:name="net.osmand.plus.NavigationService"
android:foregroundServiceType="location"

View file

@ -227,12 +227,16 @@ android {
buildTypes {
debug {
buildConfigField "String", "OSM_OAUTH_CONSUMER_KEY", "\"Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y\""
buildConfigField "String", "OSM_OAUTH_CONSUMER_SECRET", "\"lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM\""
signingConfig signingConfigs.development
debuggable false
jniDebuggable false
buildConfigField "boolean", "USE_DEBUG_LIBRARIES", "false"
}
release {
buildConfigField "String", "OSM_OAUTH_CONSUMER_KEY", "\"Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y\""
buildConfigField "String", "OSM_OAUTH_CONSUMER_SECRET", "\"lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM\""
if (gradle.startParameter.taskNames.toString().contains("huawei")) {
signingConfig signingConfigs.publishingHuawei
} else {
@ -535,6 +539,9 @@ dependencies {
implementation ("com.github.HITGIF:TextFieldBoxes:1.4.5"){
exclude group: 'com.android.support'
}
implementation('com.github.scribejava:scribejava-apis:7.1.1'){
exclude group: "com.fasterxml.jackson.core"
}
implementation 'com.jaredrummler:colorpicker:1.1.0'
freehuaweiImplementation 'com.huawei.hms:iap:5.0.2.300'

View file

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M7,13C5.8954,13 5,13.8954 5,15C5,16.1046 5.8954,17 7,17H20C20.5523,17 21,17.4477 21,18C21,18.5523 20.5523,19 20,19H7C4.7909,19 3,17.2091 3,15C3,12.7909 4.7909,11 7,11H16.5C17.0523,11 17.5,11.4477 17.5,12C17.5,12.5523 17.0523,13 16.5,13H7Z"
android:strokeAlpha="0.5"
android:fillColor="#ffffff"
android:fillType="evenOdd"
android:fillAlpha="0.5"/>
<path
android:pathData="M21,18C21,19.1046 20.1046,20 19,20C17.8954,20 17,19.1046 17,18C17,16.8954 17.8954,16 19,16C20.1046,16 21,16.8954 21,18Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M3,6C3,4.3432 4.3432,3 6,3C7.3062,3 8.4175,3.8348 8.8293,5H17C19.2091,5 21,6.7909 21,9C21,11.2091 19.2091,13 17,13H16.5C15.9477,13 15.5,12.5523 15.5,12C15.5,11.4477 15.9477,11 16.5,11H17C18.1046,11 19,10.1046 19,9C19,7.8954 18.1046,7 17,7H8.8293C8.4175,8.1652 7.3062,9 6,9C4.3432,9 3,7.6568 3,6ZM7,6C7,5.4477 6.5523,5 6,5C5.4477,5 5,5.4477 5,6C5,6.5523 5.4477,7 6,7C6.5523,7 7,6.5523 7,6Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M7,6C7,6.5523 6.5523,7 6,7C5.4477,7 5,6.5523 5,6C5,5.4477 5.4477,5 6,5C6.5523,5 7,5.4477 7,6Z"
android:strokeAlpha="0.5"
android:fillColor="#ffffff"
android:fillAlpha="0.5"/>
</vector>

View file

@ -0,0 +1,39 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M16,16m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"
android:fillColor="#ffffff"/>
<path
android:pathData="M23,22L21,22A1,1 0,0 0,20 23L20,23A1,1 0,0 0,21 24L23,24A1,1 0,0 0,24 23L24,23A1,1 0,0 0,23 22z"
android:fillColor="#8AC826"/>
<path
android:pathData="M9,10L11,10A1,1 0,0 1,12 11L12,11A1,1 0,0 1,11 12L9,12A1,1 0,0 1,8 11L8,11A1,1 0,0 1,9 10z"
android:fillColor="#140579"/>
<path
android:pathData="M14,10L16,10A1,1 0,0 1,17 11L17,11A1,1 0,0 1,16 12L14,12A1,1 0,0 1,13 11L13,11A1,1 0,0 1,14 10z"
android:fillColor="#FFC93A"/>
<path
android:pathData="M19,10L23,10A1,1 0,0 1,24 11L24,11A1,1 0,0 1,23 12L19,12A1,1 0,0 1,18 11L18,11A1,1 0,0 1,19 10z"
android:fillColor="#8AC826"/>
<path
android:pathData="M23,14L20,14A1,1 0,0 0,19 15L19,15A1,1 0,0 0,20 16L23,16A1,1 0,0 0,24 15L24,15A1,1 0,0 0,23 14z"
android:fillColor="#8AC826"/>
<path
android:pathData="M17,14L15,14A1,1 0,0 0,14 15L14,15A1,1 0,0 0,15 16L17,16A1,1 0,0 0,18 15L18,15A1,1 0,0 0,17 14z"
android:fillColor="#FFC93A"/>
<path
android:pathData="M12,14L9,14A1,1 0,0 0,8 15L8,15A1,1 0,0 0,9 16L12,16A1,1 0,0 0,13 15L13,15A1,1 0,0 0,12 14z"
android:fillColor="#140579"/>
<path
android:pathData="M23,18L18,18A1,1 0,0 0,17 19L17,19A1,1 0,0 0,18 20L23,20A1,1 0,0 0,24 19L24,19A1,1 0,0 0,23 18z"
android:fillColor="#8AC826"/>
<path
android:pathData="M15,18L12,18A1,1 0,0 0,11 19L11,19A1,1 0,0 0,12 20L15,20A1,1 0,0 0,16 19L16,19A1,1 0,0 0,15 18z"
android:fillColor="#FFC93A"/>
<path
android:pathData="M9,18L9,18A1,1 0,0 0,8 19L8,19A1,1 0,0 0,9 20L9,20A1,1 0,0 0,10 19L10,19A1,1 0,0 0,9 18z"
android:fillColor="#140579"/>
</vector>

View file

@ -6,33 +6,37 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start"
osmand:typeface="@string/font_roboto_regular"
android:layout_weight="1"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="title"/>
osmand:typeface="@string/font_roboto_regular"
tools:text="Some very long title to check overlapped texts" />
<Space
android:layout_width="@dimen/content_padding"
android:layout_height="match_parent" />
<net.osmand.plus.widgets.TextViewEx
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
osmand:typeface="@string/font_roboto_medium"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_list_text_size"
tools:text="summary"/>
osmand:typeface="@string/font_roboto_medium"
tools:text="summary" />
</FrameLayout>
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/slider"

View file

@ -1074,7 +1074,7 @@
<string name="rendering_category_routes">المسارات الرياضية</string>
<string name="rendering_category_transport">وسائل المواصلات</string>
<string name="rendering_category_others">سمات أخرى للخريطة</string>
<string name="map_widget_appearance_rem">العناصر الاخرى</string>
<string name="map_widget_appearance_rem">العناصر الأخرى</string>
<string name="map_widget_top">شريط المعلومات</string>
<string name="map_widget_right">العدادات على اليمين</string>
<string name="map_widget_left">العدادات على اليسار</string>
@ -3413,7 +3413,7 @@
<string name="select_nav_icon_descr">سترى الأيقونة فقط أثناء الملاحة أو أثناء التحرك.</string>
<string name="button_rate">قيم</string>
<string name="select_map_icon_descr">تظهر أيقونة الخريطة فقط على الخريطة ، وتتغير أثناء التنقل إلى أيقونة التنقل.</string>
<string name="logcat_buffer_descr">تحقق وتبادل سجلات مفصلة من التطبيق</string>
<string name="logcat_buffer_descr">التحقق من السجلات التفصيلية للتطبيق ومشاركتها</string>
<string name="search_offline_geo_error">تعذر تحليل الهدف الجغرافي \'%s\'.</string>
<string name="permission_is_required">الإذن مطلوب لاستخدام هذا الخيار.</string>
<string name="monitoring_min_speed_descr_side_effect">اعراض جانبية: سيفقد المسار الخاص بك جميع الأقسام التي لم يتحقق فيها معيار الحد الأدنى للسرعة (على سبيل المثال ، حيث تدفع دراجتك أعلى تل شديد الانحدار). أيضا ، لن تكون هناك معلومات حول فترات الراحة ، مثل الاستراحات. هذا له تأثيرات على أي تحليل أو مرحلة ما بعد المعالجة ، مثل عند محاولة تحديد المدة الإجمالية لرحلتك ، أو وقت الحركة ، أو متوسط سرعتك.</string>
@ -3893,4 +3893,12 @@
<string name="sort_name_ascending">الاسم: أ ي</string>
<string name="start_finish_icons">رموز البدء/الانتهاء</string>
<string name="contour_lines_thanks">شكرا لشرائك \"خطوط الكنتور\"</string>
<string name="osm_live_payment_desc_hw">رسوم الاشتراك ستفرض كل شهر. يمكنك إلغاء اشتراكك متى أردت عبر Google play.</string>
<string name="osm_live_payment_subscription_management_hw">سيتم تحصيل المبلغ على حساب AppGallery الخاص بك عند تأكيد الشراء.
\n
\nيتم تجديد الاشتراك تلقائيًا ما لم يتم إلغاؤه قبل تاريخ التجديد. سيتم خصم حسابك على فترة التجديد (شهر/ثلاثة أشهر/سنة) فقط في تاريخ التجديد.
\n
\nيمكنك إدارة وإلغاء الاشتراكات الخاصة بك عن طريق الانتقال إلى إعدادات AppGallery.</string>
<string name="routing_attr_avoid_footways_description">تجنب الممرات</string>
<string name="routing_attr_avoid_footways_name">تجنب الممرات</string>
</resources>

View file

@ -1570,7 +1570,7 @@
<string name="routing_attr_height_description">Höhe des Fahrzeugs für Routenberechnung angeben.</string>
<string name="download_wikipedia_maps">Wikipedia</string>
<string name="use_fast_recalculation">Schnelle Routenneuberechnung</string>
<string name="use_fast_recalculation_desc">Bei längeren Routen nur den Anfangsteil neu berechnen.</string>
<string name="use_fast_recalculation_desc">Nur den Anfangsteil neu berechnen. Kann bei längeren Routen benutzt werden.</string>
<string name="lang_es_ar">Spanisch (Argentinien)</string>
<string name="lang_th">Thailändisch</string>
<string name="lang_ms">Malaysisch</string>
@ -3826,7 +3826,7 @@
<string name="plan_route_select_track_file_for_open">Wählen Sie eine Trackdatei zum Öffnen aus.</string>
<string name="shared_string_done">Fertig</string>
<string name="overwrite_track">Track überschreiben</string>
<string name="threshold_distance">Schwellenwert-Distanz</string>
<string name="threshold_distance">Maximaler Abstand</string>
<string name="save_as_new_track">Als neuen Track speichern</string>
<string name="reverse_route">Route umkehren</string>
<string name="route_between_points_whole_track_button_desc">Der gesamte Track wird mit dem ausgewählten Profil neu berechnet.</string>
@ -3910,4 +3910,19 @@
<string name="sort_name_ascending">Name: A Z</string>
<string name="start_finish_icons">Start-/Ziel-Symbole</string>
<string name="contour_lines_thanks">Vielen Dank für den Kauf von \'Höhenlinien\'</string>
<string name="osm_live_payment_desc_hw">Das Abonnement wird pro ausgewähltem Zeitraum berechnet. Sie können das Abonnement jederzeit über die AppGallery kündigen.</string>
<string name="osm_live_payment_subscription_management_hw">Die Bezahlung wird Ihrem AppGallery-Konto bei der Bestätigung des Kaufs belastet.
\n
\n Das Abonnement verlängert sich automatisch, sofern es nicht vor dem Verlängerungsdatum gekündigt wird. Ihr Konto wird für den Verlängerungszeitraum (Monat / drei Monate / Jahr) nur am Verlängerungsdatum belastet.
\n
\n Sie können Ihre Abonnements verwalten und kündigen, indem Sie zu Ihren AppGallery-Einstellungen gehen.</string>
<string name="routing_attr_avoid_footways_description">Vermeidet Fußwege</string>
<string name="routing_attr_avoid_footways_name">Keine Fußwege</string>
<string name="development">Entwicklung</string>
<string name="use_live_public_transport">OsmAnd Live Daten</string>
<string name="use_live_routing">OsmAnd Live Daten</string>
<string name="use_complex_routing">Komplexe Routenberechnung</string>
<string name="complex_routing_descr">Zwei-Phasen-Routenberechnung für die Autonavigation.</string>
<string name="use_native_pt">Native ÖPNV Entwicklung</string>
<string name="use_native_pt_desc">Wechseln zu Java (sicher) Berechnung des ÖPNV-Routings</string>
</resources>

View file

@ -1541,7 +1541,7 @@
<string name="routing_attr_height_name">Límite de altura</string>
<string name="routing_attr_height_description">Indica la altura permitida del vehículo en rutas.</string>
<string name="use_fast_recalculation">Recálculo inteligente de ruta</string>
<string name="use_fast_recalculation_desc">Para viajes largos, recalcula sólo la parte inicial de la ruta.</string>
<string name="use_fast_recalculation_desc">Recalcula sólo la parte inicial de la ruta. Puede usarse para viajes largos.</string>
<string name="shared_string_logoff">Cerrar sesión</string>
<string name="rendering_value_disabled_name">Desactivado</string>
<string name="rendering_value_walkingRoutesScopeOSMC_name">Color por red de afiliación</string>
@ -3909,4 +3909,19 @@
<string name="sort_name_ascending">Nombre: A Z</string>
<string name="start_finish_icons">Iconos de inicio/fin</string>
<string name="contour_lines_thanks">Gracias por comprar las «Curvas de nivel»</string>
<string name="osm_live_payment_desc_hw">La suscripción se cobra por el período elegido. Puedes cancelarlo en cualquier momento en AppGallery.</string>
<string name="osm_live_payment_subscription_management_hw">El pago será cargado a la cuenta de AppGallery al confirmar la compra.
\n
\nLa suscripción se renueva automáticamente a menos que se cancele antes de la fecha de renovación. La cuenta será cargada por el período de renovación (mes/trimestre/año) sólo en la fecha de renovación.
\n
\nPuedes administrar y cancelar las suscripciones accediendo a los ajustes de AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Evita pasar por las veredas o aceras</string>
<string name="routing_attr_avoid_footways_name">Evitar veredas/aceras</string>
<string name="development">Desarrollo</string>
<string name="use_live_public_transport">Datos de «OsmAnd Live»</string>
<string name="use_live_routing">Datos de «OsmAnd Live»</string>
<string name="use_complex_routing">Navegación compleja</string>
<string name="complex_routing_descr">Navegación bifásica en automóvil.</string>
<string name="use_native_pt">Desarrollo nativo del transporte público</string>
<string name="use_native_pt_desc">Cambiar al cálculo de ruta Java (seguro) del transporte público</string>
</resources>

View file

@ -3905,4 +3905,13 @@
<string name="sort_name_ascending">Nombre: A Z</string>
<string name="sort_last_modified">Último modificado</string>
<string name="start_finish_icons">Iconos de inicio/fin</string>
<string name="contour_lines_thanks">Gracias por comprar las «Curvas de nivel»</string>
<string name="osm_live_payment_desc_hw">La suscripción se cobra por el período elegido. Puedes cancelarlo en cualquier momento en AppGallery.</string>
<string name="osm_live_payment_subscription_management_hw">El pago será cargado a la cuenta de AppGallery al confirmar la compra.
\n
\nLa suscripción se renueva automáticamente a menos que se cancele antes de la fecha de renovación. La cuenta será cargada por el período de renovación (mes/trimestre/año) sólo en la fecha de renovación.
\n
\nPuedes administrar y cancelar las suscripciones accediendo a los ajustes de AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Evita pasar por aceras o veredas</string>
<string name="routing_attr_avoid_footways_name">Evitar aceras</string>
</resources>

View file

@ -271,7 +271,7 @@
<string name="empty_route_calculated">Arvutatud teekond on tühi.</string>
<string name="use_online_routing_descr">Kasuta internetti teekonna arvutamiseks.</string>
<string name="use_fast_recalculation">Tark teekonna arvutamine</string>
<string name="use_fast_recalculation_desc">Pikemate vahemaade korral arvuta uuesti ainult teekonna algusosa.</string>
<string name="use_fast_recalculation_desc">Arvuta uuesti ainult teekonna algusosa. Seda võid kasutada pikemate vahemaade korral.</string>
<string name="simulate_your_location_descr">Simuleeri arvutatud või salvestatud GPX teekonda.</string>
<string name="hillshade_layer_disabled">Künkavarjutuse kiht keelatud</string>
<string name="rendering_attr_horseRoutes_name">Ratsutamisteed</string>
@ -3764,4 +3764,14 @@
<string name="sort_name_ascending">Nimi: A Z</string>
<string name="screen_timeout">Ekraani väljalülitamine</string>
<string name="app_mode_wheelchair_forward">Ratastool edasi</string>
<string name="routing_attr_avoid_footways_description">Väldi jalgteid</string>
<string name="routing_attr_avoid_footways_name">Väldi jalgteid</string>
<string name="contour_lines_thanks">Täname „Kõrgusjoonte“ ostu eest</string>
<string name="osm_live_payment_subscription_management_hw">Ostukinnituse saabumisel arveldame tellimuse eest sinu AppGallery konto alusel.
\n
\nKui sa ei tühista tellimust enne uue perioodi algust, siis tellimus pikeneb automaatselt ning arveldame järgmise ajavahemiku eest (kuu/kvartal/aasta) selle alguses.
\n
\nTellimust saad hallata ja tühistada AppGallery seadistustest.</string>
<string name="osm_live_payment_desc_hw">Arveldame tellimuse eest valitud ajavahemiku alusel. Seda saad sa vabalt valitud ajal tühistada AppGallery\'s.</string>
<string name="use_complex_routing">Keeruka teekonna koostamine</string>
</resources>

View file

@ -2063,7 +2063,7 @@
<string name="poi_dialog_reopen">بازگشایی</string>
<string name="get_plugin">دریافت</string>
<string name="use_fast_recalculation">محاسبهٔ مجدد هوشمند</string>
<string name="use_fast_recalculation_desc">برای سفرهای طولانی فقط بخش ابتدایی مسیر را مجدداً محاسبه می‌کند.</string>
<string name="use_fast_recalculation_desc">فقط بخش ابتدایی مسیر را مجدداً محاسبه می‌کند. برای سفرهای طولانی مفید است.</string>
<string name="do_you_like_osmand">آیا از OsmAnd راضی هستید؟</string>
<string name="we_really_care_about_your_opinion">دیدگاه و بازخورد شما ارزشمند است.</string>
<string name="rate_this_app">به این برنامه امتیاز بدهید</string>
@ -3933,4 +3933,13 @@
<string name="app_mode_motor_scooter">اسکوتر موتوری</string>
<string name="app_mode_wheelchair_forward">ویلچر رو به جلو</string>
<string name="threshold_distance">فاصله آستانه</string>
<string name="start_finish_icons">نمادهای ابتدا/انتها</string>
<string name="routing_attr_avoid_footways_name">راه‌های پیاده</string>
<string name="routing_attr_avoid_footways_description">از راه‌های پیاده پرهیز می‌کند</string>
<string name="development">توسعه</string>
<string name="use_live_public_transport">دادهٔ OsmAnd Live</string>
<string name="use_live_routing">دادهٔ OsmAnd Live</string>
<string name="complex_routing_descr">مسیریابی دومرحله‌ای برای ناوبری خودرویی.</string>
<string name="use_complex_routing">مسیریابی پیچیده</string>
<string name="use_native_pt_desc">برای مسیریابی حمل‌ونقل عمومی از محاسبات جاوا (امن) استفاده می‌کند</string>
</resources>

View file

@ -1532,7 +1532,7 @@
<string name="routing_attr_height_name">Limite de hauteur</string>
<string name="routing_attr_height_description">Précisez la hauteur du véhicule à respecter sur les routes.</string>
<string name="use_fast_recalculation">Recalcule intelligent de l\'itinéraire</string>
<string name="use_fast_recalculation_desc">Pour les longs trajets, recalculer uniquement le début de l\'itinéraire</string>
<string name="use_fast_recalculation_desc">Recalculer uniquement le début de l\'itinéraire (utile pour les longs trajets).</string>
<string name="shared_string_logoff">Se déconnecter</string>
<string name="rendering_value_disabled_name">Désactivé</string>
<string name="rendering_value_walkingRoutesOSMC_name">Couleur de l\'itinéraire basée sur les symboles de randonnée OSMC</string>
@ -3885,4 +3885,10 @@
<string name="sort_name_ascending">Nom : A Z</string>
<string name="start_finish_icons">Icônes de départ / arrivée</string>
<string name="contour_lines_thanks">Merci pour votre achat de \'Courbes de niveaux\'</string>
<string name="osm_live_payment_desc_hw">Abonnement facturé pour chaque période sélectionnée. Annulation possible à tout moment sur AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Éviter les trottoirs</string>
<string name="routing_attr_avoid_footways_name">Éviter les trottoirs</string>
<string name="development">Développement</string>
<string name="use_live_public_transport">OsmAnd Live data</string>
<string name="use_live_routing">OsmAnd Live data</string>
</resources>

View file

@ -3837,4 +3837,5 @@
<string name="poi_recycling_small_electrical_appliances">Pequenos aparellos eléctricos</string>
<string name="poi_departures_board">Taboleiro de saídas</string>
<string name="poi_drinking_water_refill">Recarga de auga potábel</string>
<string name="poi_fuel_lng">GNL</string>
</resources>

View file

@ -1061,7 +1061,7 @@
<string name="shared_string_share">Compartir</string>
<string name="share_fav_subject">Favoritos compartidos mediante OsmAnd</string>
<string name="error_occurred_loading_gpx">Non foi posíbel cargar o GPX.</string>
<string name="send_report">Send report</string>
<string name="send_report">Enviar denuncia</string>
<string name="none_region_found">Non foi posíbel atopar datos para as rexións no cartón de memoria.</string>
<string name="poi_namefinder_query_empty">Escribir para atopar un PDI</string>
<string name="any_poi">Calquera</string>
@ -1554,7 +1554,7 @@ Lon %2$s</string>
<string name="shared_string_release">Publicado</string>
<string name="plugin_install_needs_network">Precisas estar conectado para instalar este plugin.</string>
<string name="get_plugin">Obter</string>
<string name="use_fast_recalculation_desc">Nas viaxes longas, recalcula só o anaco inicial da rota.</string>
<string name="use_fast_recalculation_desc">Recalcular só a parte inicial da ruta para viaxes longas.</string>
<string name="do_you_like_osmand">Gosta do OsmAnd?</string>
<string name="we_really_care_about_your_opinion">A túa opinión e comentarios son valorados.</string>
<string name="rate_this_app">Avalía esta aplicación</string>
@ -3454,7 +3454,7 @@ Lon %2$s</string>
<string name="app_mode_osm">OSM</string>
<string name="select_nav_icon_descr">A icona amósase mentres se navega ou se move pola pantalla.</string>
<string name="select_map_icon_descr">A icona amósase en asueto.</string>
<string name="logcat_buffer_descr">Verifica e comparte os rexistros detallados da aplicación</string>
<string name="logcat_buffer_descr">Verifica e comparte rexistros detallados da aplicación</string>
<string name="search_offline_geo_error">Non foi posíbel analizar a intención xeográfica \'%s\'.</string>
<string name="permission_is_required">Precísase permiso para empregar esta opción.</string>
<string name="monitoring_min_speed_descr">Este é un filtro de corte de baixa velocidade para non gravar puntos por baixo dunha determinada velocidade. Isto pode facer que as pistas gravadas parezan máis suaves cando se amosan no mapa.</string>
@ -3928,4 +3928,21 @@ Lon %2$s</string>
<string name="sort_last_modified">Última modificación</string>
<string name="sort_name_descending">Nome: Z A</string>
<string name="sort_name_ascending">Nome: A Z</string>
<string name="start_finish_icons">Iconas de comezo/final</string>
<string name="contour_lines_thanks">Grazas por mercar \'Curvas de nivel\'</string>
<string name="osm_live_payment_desc_hw">Subscrición cobrada por período escollido. Cancélaa na AppGallery en calquera intre.</string>
<string name="osm_live_payment_subscription_management_hw">O pagamento será cargado na túa conta da AppGallery no mesmo intre da confirmación da compra.
\n
\nA subscrición é renovada de xeito automático a menos que sexa cancelada antes da data de renovación. A túa conta será cargada polo período de renovación (mes/trimestre/ano) só na data de renovación.
\n
\nPodes xestionar e cancelar as túas subscricións indo ós axustes da AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Evitar sendas peonís, camiños e beirarrúas</string>
<string name="routing_attr_avoid_footways_name">Evitar sendas peonís</string>
<string name="development">Desenvolvemento</string>
<string name="use_live_public_transport">Datos do OsmAnd Live</string>
<string name="use_live_routing">Datos do OsmAnd Live</string>
<string name="use_complex_routing">Enrutamento complexo</string>
<string name="complex_routing_descr">Enrutamento de dúas fases para a navegación de automóbil</string>
<string name="use_native_pt">Desenvolvemento do transporte público nativo</string>
<string name="use_native_pt_desc">Activar cálculo de enrutamento de transporte público do Java (seguro)</string>
</resources>

View file

@ -1534,7 +1534,7 @@
<string name="routing_attr_height_name">Magasságkorlátozás</string>
<string name="routing_attr_height_description">Adja meg az útvonalakon a járművekre vonatkozó magasságkorlátozást.</string>
<string name="use_fast_recalculation">Intelligens útvonal újraszámítás</string>
<string name="use_fast_recalculation_desc">Hosszú utaknál csak az útvonal kezdeti részének újraszámítása.</string>
<string name="use_fast_recalculation_desc">Csak az útvonal kezdeti részét számítja újra. Hosszú utakhoz használható.</string>
<string name="shared_string_logoff">Naplózás ki</string>
<string name="rendering_value_disabled_name">Letiltva</string>
<string name="rendering_value_walkingRoutesScopeOSMC_name">Színezés hálózathoz tartozás szerint</string>
@ -3898,4 +3898,19 @@
<string name="sort_name_ascending">Név: AZ</string>
<string name="start_finish_icons">Kiindulás/érkezés ikonjai</string>
<string name="contour_lines_thanks">Köszönjük, hogy megvásárolta a szintvonalbővítményt (Contour lines)</string>
<string name="osm_live_payment_desc_hw">Az előfizetés díja a kiválasztott időszakonként lesz kiszámítva. Bármikor törölheti az AppGallery webhelyen.</string>
<string name="osm_live_payment_subscription_management_hw">A fizetést a vásárlás visszaigazolásakor az AppGallery számlájára terheljük.
\n
\nAz előfizetés automatikusan megújul, kivéve, ha azt a megújítási dátum előtt lemondják. A megújítási időszakra (hónap / 3 hónap / év) a számláját csak a megújítás napján terheljük meg.
\n
\nAz előfizetéseket az AppGallery beállításai között kezelheti és törölheti.</string>
<string name="routing_attr_avoid_footways_description">Gyalogutak elkerülése</string>
<string name="routing_attr_avoid_footways_name">Gyalogutak elkerülése</string>
<string name="development">Fejlesztés</string>
<string name="use_live_public_transport">OsmAnd Live adatok</string>
<string name="use_live_routing">OsmAnd Live adatok</string>
<string name="use_complex_routing">Összetett útvonaltervezés</string>
<string name="complex_routing_descr">Kétszakaszos útvonaltervezés autós navigációhoz.</string>
<string name="use_native_pt">Natív tömegközlekedési fejlesztés</string>
<string name="use_native_pt_desc">Váltás Java (biztonságos) tömegközlekedési útvonaltervezésre</string>
</resources>

View file

@ -3911,4 +3911,12 @@
<string name="sort_name_ascending">שם: א ת</string>
<string name="start_finish_icons">סמלי התחלה/סיום</string>
<string name="contour_lines_thanks">תודה לך על רכישת ‚קווי מתאר’</string>
<string name="routing_attr_avoid_footways_description">הימנעות משבילי הולכי רגל</string>
<string name="routing_attr_avoid_footways_name">הימנעות משבילי הולכי רגל</string>
<string name="osm_live_payment_desc_hw">המינוי חויב לתקופה הנבחרת. ניתן לבטל דרך ה־AppGallery בכל עת.</string>
<string name="osm_live_payment_subscription_management_hw">התשלום יחויב דרך חשבון ה־AppGallery שלך עם אישור הרכישה.
\n
\nהמינוי מתחדש אוטומטי אלא אם כן בוטל בטרם תאריך החידוש. החשבון שלך יחויב על תקופת החידוש (חודש/שלושה חודשים/שנה) רק בתאריך החידוש.
\n
\nניתן לנהל ולבטל את המינויים שלך דרך ההגדרות ב־AppGallery שלך.</string>
</resources>

View file

@ -1618,4 +1618,10 @@
<string name="poi_direction_clockwise">Retning: med urviseren</string>
<string name="poi_direction_nnw">Retning: nord-nordvest</string>
<string name="poi_direction_nw">Retning: nordvest</string>
<string name="poi_drinking_water_refill">Drikkevannspåfylling</string>
<string name="poi_traffic_signals_arrow">Pil</string>
<string name="poi_traffic_signals_vibration">Vibrasjon</string>
<string name="poi_video_telephone">Video</string>
<string name="poi_volcano_status">Status</string>
<string name="poi_volcano_type">Type</string>
</resources>

View file

@ -3672,11 +3672,11 @@
<string name="use_volume_buttons_as_zoom">Lydstyrkeknapper til forstørring</string>
<string name="search_download_wikipedia_maps">Last ned Wikipedia-kart</string>
<string name="accessibility_mode_disabled">Tilgjengelighetsmodus er slått av i Android-systemet.</string>
<string name="listed_exist"/>
<string name="listed_exist">Angitt %1$s finnes allerede i OsmAnd.</string>
<string name="turn_screen_on_navigation_instructions">Navigasjonsinstruks</string>
<string name="speed_cameras_restart_descr"/>
<string name="speed_cameras_restart_descr">Start opp programmet igjen for å slette all fotoboksdata.</string>
<string name="shared_string_uninstall_and_restart">Avinstaller og start på nytt</string>
<string name="quick_action_remove_next_destination_descr"/>
<string name="quick_action_remove_next_destination_descr">Nåværende målpunkt på ruten vil slettes. Hvis det er målet, vil navigasjonen stoppe.</string>
<string name="app_mode_wheelchair">Rullestol</string>
<string name="app_mode_go_cart">Gokart</string>
<string name="plan_a_route">Planlegg en rute</string>
@ -3758,4 +3758,107 @@
<string name="number_of_gpx_files_selected_pattern">%s sporfiler valgt</string>
<string name="gpx_monitoring_stop">Sett turopptak på pause</string>
<string name="gpx_monitoring_start">Gjenoppta turopptak</string>
<string name="pass_whole_track_descr">Punkt i sporet å navigere</string>
<string name="monitoring_min_speed_descr_remark">Merk: Hastighet &gt; 0-sjekk: De fleste GPS-brikkesett rapporterer en hastighetsverdi kun hvis algoritmen fastslår at du er i bevegelse, og ingen hvis du ikke er det. Derav vil bruk av &gt; 0-innstillingen i dette filteret bruke bevegelsesoppdagelsen fra GPS-brikkesettet. Selv om det ikke filtreres har ved opptak, har man fremdeles denne funksjonen i GPX-analyse for å fastslå korrigert distanse, altså verdien som vises i feltet er distanse tatt opp i bevegelse.</string>
<string name="monitoring_min_speed_descr_recommendation">Anbefaling: Prøv å bruke bevegelsesoppdagelse via avstandsfilteret for minimumsmåling (B) først, det kan gi bedre resultater, og du vil ikke gå glipp av data. Hvis dine spor fremdeles er fulle av støy ved lave hastigheter, kan du prøve andre verdier enn null her. Merk at noen målinger ikke rapporterer hastighetsverdi i det hele tatt (som nettverksbaserte metoder), og i sådant fall vil du ikke ta opp noe.</string>
<string name="monitoring_min_speed_descr_side_effect">Bieffekt: Sporet ditt vil mangle alle deler der minimumshastigheten ikke er oppfylt (f.eks. når du dytter sykkelen din opp en bratt bakke). Pauser går også tapt siden det ikke er noen bevegelse. Dette forringer også analyse eller etterbehandling, som å forsøke å anslå total turlengde, tid i bevegelse, eller gjennomsnittshastighet.</string>
<string name="monitoring_min_speed_descr">Dette lavhastighetsfilteret tar ikke opp punkter under en gitt hastighet. Dette kan gjøre innspilte spor jevnere når de vises på kartet.</string>
<string name="monitoring_min_accuracy_descr">Dette tar opp punkter målt med minimal nøyaktighetsindikasjon (i meter/fot, som det rapporteres av Android av brikkesettet ditt). Nøyaktighet er nærheten av målinger til sann posisjon, og er ikke direkte relatert til presisjon, som er en spredning av gjentatte målinger.</string>
<string name="monitoring_min_accuracy_descr_side_effect">Bivirkning: Som et resultat av filtrering etter nøyaktighet, kan noen punkter mangle helt, f.eks. under broer, under trær, mellom høye bygninger, eller under gitte værforhold.</string>
<string name="monitoring_min_accuracy_descr_recommendation">Anbefaling: Det er vanskelig å forutsi hva som blir tatt opp og ikke, det kan være best å skru dette filteret av.</string>
<string name="monitoring_min_accuracy_descr_remark">Merk: Hvis GPS har vært av rett før et opptak, kan første punkt ha dårligere nøyaktighet, slik at man fra kodehold kan la det gå et sekund før et punkt blir tatt opp (eller man tar opp det beste av 3 punkter), men dette er ikke implementert enda.</string>
<string name="monitoring_min_distance_descr">Filteret unngår dupliserte punkter fra å bli tatt opp der det er for lite bevegelse. Lager et penere resultat uten bruk av etterbehandling.</string>
<string name="monitoring_min_distance_descr_side_effect">Bivirkning: Pauseperioder tas ikke opp i det hele tatt, eller kun med ett punkt. Små (faktiske) bevegelser (f.eks. til siden, for å markere en mulig avkjørsel i turen din) kan bli filtrert ut. Din fil inneholder mindre info for etterbehandling, og har dårligere data ved å filtrere ut åpenbart overflødige punkter ved opptak, mens arte-fakter potensielt blir beholdt som følge av dårlige forhold eller GPS-brikkesetteffekter.</string>
<string name="monitoring_min_distance_descr_recommendation">Anbefaling: En innstilling på 5 meter kan fungere for deg hvis du ikke vil fange finmaskede detaljer, og ikke ønsker å ta opp data mens du har pause.</string>
<string name="live_monitoring_adress_descr">Angi nettadressen med parametersyntaks: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
<string name="multimedia_rec_split_title">Opptaksoppdeling</string>
<string name="search_offline_geo_error">Kunne ikke tolke geo-intensjon «%s».</string>
<string name="osm_authorization_success">Autorisert</string>
<string name="use_system_screen_timeout_promo">Avskrudd som forvalg: Skjermen vil ikke slås av så lenge OsmAnd kjører i forgrunnen.
\n
\nHvis påskrudd vil OsmAnd bruke systemets innstilling for skjermtidsavbrudd.</string>
<string name="terrain_empty_state_text">Skru på for å vise relieffskygge eller skråningskart. Du kan lese mer om disse karttypene på siden vår.</string>
<string name="reset_to_default_category_button_promo">«Tilbakestill til forvalg» gjenoppretter sorteringsrekkefølgen til installasjonsforvalg.</string>
<string name="hillshade_description">Relieffskyggekart som bruker mørke skygger for å vise skråninger, topper og lavland.</string>
<string name="recalculate_route_distance_promo">Ruten vil regnes ut igjen hvis avstanden fra ruten til nåværende posisjon er mer enn valgt verdi.</string>
<string name="osm_live_payment_subscription_management">Betaling vil bli belastet din Google Play-konto ved bekreftelse av kjøp.
\n
\n Abonnement fornyes automatisk med mindre det avbrytes før fornyelsesdatoen. Din konto vil bli belastet for fornyelsesperioden (måned/tre måneder/år) kun på fornyelsesdatoen.
\n
\n Du kan håndtere og avbryte dine abonnementer ved å gå til dine Google Play-innstillinger.</string>
<string name="turn_screen_on_descr">Angi når skjermen skal vekkes opp (forsikre deg om at OsmAnd er i forgrunnen når enheten låses):</string>
<string name="map_source_zoom_levels">Sett minste og største forstørrelsesnivå å vise eller laste inn på nettbasert kart.</string>
<string name="map_source_zoom_levels_descr">Har innvirkning på om skjermen skal brukes som kart eller overlag/underlag.
\n
\n%1$s: Kartet er begrenset til valgt forstørrelsesrekkevidde.
\n
\n%2$s er nivåene de opprinnelige flisene vil være synlige, oppskalering eller nedskalering finner sted utenfor disse verdiene.</string>
<string name="app_mode_inline_skates">Rulleskøyter</string>
<string name="speed_cameras_legal_descr">I noen land og områder, er bruk av fotoboksvarsling forbudt ved lov.
\n
\nDu må vurdere dette selv i henhold til lovene i ditt land.
\n
\nVelg %1$s og du vil motta varsler og advarsler om fotobokser.
\n
\nVelg %1$s. All data som har med fotobokser å gjøre, varsler, merknader og interessepunkter vil bli slettet til OsmAnd reinstalleres helt og holdent.</string>
<string name="clear_tiles_warning">Å utføre disse endringene vil tømme hurtiglagret data for denne fliskilden.</string>
<string name="plugin_wikipedia_description">Hent info om interessepunkter fra Wikipedia. Det er din frakoblede lommeguide - bare skru på Wikipedia-programtillegget og få artikler om objekter rundt deg.</string>
<string name="track_coloring_solid">Utfylt</string>
<string name="osm_live_payment_subscription_management_hw">Betaling vil bli belastet din programgalleri-konto ved bekreftelse av kjøp.
\n
\nAbonnementet fornyes automatisk med mindre det avbrytes før fornyelsesdatoen. Din konto bil bli belastet for fornyelse for hver fornyelsesperiode (måned/tre måneder/år) kun på fornyelsesdatoen.
\n
\nDu kan håndtere og avbryte ditt abonnement ved å gå gjennom dine programgalleri-innstillinger.</string>
<string name="gpx_parse_error">OsmAnd-GPX er feilformatert, kontakt brukerstøtte for videre etterforskning.</string>
<string name="system_screen_timeout_descr">Skrur av skjermen i henhold til systemets skjermtidsavbrudd.</string>
<string name="lenght_limit_description">Angi lengden på ditt kjøretøy, noen rutebegrensninger kan gjelde for lange kjøretøy.</string>
<string name="turn_screen_on_power_button_disabled">Avskrudd. Krever «Behold skjerm på» under «Tidsavbrudd etter oppvåkning».</string>
<string name="turn_screen_on_power_button_descr">Å trykke på enhetens på-knapp vil skru skjermen på med OsmAnd på toppen av låseskjermen.</string>
<string name="pseudo_mercator_projection">Pseudo-Mercatorprojeksjon</string>
<string name="keep_active">Behold på</string>
<string name="speed_cameras_alert">Fotoboksvarsling er forbudt ved lov i noen land.</string>
<string name="quick_action_showhide_mapillary_descr">Bryter for å vise eller skjule Mapillary-lag på kartet.</string>
<string name="speed_cameras_removed_descr">Denne enheten har ikke fotobokser.</string>
<string name="in_case_of_reverse_direction">I tilfelle motsatt retning</string>
<string name="simplified_track_description">Kun rutelinjen vil lagres, rutepunktene vil slettes.</string>
<string name="context_menu_item_add_waypoint">Legg til spor-rutepunkt</string>
<string name="quick_action_add_gpx">Legg til spor-rutepunkt</string>
<string name="complex_routing_descr">To-delt ruting for bilkjøring.</string>
<string name="osm_live_payment_desc_hw">Abonnement påløper per valgte periode. Avbryt det når som helst fra programgalleriet.</string>
<string name="attach_to_the_roads">Følg veier</string>
<string name="monitoring_min_distance">Minimumsforskyvning</string>
<string name="radius_ruler_item">Radiuspasser</string>
<string name="turn_screen_on_navigation_instructions_descr">Hver navigasjonsinstruksjon skrur skjermen på.</string>
<string name="turn_screen_on_wake_time_descr">Velg skjermtidsavbrudd etter oppvåkning. («%1$s» skrur av tidsavbrudd.)</string>
<string name="keep_screen_off">Levn skjermen av</string>
<string name="expire_time_descr">Hurtiglagrede filer vil bli lastet ned igjen etter et gitt antall minutter. La dette feltet stå tomt for å aldri gjenoppfriske flis for denne kilden.
\n
\nÉn dag er 1440 minutter.
\nÉn uke er 10080 minutter.
\nÉn måned er 43829 minutter.</string>
<string name="screen_timeout_descr">Hvis «%1$s» er på, vil aktivitetstiden avhenge av den.</string>
<string name="routing_attr_length_description">Angi kjøretøylengde som tillates på rutene.</string>
<string name="routing_attr_length_name">Lengdebegrensning</string>
<string name="plan_route_exit_dialog_descr">Er du sikker på at du ønsker å forkaste alle endringer i planlagt rute ved å lukke den\?</string>
<string name="navigate_to_track_descr">Naviger fra min posisjon til sporet</string>
<string name="use_native_pt">Innebygd utvikling for offentlig transport</string>
<string name="use_native_pt_desc">Bytt til Java (trykk) ruteberegning for offentlig transport</string>
<string name="contour_lines_thanks">Takk for at du kjøpte «Koter»</string>
<string name="use_complex_routing">Kompleks ruting</string>
<string name="routing_attr_avoid_footways_name">Unngå turstier</string>
<string name="routing_attr_avoid_footways_description">Unngå turstier</string>
<string name="recalc_angle_dialog_descr">Ekstra rett segment mellom min posisjon og utregnet rute vil bli vist til den er regnet ut på ny</string>
<string name="checking_for_duplicate_description">OsmAnd sjekker %1$d for duplikater med eksisterende elementer i programmet.
\n
\nDet kan ta sin tid.</string>
<string name="export_import_quick_actions_with_profiles_promo">Du kan eksportere eller importere hurtighandlinger med programprofiler.</string>
<string name="delete_all_actions_message_q">Er du sikker på at du vil slette %d hurtighandlinger for godt\?</string>
<string name="screen_timeout">Skjermtidsavbrudd</string>
<string name="default_screen_timeout">Forvalgt skjermtidsavbrudd</string>
<string name="street_level_imagery">Gatenivåbildedata</string>
<string name="plan_route_trim_before">Beskjær før</string>
<string name="plan_route_trim_after">Beskjær før</string>
<string name="development">Utvikling</string>
<string name="use_live_public_transport">OsmAnd-sanntidsdata</string>
<string name="use_live_routing">OsmAnd-sanntidsdata</string>
</resources>

View file

@ -1538,7 +1538,7 @@
<string name="routing_attr_height_name">Limite de altura</string>
<string name="routing_attr_height_description">Especifique a altura permitida do veículo nas rotas.</string>
<string name="use_fast_recalculation">Recálculo de rota inteligente</string>
<string name="use_fast_recalculation_desc">Recalcular apenas a parte inicial da rota para viagens longas.</string>
<string name="use_fast_recalculation_desc">Recalcular apenas a parte inicial da rota. Pode ser usado para viagens longas.</string>
<string name="rendering_value_disabled_name">Desativado</string>
<string name="rendering_value_walkingRoutesScopeOSMC_name">Cor por afiliação de rede</string>
<string name="rendering_value_walkingRoutesOSMC_name">Cor por símbolo de caminhada OSMC</string>
@ -3901,4 +3901,19 @@
<string name="sort_name_ascending">Nome: A Z</string>
<string name="start_finish_icons">Ícones de início/término</string>
<string name="contour_lines_thanks">Obrigado por adquirir \'curvas de nível\'</string>
<string name="osm_live_payment_desc_hw">Assinatura cobrada por período selecionado. Cancele no AppGallery a qualquer momento.</string>
<string name="osm_live_payment_subscription_management_hw">O pagamento será cobrado em sua conta AppGallery na confirmação da compra.
\n
\nA assinatura é renovada automaticamente, a menos que seja cancelada antes da data de renovação. Sua conta será cobrada pelo período de renovação (mês/três meses/ano) apenas na data de renovação.
\n
\nVocê pode gerenciar e cancelar suas assinaturas acessando as configurações do AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Evite passarelas</string>
<string name="routing_attr_avoid_footways_name">Evite passarelas</string>
<string name="development">Desenvolvimento</string>
<string name="use_live_public_transport">Dados do OsmAnd Live</string>
<string name="use_live_routing">Dados do OsmAnd Live</string>
<string name="use_complex_routing">Roteamento complexo</string>
<string name="complex_routing_descr">Roteamento de duas fases para navegação automotiva.</string>
<string name="use_native_pt">Desenvolvimento de transporte público nativo</string>
<string name="use_native_pt_desc">Mudar para cálculo de roteamento de transporte público em Java (seguro)</string>
</resources>

View file

@ -3908,4 +3908,12 @@
<string name="sort_name_ascending">Nome: A Z</string>
<string name="start_finish_icons">Ícones de início/fim</string>
<string name="contour_lines_thanks">Obrigado por comprar \'Curvas de nível\'</string>
<string name="osm_live_payment_desc_hw">Assinatura cobrada por período selecionado. Cancele-a na AppGallery a qualquer momento.</string>
<string name="osm_live_payment_subscription_management_hw">O pagamento será debitado na sua conta AppGallery no momento da confirmação da compra.
\n
\nA assinatura é renovada automaticamente, a menos que seja cancelada antes da data de renovação. A sua conta será cobrada pelo período de renovação (mês/três meses/ano) apenas na data de renovação.
\n
\nPode gerir e cancelar as suas subscrições a ir às definições da sua AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Evitar passeios</string>
<string name="routing_attr_avoid_footways_name">Evitar passeios</string>
</resources>

View file

@ -73,7 +73,7 @@
<string name="select_postcode">Поиск почтового индекса</string>
<string name="quick_action_take_audio_note">Запись аудио⁣</string>
<string name="quick_action_take_video_note">Записать видео</string>
<string name="quick_action_take_photo_note">Фотозаметка</string>
<string name="quick_action_take_photo_note">Сделать фото</string>
<string name="quick_action_add_osm_bug">OSM-заметка</string>
<string name="parking_options">Функции парковки</string>
<string name="full_version_thanks">Благодарим вас за покупку платной версии OsmAnd.</string>
@ -531,10 +531,10 @@
<string name="overlay_transparency">Прозрачность наложения</string>
<string name="map_transparency_descr">Отрегулируйте прозрачность основной карты.</string>
<string name="map_transparency">Прозрачность основной карты</string>
<string name="layer_underlay">Карта подложки</string>
<string name="layer_underlay">Карта подложки</string>
<string name="map_underlay">Карта подложки</string>
<string name="map_underlay_descr">Выберите карту подложки</string>
<string name="layer_overlay">Карта наложения</string>
<string name="layer_overlay">Карта наложения</string>
<string name="map_overlay">Карта наложения</string>
<string name="map_overlay_descr">Выберите слой наложения поверх основной карты</string>
<string name="tile_source_already_installed">Карта уже установлена, настройки будут обновлены.</string>
@ -689,7 +689,7 @@
<string name="layer_route">Маршрут</string>
<string name="layer_osm_bugs">OSM-заметки (онлайн)</string>
<string name="layer_poi">POI…</string>
<string name="layer_map">Источник карты</string>
<string name="layer_map">Источник карты</string>
<string name="menu_layers">Слои</string>
<string name="context_menu_item_search_poi">Поиск POI</string>
<string name="use_trackball_descr">Использовать трекбол для перемещения по карте.</string>
@ -1177,9 +1177,9 @@
<string name="poi_filter_restaurants">Рестораны</string>
<string name="poi_filter_sightseeing">Достопримечательности</string>
<string name="context_menu_item_last_intermediate_point">Последний промежуточный пункт</string>
<string name="context_menu_item_first_intermediate_point">Сделать начальной остановкой</string>
<string name="add_as_last_destination_point">Сделать последней остановкой</string>
<string name="add_as_first_destination_point">Сделать начальной остановкой</string>
<string name="context_menu_item_first_intermediate_point">Первый промежуточный пункт</string>
<string name="add_as_last_destination_point">Последний промежуточный пункт</string>
<string name="add_as_first_destination_point">Первый промежуточный пункт</string>
<string name="replace_destination_point">Заменить пункт назначения</string>
<string name="new_destination_point_dialog">Пункт назначения уже задан</string>
<string name="target_point">Пункт %1$s</string>
@ -1819,7 +1819,7 @@
<string name="routing_attr_height_name">Предельная высота</string>
<string name="routing_attr_height_description">Укажите высоту транспортного средства для учёта при построении маршрута.</string>
<string name="use_fast_recalculation">Умный пересчёт маршрута</string>
<string name="use_fast_recalculation_desc">Для больших маршрутов пересчитывать только начало.</string>
<string name="use_fast_recalculation_desc">Пересчитывается только начальная часть маршрута. Может использоваться для дальних поездок.</string>
<string name="osm_edit_context_menu_delete">Удалить правки OSM</string>
<string name="rendering_value_disabled_name">Выключено</string>
<string name="rendering_value_walkingRoutesScopeOSMC_name">Раскраска по сетевой принадлежности</string>
@ -2668,8 +2668,8 @@
<string name="copy_location_name">Копировать местоположение/название POI</string>
<string name="toast_empty_name_error">Место без названия</string>
<string name="shared_string_current">Текущий</string>
<string name="last_intermediate_dest_description">Добавить последним промежуточным пунктом</string>
<string name="first_intermediate_dest_description">Добавить первым промежуточным пунктом</string>
<string name="last_intermediate_dest_description">Добавить последнюю остановку на маршруте</string>
<string name="first_intermediate_dest_description">Добавить первую остановку на маршруте</string>
<string name="subsequent_dest_description">Ранее выбранный пункт назначения станет последним промежуточным пунктом</string>
<string name="show_closed_notes">Показать закрытые заметки</string>
<string name="switch_osm_notes_visibility_desc">Показать/скрыть заметки OSM на карте.</string>
@ -3580,8 +3580,7 @@
<string name="monitoring_min_speed_descr_remark">Примечание: проверка скорости &gt; 0: большинство модулей GPS сообщают значение скорости только в том случае, если алгоритм определяет, что вы движетесь, и ничего, если вы не перемещаетесь. Следовательно, использование параметра &gt; 0 в этом фильтре в некотором смысле приводит к обнаружению факта перемещения модуля GPS. Но даже если мы не производим данную фильтрацию во время записи, то всё равно эта функция используется при анализе GPX для определения скорректированного расстояния, то есть значение, отображаемое в этом поле, является расстоянием, записанным во время движения.</string>
<string name="multimedia_rec_split_title">Разделение записи</string>
<string name="live_monitoring_adress_descr">Укажите веб-адрес со следующими параметрами: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
<string name="monitoring_min_accuracy_descr">"Будут записываться только точки, отвечающие
\n в минимальной точностью (в метрах/футах —зависит от настроек системы). Точность — это близость измерений к истинному положению, и она не связана напрямую с точностью, которая представляет собой разброс повторных измерений."</string>
<string name="monitoring_min_accuracy_descr">"Будут записываться только точки, отвечающие по показателю минимальной точности (в метрах или футах — зависит от настроек системы). Точность — это близость измерений к истинному положению, и она не связана напрямую с точностью, которая представляет собой разброс повторных измерений."</string>
<string name="monitoring_min_speed_descr_recommendation">Рекомендация: попробуйте сначала воспользоваться детектором движения через фильтр минимального смещения (B), что может дать лучшие результаты и вы потеряете меньше данных. Если треки остаются шумными на низких скоростях, попробуйте использовать ненулевые значения. Обратите внимание, что некоторые измерения могут вообще не указывать значения скорости (некоторые сетевые методы), и в этом случае ничего не будет записываться.</string>
<string name="slope_description">Для визуализации крутизны рельефа используются цвета.</string>
<string name="slope_read_more">Подробнее об уклонах можно прочитать в %1$s.</string>
@ -3904,4 +3903,16 @@
<string name="sort_name_ascending">Имя: А - Я</string>
<string name="start_finish_icons">Значки старта и финиша</string>
<string name="contour_lines_thanks">Спасибо за покупку \'Контурных линий\'</string>
<string name="routing_attr_avoid_footways_description">Избегать пешеходных дорожек</string>
<string name="routing_attr_avoid_footways_name">Избегать пешеходных дорожек</string>
<string name="osm_live_payment_desc_hw">Подписка взимается за выбранный период. Отмените её в AppGallery в любое время.</string>
<string name="osm_live_payment_subscription_management_hw">Оплата будет снята с вашей учетной записи AppGallery при подтверждении покупки.
\n
\nПодписка продлевается автоматически, если она не будет отменена до даты продления. С вашего счета будет взиматься плата за период продления (месяц/три месяца/год) только в дату продления.
\n
\nВы можете управлять своими подписками и отменять их, перейдя в настройки AppGallery.</string>
<string name="use_live_public_transport">Данные OsmAnd Live</string>
<string name="use_live_routing">Данные OsmAnd Live</string>
<string name="use_complex_routing">Комплексная маршрутизация</string>
<string name="complex_routing_descr">Двухфазная маршрутизация для автомобильной навигации.</string>
</resources>

View file

@ -3887,7 +3887,7 @@
<string name="shared_string_redo">Torra a fàghere</string>
<string name="release_3_8">• Funtzionalidade de pranificatione de un\'àndala agiornada: permitit de impreare castas diferentes de navigatzione pro segmentu e s\'inclusione de rastas
\n
\n • New Appearance menu for tracks: select color, thickness, display direction arrows, start/finish icons
\n • Menù de Aparèntzia nou pro sas rastas: ischerta su colore, grussària, visulaizatzione de sas fritzas de diretzione, iconas de incumintzu/fine
\n
\n • Visibilidade megiorada de sos nodos pro sas bitzicletas.
\n
@ -3905,4 +3905,12 @@
<string name="sort_name_ascending">Nùmene: A Z</string>
<string name="start_finish_icons">Iconas de incumintzu/fine</string>
<string name="contour_lines_thanks">Gràtzias pro àere comporadu \'Curvas de livellu\'</string>
<string name="osm_live_payment_desc_hw">Costu periòdicu de s\'abbonamentu. Lu podes anullare in AppGallery cando boles.</string>
<string name="osm_live_payment_subscription_management_hw">Su pagamentu at a èssere addebitadu a su contu tuo de AppGallery cando sa còmpora at a èssere cunfirmada.
\n
\nS\'abbonamentu si rinnovat a sa sola automaticamente, francu chi siat istadu annulladu in antis de sa die de su rinnovu. Su contu tuo at a bènnere addebitadu pro su perìodu de rinnovu (mese/tres meses/annu) in sa die de rinnovu ebbia.
\n
\nPodes amministrare e annullare sos abbonamentos tuos intrende in sas impostatziones de AppGallery tuas.</string>
<string name="routing_attr_avoid_footways_description">Èvita sos martzapiedis</string>
<string name="routing_attr_avoid_footways_name">Èvita sos martzapiedis</string>
</resources>

View file

@ -509,7 +509,7 @@
<string name="poi_register_office">Matričný úrad</string>
<string name="poi_pension_fund">Dôchodkový fond</string>
<string name="poi_migration">Imigračný úrad</string>
<string name="poi_tax_inspection">Daňová kontrola</string>
<string name="poi_tax_inspection">Daňový úrad</string>
<string name="poi_quarter">Štvrť</string>
<string name="poi_attraction_summer_toboggan">Suchá bobová dráha</string>
<string name="poi_attraction_swing_carousel">Kolotoč s hojdačkami</string>
@ -3652,4 +3652,5 @@
<string name="poi_covered_booth">Búdka</string>
<string name="poi_sms_no">Nie</string>
<string name="poi_sms_yes">Áno</string>
<string name="poi_taxi_office">Kancelária taxislužby</string>
</resources>

View file

@ -1537,7 +1537,7 @@
<string name="routing_attr_height_name">Výškový limit</string>
<string name="routing_attr_height_description">Zadajte výšku vozidla, ktorá musí byť povolená na cestách.</string>
<string name="use_fast_recalculation">Inteligentné prepočítanie trasy</string>
<string name="use_fast_recalculation_desc">Pri dlhých výletoch prepočítať iba začiatočný úsek trasy.</string>
<string name="use_fast_recalculation_desc">Prepočíta iba začiatočný úsek trasy. Môže byť použité pre dlhé výlety.</string>
<string name="shared_string_logoff">Odhlásiť</string>
<string name="rendering_value_disabled_name">Vypnuté</string>
<string name="rendering_value_walkingRoutesScopeOSMC_name">Zafarbenie podľa príslušnosti k sieti</string>
@ -3654,8 +3654,8 @@
<string name="lang_lmo">Lombardsky</string>
<string name="ltr_or_rtl_combine_via_slash_with_space">%1$s / %2$s</string>
<string name="osm_live_payment_subscription_management">Platba bude stiahnutá z vášho účtu Google Play po potvrdení nákupu.
\n
\n Predplatné sa automaticky obnovuje ak nie je zrušené pred dátumom jeho obnovenia. Ďalšia platba za obdobie predplatného (mesiac/štvrťrok/rok) bude stiahnutá v deň obnovenia.
\n
\n Predplatné sa automaticky obnovuje, ak nie je zrušené pred dátumom jeho obnovenia. Ďalšia platba za obdobie predplatného (mesiac/štvrťrok/rok) bude stiahnutá v deň obnovenia.
\n
\n Vaše predplatné môžete spravovať a zrušiť v nastaveniach Google Play.</string>
<string name="search_poi_types">Hľadať typy bodov záujmu</string>
@ -3906,4 +3906,19 @@
<string name="sort_name_ascending">Názov: A Z</string>
<string name="start_finish_icons">Ikony štartu/cieľa</string>
<string name="contour_lines_thanks">Ďakujeme za zakúpenie modulu \'Vrstevnice\'</string>
<string name="osm_live_payment_desc_hw">Predplatné bude spoplatnené v zvolenom intervale. Predplatné zrušte kedykoľvek na AppGallery.</string>
<string name="osm_live_payment_subscription_management_hw">Platba bude stiahnutá z vášho účtu AppGallery po potvrdení nákupu.
\n
\nPredplatné sa automaticky obnovuje, ak nie je zrušené pred dátumom jeho obnovenia. Ďalšia platba za obdobie predplatného (mesiac/štvrťrok/rok) bude stiahnutá v deň obnovenia.
\n
\n Vaše predplatné môžete spravovať a zrušiť v nastaveniach AppGallery.</string>
<string name="routing_attr_avoid_footways_description">Vyhnúť sa chodníkom pre chodcov</string>
<string name="routing_attr_avoid_footways_name">Vyhnúť sa chodníkom</string>
<string name="development">Vývoj</string>
<string name="use_live_public_transport">Údaje OsmAnd Live</string>
<string name="use_live_routing">Údaje OsmAnd Live</string>
<string name="use_complex_routing">Komplexný výpočet trasy</string>
<string name="complex_routing_descr">Dvojfázový výpočet trasy pre navigáciu auta.</string>
<string name="use_native_pt">Natívny vývoj hromadnej dopravy</string>
<string name="use_native_pt_desc">Prepnúť na výpočet trasy hromadnej dopravy v Jave (bezpečné)</string>
</resources>

View file

@ -1393,7 +1393,7 @@
<string name="plugin_install_needs_network">Bu eklentiyi yüklemek için çevrim içi olmanız gerekmektedir.</string>
<string name="get_plugin">Al</string>
<string name="use_fast_recalculation">Akıllı rota yeniden hesaplama</string>
<string name="use_fast_recalculation_desc">Uzun seyahatler için rotanın yalnızca ilk bölümünü yeniden hesapla.</string>
<string name="use_fast_recalculation_desc">Güzergahın yalnızca ilk bölümünü yeniden hesaplar. Uzun yolculuklar için kullanılabilir.</string>
<string name="do_you_like_osmand">OsmAnd\'ı Sevdinizmi?</string>
<string name="we_really_care_about_your_opinion">Fikir ve geri bildirimleriniz değerlidir.</string>
<string name="rate_this_app">Bu Uygulamayı Oyla</string>
@ -3861,4 +3861,19 @@
<string name="sort_name_ascending">İsim: A Z</string>
<string name="start_finish_icons">Başlangıç/bitiş simgeleri</string>
<string name="contour_lines_thanks">\'Eş yükselti eğrileri\'ni satın aldığınız için teşekkürler</string>
<string name="osm_live_payment_desc_hw">Abonelik seçilen dönem başına ücretlendirilir. İstediğiniz zaman AppGallery\'den iptal edin.</string>
<string name="osm_live_payment_subscription_management_hw">Ödeme, satın alma onaylandığında AppGallery hesabınızdan alınacaktır.
\n
\nYenileme tarihinden önce iptal edilmedikçe abonelik otomatik olarak yenilenir. Hesabınızdan yenileme süresi (ay/üç ay/yıl) için yalnızca yenileme tarihinde ücret alınacaktır.
\n
\n AppGallery ayarlarınıza giderek aboneliklerinizi yönetebilir ve iptal edebilirsiniz.</string>
<string name="routing_attr_avoid_footways_description">Yaya yollarından kaçın</string>
<string name="routing_attr_avoid_footways_name">Yaya yollarından kaçın</string>
<string name="development">Geliştirme</string>
<string name="use_live_public_transport">OsmAnd Live verileri</string>
<string name="use_live_routing">OsmAnd Live verileri</string>
<string name="use_complex_routing">Karmaşık yönlendirme</string>
<string name="complex_routing_descr">Araç navigasyonu için iki aşamalı yönlendirme.</string>
<string name="use_native_pt">Yerel Toplu Taşıma geliştirme</string>
<string name="use_native_pt_desc">Java (güvenli) Toplu Taşıma yönlendirme hesaplamasına geçin</string>
</resources>

View file

@ -1534,7 +1534,7 @@
<string name="routing_attr_height_name">高度限制</string>
<string name="routing_attr_height_description">指定被許可在道路上行駛的車輛高度。</string>
<string name="use_fast_recalculation">智慧路線重新計算</string>
<string name="use_fast_recalculation_desc">對於長途航行,只重算路線的初始部分</string>
<string name="use_fast_recalculation_desc">僅重新計算路線的初始部份。可用於長途旅程</string>
<string name="shared_string_logoff">登出</string>
<string name="rendering_value_disabled_name">已停用</string>
<string name="rendering_value_walkingRoutesScopeOSMC_name">依網絡從屬著色</string>
@ -3901,4 +3901,19 @@
<string name="sort_name_ascending">名稱A Z</string>
<string name="start_finish_icons">開始/結束圖示</string>
<string name="contour_lines_thanks">感謝您購買 \'Contour lines\'</string>
<string name="osm_live_payment_desc_hw">按選定週期收取訂閱費用。隨時在 AppGallery 上取消。</string>
<string name="osm_live_payment_subscription_management_hw">確認購買後將會從您的 AppGallery 帳號中付款。
\n
\n除非在續訂日期前取消否則就會自動續訂。您的帳號將只會在續訂日期收取訂閱週期一個月三個月一年的費用。
\n
\n您可以在您的 AppGallery 設定中管理與取消您的訂閱。</string>
<string name="routing_attr_avoid_footways_description">避免人行道</string>
<string name="routing_attr_avoid_footways_name">避免人行道</string>
<string name="development">開發</string>
<string name="use_live_public_transport">OsmAnd Live 資料</string>
<string name="use_live_routing">OsmAnd Live 資料</string>
<string name="use_complex_routing">複雜路線</string>
<string name="complex_routing_descr">汽車導航的兩階段路線。</string>
<string name="use_native_pt">原生公共運輸發展</string>
<string name="use_native_pt_desc">切換到 Java安全公共運輸路線計算</string>
</resources>

View file

@ -11,9 +11,21 @@
Thx - Hardy
-->
<string name="osm_edit_logout_success">Logout successful</string>
<string name="clear_osm_token">Clear OpenStreetMap OAuth token</string>
<string name="perform_oauth_authorization">Log in via OAuth</string>
<string name="perform_oauth_authorization_description">Perform an OAuth Login to use osmedit features</string>
<string name="use_native_pt_desc">Switch to Java (safe) Public Transport routing calculation</string>
<string name="use_native_pt">Native Public Transport development</string>
<string name="use_fast_recalculation_desc">Recalculates only the initial part of the route. Can be used for long trips.</string>
<string name="complex_routing_descr">Two-phase routing for car navigation.</string>
<string name="use_complex_routing">Complex routing</string>
<string name="use_live_routing">OsmAnd Live data</string>
<string name="use_live_public_transport">OsmAnd Live data</string>
<string name="development">Development</string>
<string name="routing_attr_avoid_footways_name">Avoid footways</string>
<string name="routing_attr_avoid_footways_description">Avoid footways</string>
<string name="osm_live_payment_subscription_management_hw">Payment will be charged to your AppGallery account at the confirmation of purchase.\n\nSubscription automatically renews unless it is canceled before the renewal date. Your account will be charged for renewal period(month/three month/year) only on the renewal date.\n\nYou can manage and cancel your subscriptions by going to your AppGallery settings.</string>
<string name="osm_live_payment_subscription_management_hw">Payment will be charged to your AppGallery account at the confirmation of purchase.\n\nSubscription automatically renews unless it is canceled before the renewal date. Your account will be charged for renewal period (month/three month/year) only on the renewal date.\n\nYou can manage and cancel your subscriptions by going to your AppGallery settings.</string>
<string name="osm_live_payment_desc_hw">Subscription charged per selected period. Cancel it on AppGallery at any time.</string>
<string name="contour_lines_thanks">Thank you for purchasing \'Contour lines\'</string>
<string name="start_finish_icons">Start/finish icons</string>
@ -241,7 +253,7 @@
<string name="extra_maps_menu_group">Extra maps</string>
<string name="search_poi_types_descr">Combine POI types from different categories. Tap switch to select all, tap left side to category selection.</string>
<string name="search_poi_types">Search for POI types</string>
<string name="osm_live_payment_subscription_management">Payment will be charged to your Google Play account at the confirmation of purchase.\n\n Subscription automatically renews unless it is canceled before the renewal date. Your account will be charged for renewal period(month/three month/year) only on the renewal date.\n\n You can manage and cancel your subscriptions by going to your Google Play settings.</string>
<string name="osm_live_payment_subscription_management">Payment will be charged to your Google Play account at the confirmation of purchase.\n\n Subscription automatically renews unless it is canceled before the renewal date. Your account will be charged for renewal period (month/three month/year) only on the renewal date.\n\n You can manage and cancel your subscriptions by going to your Google Play settings.</string>
<string name="ltr_or_rtl_combine_via_slash_with_space">%1$s / %2$s</string>
<string name="custom_color">Custom color</string>
<string name="lang_lmo">Lombard</string>
@ -1812,6 +1824,7 @@
<string name="lang_als">Albanian (Tosk)</string>
<string name="read_more">Read more</string>
<string name="whats_new">What\'s new in</string>
<string name="what_is_new">What\'s new</string>
<string name="rendering_attr_hideProposed_name">Proposed objects</string>
<string name="shared_string_update">Update</string>
<string name="shared_string_upload">Upload</string>
@ -3662,7 +3675,6 @@
<string name="plugin_install_needs_network">You need to be online to install this plugin.</string>
<string name="get_plugin">Get</string>
<string name="use_fast_recalculation">Smart route recalculation</string>
<string name="use_fast_recalculation_desc">For long trips, only recalculate the initial part of the route.</string>
<string name="do_you_like_osmand">Do you like OsmAnd?</string>
<string name="we_really_care_about_your_opinion">Your opinion and feedback is valued.</string>
<string name="rate_this_app">Rate this app</string>

View file

@ -25,46 +25,11 @@
android:summaryOn="@string/shared_string_enabled"
android:title="@string/safe_mode" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="pt_safe_mode"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="Native PT development" />
<PreferenceCategory
android:key="routing"
android:layout="@layout/preference_category_with_descr"
android:title="@string/routing_settings" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="disable_complex_routing"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="@string/disable_complex_routing" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="use_fast_recalculation"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="@string/use_fast_recalculation" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="enable_osmc_routing"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="@string/use_osm_live_routing" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="enable_osmc_public_transport"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="@string/use_osm_live_public_transport" />
<Preference
android:key="simulate_your_location"
android:layout="@layout/preference_with_descr"

View file

@ -58,7 +58,7 @@
android:layout="@layout/preference_button"
android:persistent="false"
android:title="@string/reorder_profiles"
app:fragment="net.osmand.plus.profiles.EditProfilesFragment"
app:fragment="net.osmand.plus.profiles.fragments.EditProfilesFragment"
tools:icon="@drawable/ic_action_edit_dark" />
<Preference

View file

@ -23,6 +23,7 @@ import net.osmand.plus.inapp.InAppPurchases.InAppPurchase;
import net.osmand.plus.inapp.InAppPurchases.InAppSubscription;
import net.osmand.plus.inapp.InAppPurchasesImpl.InAppPurchaseLiveUpdatesOldSubscription;
import net.osmand.plus.inapp.util.BillingManager;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.util.Algorithms;
@ -407,7 +408,7 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
}
}
}
OsmandSettings.OsmandPreference<Long> subscriptionCancelledTime = ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_TIME;
OsmandPreference<Long> subscriptionCancelledTime = ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_TIME;
if (!subscribedToLiveUpdates && ctx.getSettings().LIVE_UPDATES_PURCHASED.get()) {
if (subscriptionCancelledTime.get() == 0) {
subscriptionCancelledTime.set(System.currentTimeMillis());

View file

@ -31,7 +31,7 @@ import net.osmand.plus.inapp.InAppPurchases.InAppSubscription;
import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionIntroductoryInfo;
import net.osmand.plus.inapp.InAppPurchasesImpl.InAppPurchaseLiveUpdatesOldSubscription;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.util.Algorithms;
import java.lang.ref.WeakReference;

View file

@ -223,6 +223,19 @@ public class FileUtils {
return tempDir;
}
public static boolean isWritable(File dirToTest) {
boolean isWriteable;
try {
dirToTest.mkdirs();
File writeTestFile = File.createTempFile("osmand_", ".tmp", dirToTest);
isWriteable = writeTestFile.exists();
writeTestFile.delete();
} catch (IOException e) {
isWriteable = false;
}
return isWriteable;
}
public interface RenameCallback {
void renamedTo(File file);
}

View file

@ -18,10 +18,10 @@ import net.osmand.AndroidUtils;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.layers.AidlMapLayer;
import net.osmand.plus.views.layers.MapInfoLayer;

View file

@ -25,7 +25,7 @@ import net.osmand.core.jni.ResolvedMapStyle;
import net.osmand.core.jni.SwigUtilities;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRuleStorageProperties;

View file

@ -13,8 +13,8 @@ import androidx.annotation.StringRes;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings.BooleanPreference;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.BooleanPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.parkingpoint.ParkingPositionPlugin;
import net.osmand.util.Algorithms;

View file

@ -28,7 +28,7 @@ import net.osmand.map.OsmandRegions.RegionTranslation;
import net.osmand.map.WorldRegion;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.plus.activities.DayNightHelper;
import net.osmand.plus.helpers.DayNightHelper;
import net.osmand.plus.activities.LocalIndexHelper;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.SavingTrackHelper;

View file

@ -3,7 +3,30 @@ package net.osmand.plus;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import net.osmand.data.FavouritePoint.SpecialPointType;
import net.osmand.data.LatLon;
import net.osmand.plus.AppInitializer.AppInitializeListener;
import net.osmand.plus.AppInitializer.InitEvents;
import net.osmand.plus.api.SettingsAPI;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.EnumStringPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class AppVersionUpgradeOnInit {
public static final String FIRST_TIME_APP_RUN = "FIRST_TIME_APP_RUN"; //$NON-NLS-1$
public static final String VERSION_INSTALLED_NUMBER = "VERSION_INSTALLED_NUMBER"; //$NON-NLS-1$
public static final String NUMBER_OF_STARTS = "NUMBER_OF_STARTS"; //$NON-NLS-1$
@ -43,7 +66,7 @@ class AppVersionUpgradeOnInit {
@SuppressLint("ApplySharedPref")
void upgradeVersion(SharedPreferences startPrefs, int lastVersion) {
if(!startPrefs.contains(NUMBER_OF_STARTS)) {
if (!startPrefs.contains(NUMBER_OF_STARTS)) {
startPrefs.edit().putInt(NUMBER_OF_STARTS, 1).commit();
} else {
startPrefs.edit().putInt(NUMBER_OF_STARTS, startPrefs.getInt(NUMBER_OF_STARTS, 0) + 1).commit();
@ -59,27 +82,28 @@ class AppVersionUpgradeOnInit {
} else {
prevAppVersion = startPrefs.getInt(VERSION_INSTALLED_NUMBER, 0);
if (needsUpgrade(startPrefs, lastVersion)) {
OsmandSettings settings = app.getSettings();
if (prevAppVersion < VERSION_2_2) {
app.getSettings().SHOW_DASHBOARD_ON_START.set(true);
app.getSettings().SHOW_DASHBOARD_ON_MAP_SCREEN.set(true);
app.getSettings().SHOW_CARD_TO_CHOOSE_DRAWER.set(true);
settings.SHOW_DASHBOARD_ON_START.set(true);
settings.SHOW_DASHBOARD_ON_MAP_SCREEN.set(true);
settings.SHOW_CARD_TO_CHOOSE_DRAWER.set(true);
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_2_2).commit();
}
if (prevAppVersion < VERSION_2_3) {
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_2_3).commit();
}
if (prevAppVersion < VERSION_3_2) {
app.getSettings().BILLING_PURCHASE_TOKENS_SENT.set("");
settings.BILLING_PURCHASE_TOKENS_SENT.set("");
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_3_2).commit();
}
if (prevAppVersion < VERSION_3_5 || Version.getAppVersion(app).equals("3.5.3")
|| Version.getAppVersion(app).equals("3.5.4")) {
app.getSettings().migratePreferences();
migratePreferences();
app.getAppInitializer().addListener(new AppInitializer.AppInitializeListener() {
@Override
public void onProgress(AppInitializer init, AppInitializer.InitEvents event) {
if (event.equals(AppInitializer.InitEvents.FAVORITES_INITIALIZED)) {
app.getSettings().migrateHomeWorkParkingToFavorites();
migrateHomeWorkParkingToFavorites();
}
}
@ -90,21 +114,22 @@ class AppVersionUpgradeOnInit {
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_3_5).commit();
}
if (prevAppVersion < VERSION_3_6) {
app.getSettings().migratePreferences();
migratePreferences();
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_3_6).commit();
}
if (prevAppVersion < VERSION_3_7) {
app.getSettings().migrateEnumPreferences();
migrateEnumPreferences();
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_3_7).commit();
}
if (prevAppVersion < VERSION_3_7_01) {
app.getAppInitializer().addListener(new AppInitializer.AppInitializeListener() {
app.getAppInitializer().addListener(new AppInitializeListener() {
@Override
public void onProgress(AppInitializer init, AppInitializer.InitEvents event) {
if (event.equals(AppInitializer.InitEvents.FAVORITES_INITIALIZED)) {
if (event.equals(InitEvents.FAVORITES_INITIALIZED)) {
app.getFavorites().fixBlackBackground();
}
}
@Override
public void onFinish(AppInitializer init) {
}
@ -112,7 +137,7 @@ class AppVersionUpgradeOnInit {
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_3_7_01).commit();
}
if (prevAppVersion < VERSION_3_8_00) {
app.getSettings().migrateQuickActionStates();
migrateQuickActionStates();
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, VERSION_3_8_00).commit();
}
startPrefs.edit().putInt(VERSION_INSTALLED_NUMBER, lastVersion).commit();
@ -135,20 +160,20 @@ class AppVersionUpgradeOnInit {
}
public void resetFirstTimeRun(SharedPreferences startPrefs) {
if(startPrefs != null) {
if (startPrefs != null) {
startPrefs.edit().remove(FIRST_TIME_APP_RUN).commit();
}
}
public int getNumberOfStarts(SharedPreferences startPrefs) {
if(startPrefs == null) {
if (startPrefs == null) {
return 0;
}
return startPrefs.getInt(NUMBER_OF_STARTS, 1);
}
public long getFirstInstalledDays(SharedPreferences startPrefs) {
if(startPrefs == null) {
if (startPrefs == null) {
return 0;
}
long nd = startPrefs.getLong(FIRST_INSTALLED, 0);
@ -159,4 +184,165 @@ class AppVersionUpgradeOnInit {
public boolean isFirstTime() {
return firstTime;
}
}
public void migratePreferences() {
OsmandSettings settings = app.getSettings();
migrateEnumPreferences();
SharedPreferences globalSharedPreferences = (SharedPreferences) settings.getGlobalPreferences();
Map<String, ?> globalPrefsMap = globalSharedPreferences.getAll();
for (String key : globalPrefsMap.keySet()) {
OsmandPreference<?> pref = settings.getPreference(key);
if (pref instanceof CommonPreference) {
CommonPreference<?> commonPreference = (CommonPreference<?>) pref;
if (!commonPreference.isGlobal()) {
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
if (!commonPreference.isSetForMode(mode) && !commonPreference.hasDefaultValueForMode(mode)) {
settings.setPreference(key, globalPrefsMap.get(key), mode);
}
}
}
}
}
SharedPreferences defaultProfilePreferences = (SharedPreferences) settings.getProfilePreferences(ApplicationMode.DEFAULT);
Map<String, ?> defaultPrefsMap = defaultProfilePreferences.getAll();
for (String key : defaultPrefsMap.keySet()) {
OsmandPreference<?> pref = settings.getPreference(key);
if (pref instanceof CommonPreference) {
CommonPreference<?> commonPreference = (CommonPreference<?>) pref;
if (commonPreference.isGlobal() && !commonPreference.isSet()) {
settings.setPreference(key, defaultPrefsMap.get(key));
}
}
}
for (OsmandPreference<?> pref : getGeneralPrefs()) {
if (pref instanceof CommonPreference) {
CommonPreference<?> commonPref = (CommonPreference<?>) pref;
Object defaultVal = commonPref.getModeValue(ApplicationMode.DEFAULT);
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
if (!commonPref.isSetForMode(mode) && !commonPref.hasDefaultValueForMode(mode)) {
settings.setPreference(commonPref.getId(), defaultVal, mode);
}
}
}
}
String json = settings.getSettingsAPI().getString(settings.getGlobalPreferences(), "custom_app_profiles", "");
if (!Algorithms.isEmpty(json)) {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Type t = new TypeToken<ArrayList<ApplicationMode.ApplicationModeBean>>() {
}.getType();
List<ApplicationMode.ApplicationModeBean> customProfiles = gson.fromJson(json, t);
if (!Algorithms.isEmpty(customProfiles)) {
for (ApplicationMode.ApplicationModeBean modeBean : customProfiles) {
ApplicationMode.ApplicationModeBuilder builder = ApplicationMode.fromModeBean(app, modeBean);
ApplicationMode.saveProfile(builder, app);
}
}
}
}
public void migrateEnumPreferences() {
OsmandSettings settings = app.getSettings();
for (OsmandPreference<?> pref : settings.getRegisteredPreferences().values()) {
if (pref instanceof EnumStringPreference) {
EnumStringPreference<?> enumPref = (EnumStringPreference<?>) pref;
if (enumPref.isGlobal()) {
migrateEnumPref(enumPref, (SharedPreferences) settings.getGlobalPreferences());
} else {
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
migrateEnumPref(enumPref, (SharedPreferences) settings.getProfilePreferences(mode));
}
}
}
}
}
public void migrateQuickActionStates() {
OsmandSettings settings = app.getSettings();
String quickActionsJson = settings.getSettingsAPI().getString(settings.getGlobalPreferences(), "quick_action_new", "");
if (!Algorithms.isEmpty(quickActionsJson)) {
Gson gson = new GsonBuilder().create();
Type type = new TypeToken<HashMap<String, Boolean>>() {
}.getType();
HashMap<String, Boolean> quickActions = gson.fromJson(quickActionsJson, type);
if (!Algorithms.isEmpty(quickActions)) {
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
settings.setQuickActions(quickActions, mode);
}
}
}
}
private void migrateEnumPref(EnumStringPreference enumPref, SharedPreferences sharedPreferences) {
Object value = sharedPreferences.getAll().get(enumPref.getId());
if (value instanceof Integer) {
int enumIndex = (int) value;
if (enumIndex >= 0 && enumIndex < enumPref.getValues().length) {
Enum savedValue = enumPref.getValues()[enumIndex];
enumPref.setValue(sharedPreferences, savedValue);
}
}
}
public void migrateHomeWorkParkingToFavorites() {
OsmandSettings settings = app.getSettings();
FavouritesDbHelper favorites = app.getFavorites();
SettingsAPI settingsAPI = settings.getSettingsAPI();
Object globalPreferences = settings.getGlobalPreferences();
LatLon homePoint = null;
float lat = settingsAPI.getFloat(globalPreferences, "home_point_lat", 0);
float lon = settingsAPI.getFloat(globalPreferences, "home_point_lon", 0);
if (lat != 0 || lon != 0) {
homePoint = new LatLon(lat, lon);
}
LatLon workPoint = null;
lat = settingsAPI.getFloat(globalPreferences, "work_point_lat", 0);
lon = settingsAPI.getFloat(globalPreferences, "work_point_lon", 0);
if (lat != 0 || lon != 0) {
workPoint = new LatLon(lat, lon);
}
if (homePoint != null) {
favorites.setSpecialPoint(homePoint, SpecialPointType.HOME, null);
}
if (workPoint != null) {
favorites.setSpecialPoint(workPoint, SpecialPointType.WORK, null);
}
}
public OsmandPreference<?>[] getGeneralPrefs() {
OsmandSettings settings = app.getSettings();
return new OsmandPreference[] {
settings.EXTERNAL_INPUT_DEVICE,
settings.CENTER_POSITION_ON_MAP,
settings.ROTATE_MAP,
settings.MAP_SCREEN_ORIENTATION,
settings.LIVE_MONITORING_URL,
settings.LIVE_MONITORING_MAX_INTERVAL_TO_SEND,
settings.LIVE_MONITORING_INTERVAL,
settings.LIVE_MONITORING,
settings.SHOW_TRIP_REC_NOTIFICATION,
settings.AUTO_SPLIT_RECORDING,
settings.SAVE_TRACK_MIN_SPEED,
settings.SAVE_TRACK_PRECISION,
settings.SAVE_TRACK_MIN_DISTANCE,
settings.SAVE_TRACK_INTERVAL,
settings.TRACK_STORAGE_DIRECTORY,
settings.SAVE_HEADING_TO_GPX,
settings.DISABLE_RECORDING_ONCE_APP_KILLED,
settings.SAVE_TRACK_TO_GPX,
settings.SAVE_GLOBAL_TRACK_REMEMBER,
settings.SAVE_GLOBAL_TRACK_INTERVAL,
settings.MAP_EMPTY_STATE_ALLOWED,
settings.DO_NOT_USE_ANIMATIONS,
settings.USE_KALMAN_FILTER_FOR_COMPASS,
settings.USE_MAGNETIC_FIELD_SENSOR_COMPASS,
settings.USE_TRACKBALL_FOR_MOVEMENTS,
settings.SPEED_SYSTEM,
settings.ANGULAR_UNITS,
settings.METRIC_SYSTEM,
settings.DRIVING_REGION,
settings.DRIVING_REGION_AUTOMATIC
};
}
}

View file

@ -38,9 +38,8 @@ import net.osmand.plus.dialogs.HelpArticleDialogFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.ContextMenuItemsPreference;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.ContextMenuItemsPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -53,6 +52,9 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_CONFIGURE_PROFILE_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SWITCH_PROFILE_ID;
public class ContextMenuAdapter {
private static final Log LOG = PlatformUtil.getLog(ContextMenuAdapter.class);
@ -134,6 +136,19 @@ public class ContextMenuAdapter {
Collections.sort(items, new Comparator<ContextMenuItem>() {
@Override
public int compare(ContextMenuItem item1, ContextMenuItem item2) {
if (DRAWER_CONFIGURE_PROFILE_ID.equals(item1.getId())
&& DRAWER_SWITCH_PROFILE_ID.equals(item2.getId())) {
return 1;
} else if (DRAWER_SWITCH_PROFILE_ID.equals(item1.getId())
&& DRAWER_CONFIGURE_PROFILE_ID.equals(item2.getId())) {
return -1;
} else if (DRAWER_SWITCH_PROFILE_ID.equals(item1.getId())
|| DRAWER_CONFIGURE_PROFILE_ID.equals(item1.getId())) {
return -1;
} else if (DRAWER_SWITCH_PROFILE_ID.equals(item2.getId())
|| DRAWER_CONFIGURE_PROFILE_ID.equals(item2.getId())) {
return 1;
}
int order1 = item1.getOrder();
int order2 = item2.getOrder();
if (order1 < order2) {
@ -631,7 +646,7 @@ public class ContextMenuAdapter {
return makeDeleteAction(prefs.toArray(new OsmandPreference[prefs.size()]));
}
private static void resetSetting(ApplicationMode appMode, OsmandSettings.OsmandPreference preference, boolean profileOnly) {
private static void resetSetting(ApplicationMode appMode, OsmandPreference preference, boolean profileOnly) {
if (profileOnly) {
preference.resetModeToDefault(appMode);
} else {

View file

@ -29,7 +29,7 @@ import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.routing.RouteProvider;
import net.osmand.plus.settings.backend.OsmandSettings.MetricsConstants;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.track.GpxSplitType;
import net.osmand.plus.track.GradientScaleType;
import net.osmand.util.Algorithms;

View file

@ -15,9 +15,9 @@ import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.AngularConstants;
import net.osmand.plus.settings.backend.OsmandSettings.MetricsConstants;
import net.osmand.plus.settings.backend.OsmandSettings.SpeedConstants;
import net.osmand.plus.helpers.enums.AngularConstants;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.helpers.enums.SpeedConstants;
import net.osmand.util.Algorithms;
import java.text.DateFormatSymbols;

View file

@ -30,6 +30,7 @@ import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.access.AccessibilityPlugin;
@ -42,7 +43,7 @@ import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.AppInitializer.AppInitializeListener;
import net.osmand.plus.access.AccessibilityMode;
import net.osmand.plus.activities.DayNightHelper;
import net.osmand.plus.helpers.DayNightHelper;
import net.osmand.plus.activities.ExitActivity;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.SavingTrackHelper;
@ -56,7 +57,9 @@ import net.osmand.plus.download.DownloadIndexesThread;
import net.osmand.plus.download.DownloadService;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.enums.DrivingRegion;
import net.osmand.plus.helpers.LockHelper;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.helpers.WaypointHelper;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
@ -189,7 +192,7 @@ public class OsmandApplication extends MultiDexApplication {
osmandSettings.initExternalStorageDirectory();
}
externalStorageDirectory = osmandSettings.getExternalStorageDirectory();
if (!OsmandSettings.isWritable(externalStorageDirectory)) {
if (!FileUtils.isWritable(externalStorageDirectory)) {
externalStorageDirectoryReadOnly = true;
externalStorageDirectory = osmandSettings.getInternalAppPath();
}
@ -983,15 +986,15 @@ public class OsmandApplication extends MultiDexApplication {
}
public void setupDrivingRegion(WorldRegion reg) {
OsmandSettings.DrivingRegion drg = null;
DrivingRegion drg = null;
WorldRegion.RegionParams params = reg.getParams();
// boolean americanSigns = "american".equals(params.getRegionRoadSigns());
boolean leftHand = "yes".equals(params.getRegionLeftHandDriving());
OsmandSettings.MetricsConstants mc1 = "miles".equals(params.getRegionMetric()) ?
OsmandSettings.MetricsConstants.MILES_AND_FEET : OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS;
OsmandSettings.MetricsConstants mc2 = "miles".equals(params.getRegionMetric()) ?
OsmandSettings.MetricsConstants.MILES_AND_METERS : OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS;
for (OsmandSettings.DrivingRegion r : OsmandSettings.DrivingRegion.values()) {
MetricsConstants mc1 = "miles".equals(params.getRegionMetric()) ?
MetricsConstants.MILES_AND_FEET : MetricsConstants.KILOMETERS_AND_METERS;
MetricsConstants mc2 = "miles".equals(params.getRegionMetric()) ?
MetricsConstants.MILES_AND_METERS : MetricsConstants.KILOMETERS_AND_METERS;
for (DrivingRegion r : DrivingRegion.values()) {
if (r.leftHandDriving == leftHand && (r.defMetrics == mc1 || r.defMetrics == mc2)) {
drg = r;
break;

View file

@ -47,6 +47,8 @@ import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.search.QuickSearchDialogFragment;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.skimapsplugin.SkiMapsPlugin;
import net.osmand.plus.srtmplugin.SRTMPlugin;
@ -80,7 +82,7 @@ public abstract class OsmandPlugin {
protected OsmandApplication app;
protected List<OsmandSettings.OsmandPreference> pluginPreferences = new ArrayList<>();
protected List<OsmandPreference> pluginPreferences = new ArrayList<>();
private boolean active;
private String installURL = null;
@ -118,7 +120,7 @@ public abstract class OsmandPlugin {
return null;
}
public List<OsmandSettings.OsmandPreference> getPreferences() {
public List<OsmandPreference> getPreferences() {
return pluginPreferences;
}
@ -919,44 +921,44 @@ public abstract class OsmandPlugin {
}
}
protected OsmandSettings.CommonPreference<Boolean> registerBooleanPreference(OsmandApplication app, String prefId, boolean defValue) {
OsmandSettings.CommonPreference<Boolean> preference = app.getSettings().registerBooleanPreference(prefId, defValue);
protected CommonPreference<Boolean> registerBooleanPreference(OsmandApplication app, String prefId, boolean defValue) {
CommonPreference<Boolean> preference = app.getSettings().registerBooleanPreference(prefId, defValue);
pluginPreferences.add(preference);
return preference;
}
private OsmandSettings.CommonPreference<Boolean> registerBooleanAccessibilityPreference(OsmandApplication app, String prefId, boolean defValue) {
OsmandSettings.CommonPreference<Boolean> preference = app.getSettings().registerBooleanAccessibilityPreference(prefId, defValue);
private CommonPreference<Boolean> registerBooleanAccessibilityPreference(OsmandApplication app, String prefId, boolean defValue) {
CommonPreference<Boolean> preference = app.getSettings().registerBooleanAccessibilityPreference(prefId, defValue);
pluginPreferences.add(preference);
return preference;
}
protected OsmandSettings.CommonPreference<String> registerStringPreference(OsmandApplication app, String prefId, String defValue) {
OsmandSettings.CommonPreference<String> preference = app.getSettings().registerStringPreference(prefId, defValue);
protected CommonPreference<String> registerStringPreference(OsmandApplication app, String prefId, String defValue) {
CommonPreference<String> preference = app.getSettings().registerStringPreference(prefId, defValue);
pluginPreferences.add(preference);
return preference;
}
protected OsmandSettings.CommonPreference<Integer> registerIntPreference(OsmandApplication app, String prefId, int defValue) {
OsmandSettings.CommonPreference<Integer> preference = app.getSettings().registerIntPreference(prefId, defValue);
protected CommonPreference<Integer> registerIntPreference(OsmandApplication app, String prefId, int defValue) {
CommonPreference<Integer> preference = app.getSettings().registerIntPreference(prefId, defValue);
pluginPreferences.add(preference);
return preference;
}
protected OsmandSettings.CommonPreference<Long> registerLongPreference(OsmandApplication app, String prefId, long defValue) {
OsmandSettings.CommonPreference<Long> preference = app.getSettings().registerLongPreference(prefId, defValue);
protected CommonPreference<Long> registerLongPreference(OsmandApplication app, String prefId, long defValue) {
CommonPreference<Long> preference = app.getSettings().registerLongPreference(prefId, defValue);
pluginPreferences.add(preference);
return preference;
}
protected OsmandSettings.CommonPreference<Float> registerFloatPreference(OsmandApplication app, String prefId, float defValue) {
OsmandSettings.CommonPreference<Float> preference = app.getSettings().registerFloatPreference(prefId, defValue);
protected CommonPreference<Float> registerFloatPreference(OsmandApplication app, String prefId, float defValue) {
CommonPreference<Float> preference = app.getSettings().registerFloatPreference(prefId, defValue);
pluginPreferences.add(preference);
return preference;
}
protected <T extends Enum> OsmandSettings.CommonPreference<T> registerEnumIntPreference(OsmandApplication app, String prefId, Enum defaultValue, Enum[] values, Class<T> clz) {
OsmandSettings.CommonPreference<T> preference = app.getSettings().registerEnumIntPreference(prefId, defaultValue, values, clz);
protected <T extends Enum> CommonPreference<T> registerEnumIntPreference(OsmandApplication app, String prefId, Enum defaultValue, Enum[] values, Class<T> clz) {
CommonPreference<T> preference = app.getSettings().registerEnumIntPreference(prefId, defaultValue, values, clz);
pluginPreferences.add(preference);
return preference;
}

View file

@ -1,13 +1,15 @@
package net.osmand.plus;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class Version {
private final String appVersion;
@ -149,4 +151,21 @@ public class Version {
return v;
}
}
public static boolean isOpenGlAvailable(OsmandApplication app) {
if ("qnx".equals(System.getProperty("os.name"))) {
return false;
}
File nativeLibraryDir = new File(app.getApplicationInfo().nativeLibraryDir);
if (nativeLibraryDir.exists() && nativeLibraryDir.canRead()) {
File[] files = nativeLibraryDir.listFiles();
if (files != null) {
for (File file : files) {
if ("libOsmAndCoreWithJNI.so".equals(file.getName())) {
return true;
}
}
}
}
return false;
}
}

View file

@ -43,6 +43,7 @@ import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.FavouritesDbHelper.FavoritesListener;
import net.osmand.plus.MapMarkersHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
@ -96,7 +97,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
private Set<FavoriteGroup> groupsToDelete = new LinkedHashSet<>();
private ActionMode actionMode;
private Drawable arrowImageDisabled;
private HashMap<String, OsmandSettings.OsmandPreference<Boolean>> preferenceCache = new HashMap<>();
private HashMap<String, OsmandPreference<Boolean>> preferenceCache = new HashMap<>();
private View footerView;
private Location lastLocation;
private float lastHeading;
@ -763,8 +764,8 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
}
}
private OsmandSettings.OsmandPreference<Boolean> getGroupExpandedPreference(String groupName) {
OsmandSettings.OsmandPreference<Boolean> preference = preferenceCache.get(groupName);
private OsmandPreference<Boolean> getGroupExpandedPreference(String groupName) {
OsmandPreference<Boolean> preference = preferenceCache.get(groupName);
if (preference == null) {
String groupKey = groupName + GROUP_EXPANDED_POSTFIX;
preference = getSettings().registerBooleanPreference(groupKey, false);

View file

@ -172,6 +172,8 @@ public class HelpActivity extends OsmandActionBarActivity implements AdapterView
"feature_articles/technical-articles.html"));
contextMenuAdapter.addItem(createItem(R.string.versions_item, NULL_ID,
"feature_articles/changes.html"));
contextMenuAdapter.addItem(createItem(R.string.what_is_new, NULL_ID,
"feature_articles/blog.html"));
String releasedate = "";
if (!this.getString(R.string.app_edition).equals("")) {

View file

@ -74,6 +74,9 @@ import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndLocationSimulation;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.helpers.DayNightHelper;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
@ -98,7 +101,7 @@ import net.osmand.plus.firstusage.FirstUsageWelcomeFragment;
import net.osmand.plus.firstusage.FirstUsageWizardFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.DiscountHelper;
import net.osmand.plus.helpers.ImportHelper;
import net.osmand.plus.importfiles.ImportHelper;
import net.osmand.plus.helpers.IntentHelper;
import net.osmand.plus.helpers.LockHelper;
import net.osmand.plus.helpers.LockHelper.LockUIAdapter;
@ -130,7 +133,6 @@ import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchTab;
import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchType;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.plus.settings.fragments.ConfigureProfileFragment;
@ -533,7 +535,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
@Override
public void requestPrivateAccessRouting() {
if (!settings.FORCE_PRIVATE_ACCESS_ROUTING_ASKED.getModeValue(getRoutingHelper().getAppMode())) {
final OsmandSettings.CommonPreference<Boolean> allowPrivate
final CommonPreference<Boolean> allowPrivate
= settings.getCustomRoutingBooleanProperty(GeneralRouter.ALLOW_PRIVATE, false);
final List<ApplicationMode> modes = ApplicationMode.values(app);
for (ApplicationMode mode : modes) {

View file

@ -29,7 +29,7 @@ import net.osmand.plus.DialogListItemAdapter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.activities.MapActivity.ShowQuickSearchMode;

View file

@ -25,13 +25,13 @@ import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.profiles.AppProfileArrayAdapter;
import net.osmand.plus.profiles.ProfileDataObject;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import org.apache.commons.logging.Log;

View file

@ -42,9 +42,9 @@ import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.AngularConstants;
import net.osmand.plus.settings.backend.OsmandSettings.DrivingRegion;
import net.osmand.plus.settings.backend.OsmandSettings.MetricsConstants;
import net.osmand.plus.helpers.enums.AngularConstants;
import net.osmand.plus.helpers.enums.DrivingRegion;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.base.MapViewTrackingUtilities;

View file

@ -34,6 +34,12 @@ import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.helpers.enums.AutoZoomMap;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.helpers.enums.SpeedConstants;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
@ -44,10 +50,6 @@ import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper;
import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.AutoZoomMap;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandSettings.SpeedConstants;
import net.osmand.plus.voice.CommandPlayer;
import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
@ -171,7 +173,7 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
//array size must be equal!
Float[] speedLimitsKmhPos = new Float[]{0f, 5f, 7f, 10f, 15f, 20f};
Float[] speedLimitsMphPos = new Float[]{0f, 3f, 5f, 7f, 10f, 15f};
if (settings.METRIC_SYSTEM.get() == OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS) {
if (settings.METRIC_SYSTEM.get() == MetricsConstants.KILOMETERS_AND_METERS) {
String[] speedNames = new String[speedLimitsKmh.length];
String[] speedNamesPos = new String[speedLimitsKmhPos.length];
for (int i = 0; i < speedLimitsKmh.length; i++) {
@ -407,7 +409,7 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
}
public static boolean isRoutingParameterSelected(OsmandSettings settings, ApplicationMode am, RoutingParameter routingParameter) {
final OsmandSettings.CommonPreference<Boolean> property =
final CommonPreference<Boolean> property =
settings.getCustomRoutingBooleanProperty(routingParameter.getId(), routingParameter.getDefaultBoolean());
if(am != null) {
return property.getModeValue(am);
@ -417,7 +419,7 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
}
public static void setRoutingParameterSelected(OsmandSettings settings, ApplicationMode am, String routingParameterId, boolean defaultBoolean, boolean isChecked) {
final OsmandSettings.CommonPreference<Boolean> property = settings.getCustomRoutingBooleanProperty(routingParameterId, defaultBoolean);
final CommonPreference<Boolean> property = settings.getCustomRoutingBooleanProperty(routingParameterId, defaultBoolean);
if (am != null) {
property.setModeValue(am, isChecked);
} else {

View file

@ -53,8 +53,8 @@ import net.osmand.plus.ContextMenuAdapter.ItemClickListener;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;

View file

@ -38,7 +38,6 @@ import net.osmand.PlatformUtil;
import net.osmand.data.PointDescription;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings.NotesSortByMode;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.ActionBarProgressActivity;

View file

@ -0,0 +1,14 @@
package net.osmand.plus.audionotes;
public enum NotesSortByMode {
BY_TYPE,
BY_DATE;
public boolean isByType() {
return this == BY_TYPE;
}
public boolean isByDate() {
return this == BY_DATE;
}
}

View file

@ -3,8 +3,7 @@ package net.osmand.plus.audionotes;
import android.os.Bundle;
import android.view.View;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.NotesSortByMode;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
@ -53,7 +52,7 @@ public class SortByMenuBottomSheetDialogFragment extends MenuBottomSheetDialogFr
}
private void selectSortByMode(NotesSortByMode mode) {
final OsmandSettings.CommonPreference<NotesSortByMode> sortByMode = getMyApplication().getSettings().NOTES_SORT_BY_MODE;
final CommonPreference<NotesSortByMode> sortByMode = getMyApplication().getSettings().NOTES_SORT_BY_MODE;
if (sortByMode.get() != mode) {
sortByMode.set(mode);
if (listener != null) {

View file

@ -25,7 +25,7 @@ import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.Version;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;

View file

@ -30,6 +30,7 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.ValueHolder;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
@ -113,7 +114,7 @@ public class DashChooseAppDirFragment {
boolean copyFiles = !currentAppFile.getAbsolutePath().equals(selectedFile.getAbsolutePath()) && !mapsCopied;
warningReadonly.setVisibility(copyFiles ? View.VISIBLE : View.GONE);
if (copyFiles) {
if (!OsmandSettings.isWritable(currentAppFile)) {
if (!FileUtils.isWritable(currentAppFile)) {
warningReadonly.setText(activity.getString(R.string.android_19_location_disabled,
currentAppFile.getAbsolutePath()));
} else {
@ -385,7 +386,7 @@ public class DashChooseAppDirFragment {
@Override
public void onClick(View v) {
boolean wr = OsmandSettings.isWritable(selectedFile);
boolean wr = FileUtils.isWritable(selectedFile);
if (wr) {
boolean changed = !currentAppFile.getAbsolutePath().equals(selectedFile.getAbsolutePath());
getMyApplication().setExternalStorageDirectory(type, selectedFile.getAbsolutePath());

View file

@ -24,7 +24,7 @@ import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;

View file

@ -35,12 +35,7 @@ public class DevelopmentSettingsFragment extends BaseSettingsFragment {
setupOpenglRenderPref();
setupSafeModePref();
setupPTSafeMode();
setupDisableComplexRoutingPref();
setupFastRecalculationPref();
setupOsmLiveForRoutingPref();
setupOsmLiveForPublicTransportPref();
setupSimulateYourLocationPref();
Preference debuggingAndDevelopment = findPreference("debugging_and_development");
@ -62,13 +57,17 @@ public class DevelopmentSettingsFragment extends BaseSettingsFragment {
}
private void setupOpenglRenderPref() {
SwitchPreferenceEx useOpenglRender = (SwitchPreferenceEx) findPreference(settings.USE_OPENGL_RENDER.getId());
useOpenglRender.setDescription(getString(R.string.use_opengl_render_descr));
useOpenglRender.setIconSpaceReserved(false);
SwitchPreferenceEx useOpenglRender = findPreference(settings.USE_OPENGL_RENDER.getId());
if (Version.isOpenGlAvailable(app)) {
useOpenglRender.setDescription(getString(R.string.use_opengl_render_descr));
useOpenglRender.setIconSpaceReserved(false);
} else {
useOpenglRender.setVisible(false);
}
}
private void setupSafeModePref() {
SwitchPreferenceEx safeMode = (SwitchPreferenceEx) findPreference(settings.SAFE_MODE.getId());
SwitchPreferenceEx safeMode = findPreference(settings.SAFE_MODE.getId());
if (!Version.isBlackberry(app)) {
safeMode.setDescription(getString(R.string.safe_mode_description));
safeMode.setIconSpaceReserved(false);
@ -82,40 +81,6 @@ public class DevelopmentSettingsFragment extends BaseSettingsFragment {
}
}
private void setupPTSafeMode() {
SwitchPreferenceEx ptSafeMode = (SwitchPreferenceEx) findPreference(settings.PT_SAFE_MODE.getId());
if (!Version.isBlackberry(app)) {
ptSafeMode.setDescription("Switch to Java (safe) Public Transport routing calculation");
ptSafeMode.setIconSpaceReserved(false);
} else {
ptSafeMode.setVisible(false);
}
}
private void setupDisableComplexRoutingPref() {
SwitchPreferenceEx disableComplexRouting = (SwitchPreferenceEx) findPreference(settings.DISABLE_COMPLEX_ROUTING.getId());
disableComplexRouting.setDescription(getString(R.string.disable_complex_routing_descr));
disableComplexRouting.setIconSpaceReserved(false);
}
private void setupFastRecalculationPref() {
SwitchPreferenceEx useFastRecalculation = (SwitchPreferenceEx) findPreference(settings.USE_FAST_RECALCULATION.getId());
useFastRecalculation.setDescription(getString(R.string.use_fast_recalculation_desc));
useFastRecalculation.setIconSpaceReserved(false);
}
private void setupOsmLiveForRoutingPref() {
SwitchPreferenceEx useOsmLiveForRouting = (SwitchPreferenceEx) findPreference(settings.USE_OSM_LIVE_FOR_ROUTING.getId());
useOsmLiveForRouting.setDescription(getString(R.string.use_osm_live_routing_description));
useOsmLiveForRouting.setIconSpaceReserved(false);
}
private void setupOsmLiveForPublicTransportPref() {
SwitchPreferenceEx useOsmLiveForPublicTransport = (SwitchPreferenceEx) findPreference(settings.USE_OSM_LIVE_FOR_PUBLIC_TRANSPORT.getId());
useOsmLiveForPublicTransport.setDescription(getString(R.string.use_osm_live_public_transport_description));
useOsmLiveForPublicTransport.setIconSpaceReserved(false);
}
private void setupSimulateYourLocationPref() {
final Preference simulateYourLocation = findPreference(SIMULATE_YOUR_LOCATION);
simulateYourLocation.setIconSpaceReserved(false);

View file

@ -14,11 +14,11 @@ import android.preference.PreferenceScreen;
import net.osmand.plus.OsmAndLocationSimulation;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.SettingsBaseActivity;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.SunriseSunset;
import java.text.SimpleDateFormat;
@ -34,41 +34,27 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
app.applyTheme(this);
super.onCreate(savedInstanceState);
getToolbar().setTitle(R.string.debugging_and_development);
PreferenceScreen cat = getPreferenceScreen();
PreferenceScreen category = getPreferenceScreen();
Preference pref;
cat.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER,
R.string.use_opengl_render, R.string.use_opengl_render_descr));
if (Version.isOpenGlAvailable(app)) {
category.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER,
R.string.use_opengl_render, R.string.use_opengl_render_descr));
}
if (!Version.isBlackberry(app)) {
CheckBoxPreference nativeCheckbox = createCheckBoxPreference(settings.SAFE_MODE, R.string.safe_mode, R.string.safe_mode_description);
CheckBoxPreference nativePTCheckbox = createCheckBoxPreference(settings.PT_SAFE_MODE, "Native PT routing development", "Switch to Java (safe) Public Transport routing calculation");
// disable the checkbox if the library cannot be used
if ((NativeOsmandLibrary.isLoaded() && !NativeOsmandLibrary.isSupported()) || settings.NATIVE_RENDERING_FAILED.get()) {
nativeCheckbox.setEnabled(false);
nativeCheckbox.setChecked(true);
}
cat.addPreference(nativeCheckbox);
cat.addPreference(nativePTCheckbox);
category.addPreference(nativeCheckbox);
}
PreferenceCategory navigation = new PreferenceCategory(this);
navigation.setTitle(R.string.routing_settings);
cat.addPreference(navigation);
navigation.addPreference(createCheckBoxPreference(settings.DISABLE_COMPLEX_ROUTING,
R.string.disable_complex_routing, R.string.disable_complex_routing_descr));
navigation.addPreference(createCheckBoxPreference(settings.USE_FAST_RECALCULATION,
R.string.use_fast_recalculation, R.string.use_fast_recalculation_desc));
navigation.addPreference(createCheckBoxPreference(settings.USE_OSM_LIVE_FOR_ROUTING,
R.string.use_osm_live_routing,
R.string.use_osm_live_routing_description));
navigation.addPreference(createCheckBoxPreference(settings.USE_OSM_LIVE_FOR_PUBLIC_TRANSPORT,
R.string.use_osm_live_public_transport,
R.string.use_osm_live_public_transport_description));
category.addPreference(navigation);
pref = new Preference(this);
final Preference simulate = pref;
final OsmAndLocationSimulation sim = getMyApplication().getLocationProvider().getLocationSimulation();
@ -95,7 +81,7 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
PreferenceCategory debug = new PreferenceCategory(this);
debug.setTitle(R.string.debugging_and_development);
cat.addPreference(debug);
category.addPreference(debug);
CheckBoxPreference dbg = createCheckBoxPreference(settings.DEBUG_RENDERING_INFO,
R.string.trace_rendering, R.string.trace_rendering_descr);
@ -125,10 +111,6 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
debug.addPreference(createCheckBoxPreference(settings.SHOULD_SHOW_FREE_VERSION_BANNER,
R.string.show_free_version_banner,
R.string.show_free_version_banner_description));
pref = new Preference(this);
pref.setTitle(R.string.test_voice_prompts);
@ -141,7 +123,7 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
return true;
}
});
cat.addPreference(pref);
category.addPreference(pref);
pref = new Preference(this);
pref.setTitle(R.string.logcat_buffer);
@ -154,11 +136,11 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
return true;
}
});
cat.addPreference(pref);
category.addPreference(pref);
PreferenceCategory info = new PreferenceCategory(this);
info.setTitle(R.string.info_button);
cat.addPreference(info);
category.addPreference(info);
pref = new Preference(this);
pref.setTitle(R.string.global_app_allocated_memory);

View file

@ -19,7 +19,7 @@ import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.activities.OsmandActionBarActivity;
import net.osmand.plus.routing.data.StreetName;
@ -151,7 +151,7 @@ public class TestVoiceActivity extends OsmandActionBarActivity {
v += "\n \u25CF BT SCO: The current app profile is not set to use 'Phone call audio'.";
}
//OsmandSettings.OsmandPreference<Integer> pref = ((OsmandApplication) getApplication()).getSettings().VOICE_PROMPT_DELAY[stream];
//OsmandPreference<Integer> pref = ((OsmandApplication) getApplication()).getSettings().VOICE_PROMPT_DELAY[stream];
//if(pref != null) {
// v += "\n \u25CF Voice prompt delay for selected output: " + pref.get() + "\u00A0ms";
//}
@ -299,7 +299,7 @@ public class TestVoiceActivity extends OsmandActionBarActivity {
}
if (description.startsWith("\u25BA (11.2)")) {
int ams = ((OsmandApplication) getApplication()).getSettings().AUDIO_MANAGER_STREAM.get();
OsmandSettings.OsmandPreference<Integer> pref = ((OsmandApplication) getApplication()).getSettings().VOICE_PROMPT_DELAY[ams];
OsmandPreference<Integer> pref = ((OsmandApplication) getApplication()).getSettings().VOICE_PROMPT_DELAY[ams];
if (pref != null) {
if (pref.get() >= 3000) {
pref.set(0);

View file

@ -33,6 +33,11 @@ import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.DialogListItemAdapter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.helpers.enums.DayNightMode;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.ListStringPreference;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
@ -40,9 +45,6 @@ import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings.ListStringPreference;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.transport.TransportLinesMenu;
import net.osmand.plus.views.OsmandMapTileView;
@ -307,7 +309,7 @@ public class ConfigureMapMenu {
DateFormat dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
String sunriseTime = dateFormat.format(sunriseSunset.getSunrise());
String sunsetTime = dateFormat.format(sunriseSunset.getSunset());
OsmandSettings.DayNightMode dayNightMode = activity.getMyApplication().getSettings().DAYNIGHT_MODE.get();
DayNightMode dayNightMode = activity.getMyApplication().getSettings().DAYNIGHT_MODE.get();
if (dayNightMode.isDay() || dayNightMode.isNight()) {
if (sunriseSunset.isDaytime()) {
description = String.format(app.getString(R.string.sunset_at), sunsetTime);
@ -334,9 +336,9 @@ public class ConfigureMapMenu {
final OsmandMapTileView view = activity.getMapView();
AlertDialog.Builder bld = new AlertDialog.Builder(new ContextThemeWrapper(view.getContext(), themeRes));
bld.setTitle(R.string.daynight);
final String[] items = new String[OsmandSettings.DayNightMode.values().length];
final String[] items = new String[DayNightMode.values().length];
for (int i = 0; i < items.length; i++) {
items[i] = OsmandSettings.DayNightMode.values()[i].toHumanString(app);
items[i] = DayNightMode.values()[i].toHumanString(app);
}
int i = view.getSettings().DAYNIGHT_MODE.get().ordinal();
bld.setNegativeButton(R.string.shared_string_dismiss, null);
@ -345,7 +347,7 @@ public class ConfigureMapMenu {
@Override
public void onClick(View v) {
int which = (int) v.getTag();
view.getSettings().DAYNIGHT_MODE.set(OsmandSettings.DayNightMode.values()[which]);
view.getSettings().DAYNIGHT_MODE.set(DayNightMode.values()[which]);
refreshMapComplete(activity);
activity.getDashboard().refreshContent(true);
// adapter.getItem(pos).setDescription(s, getDayNightDescr(activity));
@ -376,7 +378,7 @@ public class ConfigureMapMenu {
return false;
}
final OsmandMapTileView view = activity.getMapView();
final OsmandSettings.OsmandPreference<Float> mapDensity = view.getSettings().MAP_DENSITY;
final OsmandPreference<Float> mapDensity = view.getSettings().MAP_DENSITY;
AlertDialog.Builder bld = new AlertDialog.Builder(new ContextThemeWrapper(view.getContext(), themeRes));
int p = (int) (mapDensity.get() * 100);
final TIntArrayList tlist = new TIntArrayList(new int[]{25, 33, 50, 75, 100, 125, 150, 200, 300, 400});
@ -669,25 +671,25 @@ public class ConfigureMapMenu {
@ColorInt final int selectedProfileColor) {
final List<RenderingRuleProperty> ps = new ArrayList<>();
final List<OsmandSettings.CommonPreference<Boolean>> prefs = new ArrayList<>();
final List<CommonPreference<Boolean>> prefs = new ArrayList<>();
Iterator<RenderingRuleProperty> it = customRules.iterator();
while (it.hasNext()) {
RenderingRuleProperty p = it.next();
if (category.equals(p.getCategory()) && p.isBoolean()) {
ps.add(p);
final OsmandSettings.CommonPreference<Boolean> pref = activity.getMyApplication().getSettings()
final CommonPreference<Boolean> pref = activity.getMyApplication().getSettings()
.getCustomRenderBooleanProperty(p.getAttrName());
prefs.add(pref);
it.remove();
}
}
if (prefs.size() > 0) {
final List<OsmandSettings.CommonPreference<String>> includedPrefs = new ArrayList<>();
final List<CommonPreference<String>> includedPrefs = new ArrayList<>();
if (customRulesIncluded != null) {
for (RenderingRuleProperty p : customRulesIncluded) {
if (!p.isBoolean()) {
final OsmandSettings.CommonPreference<String> pref = activity.getMyApplication().getSettings()
final CommonPreference<String> pref = activity.getMyApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
includedPrefs.add(pref);
}
@ -729,14 +731,14 @@ public class ConfigureMapMenu {
.setId(id)
.setIcon(icon).setListener(clickListener);
boolean selected = false;
for (OsmandSettings.CommonPreference<Boolean> p : prefs) {
for (CommonPreference<Boolean> p : prefs) {
if (p.get()) {
selected = true;
break;
}
}
if (!selected && includedPrefs.size() > 0) {
for (OsmandSettings.CommonPreference<String> p : includedPrefs) {
for (CommonPreference<String> p : includedPrefs) {
if (!Algorithms.isEmpty(p.get())) {
selected = true;
break;
@ -773,17 +775,17 @@ public class ConfigureMapMenu {
return null;
}
protected String getDescription(final List<OsmandSettings.CommonPreference<Boolean>> prefs,
final List<OsmandSettings.CommonPreference<String>> includedPrefs) {
protected String getDescription(final List<CommonPreference<Boolean>> prefs,
final List<CommonPreference<String>> includedPrefs) {
int count = 0;
int enabled = 0;
for (OsmandSettings.CommonPreference<Boolean> p : prefs) {
for (CommonPreference<Boolean> p : prefs) {
count++;
if (p.get()) {
enabled++;
}
}
for (OsmandSettings.CommonPreference<String> p : includedPrefs) {
for (CommonPreference<String> p : includedPrefs) {
count++;
if (!Algorithms.isEmpty(p.get())) {
enabled++;
@ -856,11 +858,11 @@ public class ConfigureMapMenu {
prefs.get(i).set(tempPrefs[i]);
selected |= tempPrefs[i];
}
final List<OsmandSettings.CommonPreference<String>> includedPrefs = new ArrayList<>();
final List<CommonPreference<String>> includedPrefs = new ArrayList<>();
if (customRulesIncluded != null) {
for (RenderingRuleProperty p : customRulesIncluded) {
if (p.getAttrName().equals(HIKING_ROUTES_OSMC_ATTR)) {
final OsmandSettings.CommonPreference<String> pref = activity.getMyApplication().getSettings()
final CommonPreference<String> pref = activity.getMyApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
includedPrefs.add(pref);
if (hikingRouteOSMCValue == 0) {
@ -894,7 +896,7 @@ public class ConfigureMapMenu {
if (customRulesIncluded != null) {
for (RenderingRuleProperty p : customRulesIncluded) {
if (!p.isBoolean()) {
final OsmandSettings.CommonPreference<String> pref = activity.getMyApplication().getSettings()
final CommonPreference<String> pref = activity.getMyApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
View spinnerView = View.inflate(new ContextThemeWrapper(activity, themeRes), R.layout.spinner_rule_layout, null);
@ -1031,7 +1033,7 @@ public class ConfigureMapMenu {
final String propertyDescr = SettingsActivity.getStringPropertyDescription(view.getContext(),
p.getAttrName(), p.getName());
if (p.isBoolean()) {
final OsmandSettings.CommonPreference<Boolean> pref = view.getApplication().getSettings()
final CommonPreference<Boolean> pref = view.getApplication().getSettings()
.getCustomRenderBooleanProperty(p.getAttrName());
return ContextMenuItem.createBuilder(propertyName)
.setId(id)
@ -1047,7 +1049,7 @@ public class ConfigureMapMenu {
.setSelected(pref.get())
.createItem();
} else {
final OsmandSettings.CommonPreference<String> pref = view.getApplication().getSettings()
final CommonPreference<String> pref = view.getApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
final String descr;
if (!Algorithms.isEmpty(pref.get())) {

View file

@ -27,7 +27,7 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemTwoChoicesButton.OnBo
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRuleStorageProperties;

View file

@ -13,7 +13,7 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.helpers.ImportHelper;
import net.osmand.plus.importfiles.ImportHelper;
public class ImportGpxBottomSheetDialogFragment extends MenuBottomSheetDialogFragment {

View file

@ -10,8 +10,9 @@ import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.LayerTransparencySeekbarMode;
import net.osmand.plus.rastermaps.LayerTransparencySeekbarMode;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityLayers;
@ -39,9 +40,9 @@ public class RasterMapMenu {
final OsmandSettings settings = app.getSettings();
final OsmandRasterMapsPlugin plugin = OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class);
assert plugin != null;
final OsmandSettings.CommonPreference<Integer> mapTransparencyPreference;
final OsmandSettings.CommonPreference<String> mapTypePreference;
final OsmandSettings.CommonPreference<String> exMapTypePreference;
final CommonPreference<Integer> mapTransparencyPreference;
final CommonPreference<String> mapTypePreference;
final CommonPreference<String> exMapTypePreference;
final LayerTransparencySeekbarMode currentMapTypeSeekbarMode =
type == RasterMapType.OVERLAY ? LayerTransparencySeekbarMode.OVERLAY : LayerTransparencySeekbarMode.UNDERLAY;
@StringRes final int mapTypeString;
@ -62,7 +63,7 @@ public class RasterMapMenu {
throw new RuntimeException("Unexpected raster map type");
}
final OsmandSettings.CommonPreference<Boolean> hidePolygonsPref =
final CommonPreference<Boolean> hidePolygonsPref =
mapActivity.getMyApplication().getSettings().getCustomRenderBooleanProperty("noPolygons");
String mapTypeDescr = mapTypePreference.get();
@ -181,8 +182,8 @@ public class RasterMapMenu {
@NonNull
public static Boolean isSeekbarVisible(OsmandApplication app, RasterMapType type) {
final OsmandSettings.LayerTransparencySeekbarMode currentMapTypeSeekbarMode =
type == RasterMapType.OVERLAY ? OsmandSettings.LayerTransparencySeekbarMode.OVERLAY : OsmandSettings.LayerTransparencySeekbarMode.UNDERLAY;
final LayerTransparencySeekbarMode currentMapTypeSeekbarMode =
type == RasterMapType.OVERLAY ? LayerTransparencySeekbarMode.OVERLAY : LayerTransparencySeekbarMode.UNDERLAY;
LayerTransparencySeekbarMode seekbarMode = app.getSettings().LAYER_TRANSPARENCY_SEEKBAR_MODE.get();
return seekbarMode == LayerTransparencySeekbarMode.UNDEFINED || seekbarMode == currentMapTypeSeekbarMode;
}

View file

@ -19,7 +19,7 @@ import androidx.fragment.app.FragmentManager;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;

View file

@ -5,6 +5,7 @@ import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
@ -22,7 +23,7 @@ import net.osmand.map.WorldRegion;
import net.osmand.map.WorldRegion.RegionParams;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.base.BasicProgressAsyncTask;
@ -58,8 +59,8 @@ public class DownloadIndexesThread {
private ConcurrentLinkedQueue<IndexItem> indexItemDownloading = new ConcurrentLinkedQueue<IndexItem>();
private IndexItem currentDownloadingItem = null;
private int currentDownloadingItemProgress = 0;
private DownloadResources indexes;
private static final int THREAD_ID = 10103;
public interface DownloadEvents {
@ -336,6 +337,7 @@ public class DownloadIndexesThread {
@Override
protected DownloadResources doInBackground(Void... params) {
TrafficStats.setThreadStatsTag(THREAD_ID);
DownloadResources result = null;
DownloadOsmandIndexesHelper.IndexFileList indexFileList = DownloadOsmandIndexesHelper.getIndexesList(ctx);
if (indexFileList != null) {

View file

@ -21,6 +21,7 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.IProgress;
import net.osmand.plus.OnDismissDialogFragmentListener;
import net.osmand.plus.OsmandApplication;
@ -71,7 +72,7 @@ public class DataStoragePlaceDialogFragment extends BottomSheetDialogFragment {
File internalStorage = getInternalStorageDirectory(activity);
File external1Storage = getExternal1StorageDirectory(activity);
if (external1Storage != null && external1Storage.exists() && OsmandSettings.isWritable(external1Storage)) {
if (external1Storage != null && external1Storage.exists() && FileUtils.isWritable(external1Storage)) {
deviceStorage = external1Storage;
deviceStorageType = OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE;
deviceStorageName = getString(R.string.storage_directory_external);
@ -246,7 +247,7 @@ public class DataStoragePlaceDialogFragment extends BottomSheetDialogFragment {
};
public boolean saveFilesLocation(int type, File selectedFile, Activity context) {
boolean wr = OsmandSettings.isWritable(selectedFile);
boolean wr = FileUtils.isWritable(selectedFile);
if (wr) {
((OsmandApplication) context.getApplication())
.setExternalStorageDirectory(type, selectedFile.getAbsolutePath());

View file

@ -1,20 +1,6 @@
package net.osmand.plus.activities;
package net.osmand.plus.helpers;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings.DayNightMode;
import net.osmand.util.SunriseSunset;
import org.apache.commons.logging.Log;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
@ -22,6 +8,20 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.LocationManager;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.helpers.enums.DayNightMode;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.util.SunriseSunset;
import org.apache.commons.logging.Log;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
/**
* Class to help determine if we want to render day or night map - it uses the
* DayNightMode enumeration for its behavior<BR>

View file

@ -80,6 +80,10 @@ import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.helpers.enums.SpeedConstants;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
@ -93,7 +97,6 @@ import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.router.RouteStatisticsHelper;
@ -514,9 +517,9 @@ public class GpxUiHelper {
} else {
final View apprTitleView = View.inflate(new ContextThemeWrapper(activity, themeRes), R.layout.select_gpx_appearance_title, null);
final OsmandSettings.CommonPreference<String> prefWidth
final CommonPreference<String> prefWidth
= app.getSettings().getCustomRenderProperty(CURRENT_TRACK_WIDTH_ATTR);
final OsmandSettings.CommonPreference<String> prefColor
final CommonPreference<String> prefColor
= app.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR);
updateAppearanceTitle(activity, app, trackWidthProp, renderer, apprTitleView, prefWidth.get(), prefColor.get());
@ -574,7 +577,7 @@ public class GpxUiHelper {
if (SHOW_START_FINISH_ATTR.equals(entry.getKey())) {
app.getSettings().SHOW_START_FINISH_ICONS.set("true".equals(entry.getValue()));
} else {
final OsmandSettings.CommonPreference<String> pref
final CommonPreference<String> pref
= app.getSettings().getCustomRenderProperty(entry.getKey());
pref.set(entry.getValue());
}
@ -1039,7 +1042,7 @@ public class GpxUiHelper {
private static float setupAxisDistance(OsmandApplication ctx, AxisBase axisBase, float meters) {
OsmandSettings settings = ctx.getSettings();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
MetricsConstants mc = settings.METRIC_SYSTEM.get();
float divX;
String format1 = "{0,number,0.#} ";
@ -1048,10 +1051,10 @@ public class GpxUiHelper {
float granularity = 1f;
int mainUnitStr;
float mainUnitInMeters;
if (mc == OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS) {
if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
mainUnitStr = R.string.km;
mainUnitInMeters = METERS_IN_KILOMETER;
} else if (mc == OsmandSettings.MetricsConstants.NAUTICAL_MILES) {
} else if (mc == MetricsConstants.NAUTICAL_MILES) {
mainUnitStr = R.string.nm;
mainUnitInMeters = METERS_IN_ONE_NAUTICALMILE;
} else {
@ -1065,10 +1068,10 @@ public class GpxUiHelper {
if (meters >= 100 * mainUnitInMeters ||
meters > 9.99f * mainUnitInMeters ||
meters > 0.999f * mainUnitInMeters ||
mc == OsmandSettings.MetricsConstants.MILES_AND_FEET && meters > 0.249f * mainUnitInMeters ||
mc == OsmandSettings.MetricsConstants.MILES_AND_METERS && meters > 0.249f * mainUnitInMeters ||
mc == OsmandSettings.MetricsConstants.MILES_AND_YARDS && meters > 0.249f * mainUnitInMeters ||
mc == OsmandSettings.MetricsConstants.NAUTICAL_MILES && meters > 0.99f * mainUnitInMeters) {
mc == MetricsConstants.MILES_AND_FEET && meters > 0.249f * mainUnitInMeters ||
mc == MetricsConstants.MILES_AND_METERS && meters > 0.249f * mainUnitInMeters ||
mc == MetricsConstants.MILES_AND_YARDS && meters > 0.249f * mainUnitInMeters ||
mc == MetricsConstants.NAUTICAL_MILES && meters > 0.99f * mainUnitInMeters) {
divX = mainUnitInMeters;
if (fmt == null) {
@ -1078,13 +1081,13 @@ public class GpxUiHelper {
} else {
fmt = null;
granularity = 1f;
if (mc == OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS || mc == OsmandSettings.MetricsConstants.MILES_AND_METERS) {
if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == MetricsConstants.MILES_AND_METERS) {
divX = 1f;
mainUnitStr = R.string.m;
} else if (mc == OsmandSettings.MetricsConstants.MILES_AND_FEET) {
} else if (mc == MetricsConstants.MILES_AND_FEET) {
divX = 1f / FEET_IN_ONE_METER;
mainUnitStr = R.string.foot;
} else if (mc == OsmandSettings.MetricsConstants.MILES_AND_YARDS) {
} else if (mc == MetricsConstants.MILES_AND_YARDS) {
divX = 1f / YARDS_IN_ONE_METER;
mainUnitStr = R.string.yard;
} else {
@ -1306,8 +1309,8 @@ public class GpxUiHelper {
boolean drawFilled,
boolean calcWithoutGaps) {
OsmandSettings settings = ctx.getSettings();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
boolean useFeet = (mc == OsmandSettings.MetricsConstants.MILES_AND_FEET) || (mc == OsmandSettings.MetricsConstants.MILES_AND_YARDS);
MetricsConstants mc = settings.METRIC_SYSTEM.get();
boolean useFeet = (mc == MetricsConstants.MILES_AND_FEET) || (mc == MetricsConstants.MILES_AND_YARDS);
boolean light = settings.isLightContent();
final float convEle = useFeet ? 3.28084f : 1.0f;
@ -1408,19 +1411,19 @@ public class GpxUiHelper {
divX = setupAxisDistance(ctx, xAxis, calcWithoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance);
}
OsmandSettings.SpeedConstants sps = settings.SPEED_SYSTEM.get();
SpeedConstants sps = settings.SPEED_SYSTEM.get();
float mulSpeed = Float.NaN;
float divSpeed = Float.NaN;
final String mainUnitY = sps.toShortString(ctx);
if (sps == OsmandSettings.SpeedConstants.KILOMETERS_PER_HOUR) {
if (sps == SpeedConstants.KILOMETERS_PER_HOUR) {
mulSpeed = 3.6f;
} else if (sps == OsmandSettings.SpeedConstants.MILES_PER_HOUR) {
} else if (sps == SpeedConstants.MILES_PER_HOUR) {
mulSpeed = 3.6f * METERS_IN_KILOMETER / METERS_IN_ONE_MILE;
} else if (sps == OsmandSettings.SpeedConstants.NAUTICALMILES_PER_HOUR) {
} else if (sps == SpeedConstants.NAUTICALMILES_PER_HOUR) {
mulSpeed = 3.6f * METERS_IN_KILOMETER / METERS_IN_ONE_NAUTICALMILE;
} else if (sps == OsmandSettings.SpeedConstants.MINUTES_PER_KILOMETER) {
} else if (sps == SpeedConstants.MINUTES_PER_KILOMETER) {
divSpeed = METERS_IN_KILOMETER / 60;
} else if (sps == OsmandSettings.SpeedConstants.MINUTES_PER_MILE) {
} else if (sps == SpeedConstants.MINUTES_PER_MILE) {
divSpeed = METERS_IN_ONE_MILE / 60;
} else {
mulSpeed = 1f;
@ -1571,8 +1574,8 @@ public class GpxUiHelper {
}
OsmandSettings settings = ctx.getSettings();
boolean light = settings.isLightContent();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
boolean useFeet = (mc == OsmandSettings.MetricsConstants.MILES_AND_FEET) || (mc == OsmandSettings.MetricsConstants.MILES_AND_YARDS);
MetricsConstants mc = settings.METRIC_SYSTEM.get();
boolean useFeet = (mc == MetricsConstants.MILES_AND_FEET) || (mc == MetricsConstants.MILES_AND_YARDS);
final float convEle = useFeet ? 3.28084f : 1.0f;
final float totalDistance = calcWithoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,8 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.routing.VoiceRouter.VoiceMessageListener;
import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.routing.VoiceRouter.VoiceMessageListener;
import org.apache.commons.logging.Log;

View file

@ -24,6 +24,9 @@ import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.IntermediatePointsDialog;
import net.osmand.plus.base.PointImageDrawable;
import net.osmand.plus.helpers.enums.DrivingRegion;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.helpers.enums.SpeedConstants;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.routing.AlarmInfo;
@ -31,8 +34,6 @@ import net.osmand.plus.routing.AlarmInfo.AlarmInfoType;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.VoiceRouter;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.MetricsConstants;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
@ -193,7 +194,7 @@ public class WaypointHelper {
return found;
}
public AlarmInfo getMostImportantAlarm(OsmandSettings.SpeedConstants sc, boolean showCameras) {
public AlarmInfo getMostImportantAlarm(SpeedConstants sc, boolean showCameras) {
Location lastProjection = app.getRoutingHelper().getLastProjection();
float mxspeed = route.getCurrentMaxSpeed();
float delta = app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f;
@ -291,7 +292,7 @@ public class WaypointHelper {
}
public AlarmInfo calculateMostImportantAlarm(RouteDataObject ro, Location loc, MetricsConstants mc,
OsmandSettings.SpeedConstants sc, boolean showCameras) {
SpeedConstants sc, boolean showCameras) {
float mxspeed = ro.getMaximumSpeed(ro.bearingVsRouteDirection(loc));
float delta = app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f;
AlarmInfo speedAlarm = createSpeedAlarm(sc, mxspeed, loc, delta);
@ -331,7 +332,7 @@ public class WaypointHelper {
return null;
}
private static AlarmInfo createSpeedAlarm(OsmandSettings.SpeedConstants sc, float mxspeed, Location loc, float delta) {
private static AlarmInfo createSpeedAlarm(SpeedConstants sc, float mxspeed, Location loc, float delta) {
AlarmInfo speedAlarm = null;
if (mxspeed != 0 && loc != null && loc.hasSpeed() && mxspeed != RouteDataObject.NONE_MAX_SPEED) {
if (loc.getSpeed() > mxspeed + delta) {
@ -790,7 +791,7 @@ public class WaypointHelper {
} else if (type == ALARMS) {
//assign alarm list icons manually for now
String typeString = ((AlarmInfo) point).getType().toString();
OsmandSettings.DrivingRegion region = app.getSettings().DRIVING_REGION.get();
DrivingRegion region = app.getSettings().DRIVING_REGION.get();
if (typeString.equals("SPEED_CAMERA")) {
return AppCompatResources.getDrawable(uiCtx, R.drawable.mx_highway_speed_camera);
} else if (typeString.equals("BORDER_CONTROL")) {

View file

@ -0,0 +1,27 @@
package net.osmand.plus.helpers.enums;
import android.content.Context;
import net.osmand.plus.R;
public enum AngularConstants {
DEGREES(R.string.shared_string_degrees, "°"),
DEGREES360(R.string.shared_string_degrees, "°"),
MILLIRADS(R.string.shared_string_milliradians, "mil");
private final int key;
private final String unit;
AngularConstants(int key, String unit) {
this.key = key;
this.unit = unit;
}
public String toHumanString(Context ctx) {
return ctx.getString(key);
}
public String getUnitSymbol() {
return unit;
}
}

View file

@ -0,0 +1,19 @@
package net.osmand.plus.helpers.enums;
import net.osmand.plus.R;
public enum AutoZoomMap {
FARTHEST(R.string.auto_zoom_farthest, 1f, 15.5f),
FAR(R.string.auto_zoom_far, 1.4f, 17f),
CLOSE(R.string.auto_zoom_close, 2f, 19f);
public final float coefficient;
public final int name;
public final float maxZoom;
AutoZoomMap(int name, float coefficient, float maxZoom) {
this.name = name;
this.coefficient = coefficient;
this.maxZoom = maxZoom;
}
}

View file

@ -0,0 +1,62 @@
package net.osmand.plus.helpers.enums;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import net.osmand.plus.R;
public enum DayNightMode {
AUTO(R.string.daynight_mode_auto, R.drawable.ic_action_map_sunset),
DAY(R.string.daynight_mode_day, R.drawable.ic_action_map_day),
NIGHT(R.string.daynight_mode_night, R.drawable.ic_action_map_night),
SENSOR(R.string.daynight_mode_sensor, R.drawable.ic_action_map_light_sensor);
private final int key;
@DrawableRes
private final int drawableRes;
DayNightMode(@StringRes int key, @DrawableRes int drawableRes) {
this.key = key;
this.drawableRes = drawableRes;
}
public String toHumanString(Context ctx) {
return ctx.getString(key);
}
@DrawableRes
public int getIconRes() {
return drawableRes;
}
public boolean isSensor() {
return this == SENSOR;
}
public boolean isAuto() {
return this == AUTO;
}
public boolean isDay() {
return this == DAY;
}
public boolean isNight() {
return this == NIGHT;
}
public static DayNightMode[] possibleValues(Context context) {
SensorManager mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
Sensor mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
boolean isLightSensorEnabled = mLight != null;
if (isLightSensorEnabled) {
return DayNightMode.values();
} else {
return new DayNightMode[]{AUTO, DAY, NIGHT};
}
}
}

View file

@ -0,0 +1,62 @@
package net.osmand.plus.helpers.enums;
import android.content.Context;
import net.osmand.plus.R;
import java.util.Locale;
/**
* Class represents specific for driving region
* Signs, leftHandDriving
*/
public enum DrivingRegion {
EUROPE_ASIA(R.string.driving_region_europe_asia, MetricsConstants.KILOMETERS_AND_METERS, false),
US(R.string.driving_region_us, MetricsConstants.MILES_AND_FEET, false),
CANADA(R.string.driving_region_canada, MetricsConstants.KILOMETERS_AND_METERS, false),
UK_AND_OTHERS(R.string.driving_region_uk, MetricsConstants.MILES_AND_METERS, true),
JAPAN(R.string.driving_region_japan, MetricsConstants.KILOMETERS_AND_METERS, true),
AUSTRALIA(R.string.driving_region_australia, MetricsConstants.KILOMETERS_AND_METERS, true);
public final boolean leftHandDriving;
public final MetricsConstants defMetrics;
public final int name;
DrivingRegion(int name, MetricsConstants def, boolean leftHandDriving) {
this.name = name;
defMetrics = def;
this.leftHandDriving = leftHandDriving;
}
public boolean isAmericanTypeSigns() {
return this == DrivingRegion.AUSTRALIA ||
this == DrivingRegion.US ||
this == DrivingRegion.CANADA;
}
public String getDescription(Context ctx) {
return ctx.getString(leftHandDriving ? R.string.left_side_navigation : R.string.right_side_navigation) +
", " +
defMetrics.toHumanString(ctx).toLowerCase();
}
public static DrivingRegion getDrivingRegionByLocale() {
Locale df = Locale.getDefault();
if (df == null) {
return DrivingRegion.EUROPE_ASIA;
}
if (df.getCountry().equalsIgnoreCase(Locale.US.getCountry())) {
return DrivingRegion.US;
} else if (df.getCountry().equalsIgnoreCase(Locale.CANADA.getCountry())) {
return DrivingRegion.CANADA;
} else if (df.getCountry().equalsIgnoreCase(Locale.JAPAN.getCountry())) {
return DrivingRegion.JAPAN;
} else if (df.getCountry().equalsIgnoreCase("au")) {
return DrivingRegion.AUSTRALIA;
} else if (df.getCountry().equalsIgnoreCase(Locale.UK.getCountry())) {
return DrivingRegion.UK_AND_OTHERS;
}
return DrivingRegion.EUROPE_ASIA;
}
}

View file

@ -0,0 +1,29 @@
package net.osmand.plus.helpers.enums;
import android.content.Context;
import net.osmand.plus.R;
public enum MetricsConstants {
KILOMETERS_AND_METERS(R.string.si_km_m, "km-m"),
MILES_AND_FEET(R.string.si_mi_feet, "mi-f"),
MILES_AND_METERS(R.string.si_mi_meters, "mi-m"),
MILES_AND_YARDS(R.string.si_mi_yard, "mi-y"),
NAUTICAL_MILES(R.string.si_nm, "nm");
private final int key;
private final String ttsString;
MetricsConstants(int key, String ttsString) {
this.key = key;
this.ttsString = ttsString;
}
public String toHumanString(Context ctx) {
return ctx.getString(key);
}
public String toTTSString() {
return ttsString;
}
}

View file

@ -0,0 +1,32 @@
package net.osmand.plus.helpers.enums;
import android.content.Context;
import net.osmand.plus.R;
public enum SpeedConstants {
KILOMETERS_PER_HOUR(R.string.km_h, R.string.si_kmh, false),
MILES_PER_HOUR(R.string.mile_per_hour, R.string.si_mph, true),
METERS_PER_SECOND(R.string.m_s, R.string.si_m_s, false),
MINUTES_PER_MILE(R.string.min_mile, R.string.si_min_m, true),
MINUTES_PER_KILOMETER(R.string.min_km, R.string.si_min_km, false),
NAUTICALMILES_PER_HOUR(R.string.nm_h, R.string.si_nm_h, true);
public final int key;
public final int descr;
public final boolean imperial;
SpeedConstants(int key, int descr, boolean imperial) {
this.key = key;
this.descr = descr;
this.imperial = imperial;
}
public String toHumanString(Context ctx) {
return ctx.getString(descr);
}
public String toShortString(Context ctx) {
return ctx.getString(key);
}
}

View file

@ -0,0 +1,38 @@
package net.osmand.plus.helpers.enums;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import net.osmand.plus.R;
public enum TracksSortByMode {
BY_DATE(R.string.sort_last_modified, R.drawable.ic_action_time_start),
BY_NAME_ASCENDING(R.string.sort_name_ascending, R.drawable.ic_action_sort_by_name_ascending),
BY_NAME_DESCENDING(R.string.sort_name_descending, R.drawable.ic_action_sort_by_name_descending);
private final int iconId;
private final int nameId;
TracksSortByMode(int nameId, int iconId) {
this.nameId = nameId;
this.iconId = iconId;
}
public boolean isByName() {
return this == BY_NAME_ASCENDING || this == BY_NAME_DESCENDING;
}
public boolean isByDate() {
return this == BY_DATE;
}
@StringRes
public int getNameId() {
return nameId;
}
@DrawableRes
public int getIconId() {
return iconId;
}
}

View file

@ -0,0 +1,45 @@
package net.osmand.plus.importfiles;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import java.lang.ref.WeakReference;
abstract class BaseImportAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
protected OsmandApplication app;
protected WeakReference<FragmentActivity> activityRef;
protected ProgressDialog progress;
public BaseImportAsyncTask(@NonNull FragmentActivity activity) {
app = (OsmandApplication) activity.getApplicationContext();
activityRef = new WeakReference<>(activity);
}
@Override
protected void onPreExecute() {
showProgress();
}
protected void showProgress() {
FragmentActivity activity = activityRef.get();
if (AndroidUtils.isActivityNotDestroyed(activity)) {
String title = app.getString(R.string.loading_smth, "");
progress = ProgressDialog.show(activity, title, app.getString(R.string.loading_data));
}
}
protected void hideProgress() {
FragmentActivity activity = activityRef.get();
if (progress != null && AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
}
}

View file

@ -0,0 +1,58 @@
package net.osmand.plus.importfiles;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.data.FavouritePoint;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.R;
import java.util.List;
import static net.osmand.plus.importfiles.ImportHelper.asFavourites;
import static net.osmand.plus.myplaces.FavoritesActivity.FAV_TAB;
import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID;
class FavoritesImportTask extends BaseImportAsyncTask<Void, Void, GPXFile> {
private GPXFile gpxFile;
private String fileName;
private boolean forceImportFavourites;
public FavoritesImportTask(@NonNull FragmentActivity activity, @NonNull GPXFile gpxFile,
@NonNull String fileName, boolean forceImportFavourites) {
super(activity);
this.gpxFile = gpxFile;
this.fileName = fileName;
this.forceImportFavourites = forceImportFavourites;
}
@Override
protected GPXFile doInBackground(Void... nothing) {
List<FavouritePoint> favourites = asFavourites(app, gpxFile.getPoints(), fileName, forceImportFavourites);
FavouritesDbHelper favoritesHelper = app.getFavorites();
for (FavouritePoint favourite : favourites) {
favoritesHelper.deleteFavourite(favourite, false);
favoritesHelper.addFavourite(favourite, false);
}
favoritesHelper.sortAll();
favoritesHelper.saveCurrentPointsIntoFile();
return null;
}
@Override
protected void onPostExecute(GPXFile result) {
hideProgress();
FragmentActivity activity = activityRef.get();
if (activity != null) {
app.showToastMessage(R.string.fav_imported_sucessfully);
Intent newIntent = new Intent(activity, app.getAppCustomization().getFavoritesActivity());
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.putExtra(TAB_ID, FAV_TAB);
activity.startActivity(newIntent);
}
}
}

View file

@ -0,0 +1,59 @@
package net.osmand.plus.importfiles;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.util.Algorithms;
import java.io.FileNotFoundException;
import java.io.InputStream;
class GpxImportTask extends BaseImportAsyncTask<Void, Void, GPXFile> {
private ImportHelper importHelper;
private Uri gpxFile;
private String fileName;
private boolean save;
private boolean useImportDir;
private boolean showInDetailsActivity;
public GpxImportTask(@NonNull ImportHelper importHelper, @NonNull FragmentActivity activity,
@NonNull Uri gpxFile, @NonNull String fileName, boolean save, boolean useImportDir,
boolean showInDetailsActivity) {
super(activity);
this.importHelper = importHelper;
this.gpxFile = gpxFile;
this.fileName = fileName;
this.save = save;
this.useImportDir = useImportDir;
this.showInDetailsActivity = showInDetailsActivity;
}
@Override
protected GPXFile doInBackground(Void... nothing) {
InputStream is = null;
try {
is = app.getContentResolver().openInputStream(gpxFile);
if (is != null) {
return GPXUtilities.loadGPXFile(is);
}
} catch (FileNotFoundException e) {
//
} catch (SecurityException e) {
ImportHelper.log.error(e.getMessage(), e);
} finally {
Algorithms.closeStream(is);
}
return null;
}
@Override
protected void onPostExecute(GPXFile result) {
hideProgress();
importHelper.handleResult(result, fileName, save, useImportDir, false, showInDetailsActivity);
}
}

View file

@ -0,0 +1,83 @@
package net.osmand.plus.importfiles;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.util.Algorithms;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static net.osmand.plus.importfiles.KmlImportTask.loadGpxFromKml;
class GpxOrFavouritesImportTask extends BaseImportAsyncTask<Void, Void, GPXFile> {
private ImportHelper importHelper;
private Uri fileUri;
private String fileName;
private boolean save;
private boolean useImportDir;
private boolean forceImportFavourites;
private boolean forceImportGpx;
public GpxOrFavouritesImportTask(@NonNull ImportHelper importHelper, @NonNull FragmentActivity activity,
@NonNull Uri fileUri, String fileName, boolean save, boolean useImportDir,
boolean forceImportFavourites, boolean forceImportGpx) {
super(activity);
this.importHelper = importHelper;
this.fileUri = fileUri;
this.fileName = fileName;
this.save = save;
this.useImportDir = useImportDir;
this.forceImportFavourites = forceImportFavourites;
this.forceImportGpx = forceImportGpx;
}
@Override
protected GPXFile doInBackground(Void... nothing) {
InputStream is = null;
ZipInputStream zis = null;
try {
is = app.getContentResolver().openInputStream(fileUri);
if (is != null) {
if (fileName != null && fileName.endsWith(ImportHelper.KML_SUFFIX)) {
return loadGpxFromKml(is);
} else if (fileName != null && fileName.endsWith(ImportHelper.KMZ_SUFFIX)) {
try {
zis = new ZipInputStream(is);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().endsWith(ImportHelper.KML_SUFFIX)) {
return loadGpxFromKml(zis);
}
}
} catch (Exception e) {
return null;
}
} else {
return GPXUtilities.loadGPXFile(is);
}
}
} catch (FileNotFoundException e) {
//
} catch (SecurityException e) {
ImportHelper.log.error(e.getMessage(), e);
} finally {
Algorithms.closeStream(is);
Algorithms.closeStream(zis);
}
return null;
}
@Override
protected void onPostExecute(GPXFile result) {
hideProgress();
importHelper.importGpxOrFavourites(result, fileName, save, useImportDir, forceImportFavourites, forceImportGpx);
}
}

View file

@ -0,0 +1,675 @@
package net.osmand.plus.importfiles;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import net.osmand.CallbackWithObject;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.PlatformUtil;
import net.osmand.data.FavouritePoint;
import net.osmand.data.FavouritePoint.BackgroundType;
import net.osmand.plus.AppInitializer;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.dialogs.ImportGpxBottomSheetDialogFragment;
import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.settings.backend.SettingsHelper;
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import static android.app.Activity.RESULT_OK;
import static net.osmand.IndexConstants.BINARY_MAP_INDEX_EXT;
import static net.osmand.IndexConstants.GPX_FILE_EXT;
import static net.osmand.IndexConstants.GPX_IMPORT_DIR;
import static net.osmand.IndexConstants.GPX_INDEX_DIR;
import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT;
import static net.osmand.IndexConstants.RENDERER_INDEX_EXT;
import static net.osmand.IndexConstants.ROUTING_FILE_EXT;
import static net.osmand.IndexConstants.SQLITE_CHART_FILE_EXT;
import static net.osmand.IndexConstants.SQLITE_EXT;
import static net.osmand.IndexConstants.WPT_CHART_FILE_EXT;
import static net.osmand.data.FavouritePoint.DEFAULT_BACKGROUND_TYPE;
import static net.osmand.plus.myplaces.FavoritesActivity.GPX_TAB;
import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID;
/**
* @author Koen Rabaey
*/
public class ImportHelper {
public static final Log log = PlatformUtil.getLog(ImportHelper.class);
public static final String KML_SUFFIX = ".kml";
public static final String KMZ_SUFFIX = ".kmz";
public static final int IMPORT_FILE_REQUEST = 1006;
private final OsmandApplication app;
private final OsmandMapTileView mapView;
private final AppCompatActivity activity;
private OnGpxImportCompleteListener gpxImportCompleteListener;
public enum ImportType {
SETTINGS(OSMAND_SETTINGS_FILE_EXT),
ROUTING(ROUTING_FILE_EXT),
RENDERING(RENDERER_INDEX_EXT),
GPX(GPX_FILE_EXT),
KML(KML_SUFFIX),
KMZ(KMZ_SUFFIX);
ImportType(String extension) {
this.extension = extension;
}
private String extension;
public String getExtension() {
return extension;
}
}
public interface OnGpxImportCompleteListener {
void onImportComplete(boolean success);
void onSaveComplete(boolean success, GPXFile result);
}
public ImportHelper(final AppCompatActivity activity, final OsmandApplication app, final OsmandMapTileView mapView) {
this.activity = activity;
this.app = app;
this.mapView = mapView;
}
public void setGpxImportCompleteListener(OnGpxImportCompleteListener gpxImportCompleteListener) {
this.gpxImportCompleteListener = gpxImportCompleteListener;
}
public void handleContentImport(final Uri contentUri, Bundle extras, final boolean useImportDir) {
String name = getNameFromContentUri(app, contentUri);
handleFileImport(contentUri, name, extras, useImportDir);
}
public void importFavoritesFromGpx(final GPXFile gpxFile, final String fileName) {
importFavoritesImpl(gpxFile, fileName, false);
}
public void handleGpxImport(GPXFile result, String name, boolean save, boolean useImportDir) {
handleResult(result, name, save, useImportDir, false);
}
public boolean handleGpxImport(final Uri contentUri, final boolean useImportDir) {
return handleGpxImport(contentUri, useImportDir, true);
}
public boolean handleGpxImport(final Uri contentUri, final boolean useImportDir, boolean showInDetailsActivity) {
String name = getNameFromContentUri(app, contentUri);
boolean isOsmandSubdir = Algorithms.isSubDirectory(app.getAppPath(GPX_INDEX_DIR), new File(contentUri.getPath()));
if (!isOsmandSubdir && name != null) {
String nameLC = name.toLowerCase();
if (nameLC.endsWith(GPX_FILE_EXT)) {
name = name.substring(0, name.length() - GPX_FILE_EXT.length()) + GPX_FILE_EXT;
handleGpxImport(contentUri, name, true, useImportDir, showInDetailsActivity);
return true;
} else if (nameLC.endsWith(KML_SUFFIX)) {
name = name.substring(0, name.length() - KML_SUFFIX.length()) + KML_SUFFIX;
handleKmlImport(contentUri, name, true, useImportDir);
return true;
} else if (nameLC.endsWith(KMZ_SUFFIX)) {
name = name.substring(0, name.length() - KMZ_SUFFIX.length()) + KMZ_SUFFIX;
handleKmzImport(contentUri, name, true, useImportDir);
return true;
}
}
return false;
}
public void handleGpxOrFavouritesImport(@NonNull Uri uri) {
String scheme = uri.getScheme();
boolean isFileIntent = "file".equals(scheme);
boolean isContentIntent = "content".equals(scheme);
boolean isOsmandSubdir = Algorithms.isSubDirectory(app.getAppPath(GPX_INDEX_DIR), new File(uri.getPath()));
final boolean saveFile = !isFileIntent || !isOsmandSubdir;
String fileName = "";
if (isFileIntent) {
fileName = new File(uri.getPath()).getName();
} else if (isContentIntent) {
fileName = getNameFromContentUri(app, uri);
}
handleGpxOrFavouritesImport(uri, fileName, saveFile, false, true, false);
}
public void handleFileImport(Uri intentUri, String fileName, Bundle extras, boolean useImportDir) {
boolean isFileIntent = "file".equals(intentUri.getScheme());
boolean isOsmandSubdir = Algorithms.isSubDirectory(app.getAppPath(GPX_INDEX_DIR), new File(intentUri.getPath()));
boolean saveFile = !isFileIntent || !isOsmandSubdir;
if (fileName == null) {
handleUriImport(intentUri, saveFile, useImportDir);
} else if (fileName.endsWith(KML_SUFFIX)) {
handleKmlImport(intentUri, fileName, saveFile, useImportDir);
} else if (fileName.endsWith(KMZ_SUFFIX)) {
handleKmzImport(intentUri, fileName, saveFile, useImportDir);
} else if (fileName.endsWith(BINARY_MAP_INDEX_EXT)) {
handleObfImport(intentUri, fileName);
} else if (fileName.endsWith(SQLITE_EXT)) {
handleSqliteTileImport(intentUri, fileName);
} else if (fileName.endsWith(OSMAND_SETTINGS_FILE_EXT)) {
handleOsmAndSettingsImport(intentUri, fileName, extras, null);
} else if (fileName.endsWith(ROUTING_FILE_EXT)) {
handleXmlFileImport(intentUri, fileName, null);
} else if (fileName.endsWith(WPT_CHART_FILE_EXT)) {
handleGpxOrFavouritesImport(intentUri, fileName.replace(WPT_CHART_FILE_EXT, GPX_FILE_EXT), saveFile, useImportDir, false, true);
} else if (fileName.endsWith(SQLITE_CHART_FILE_EXT)) {
handleSqliteTileImport(intentUri, fileName.replace(SQLITE_CHART_FILE_EXT, SQLITE_EXT));
} else {
handleGpxOrFavouritesImport(intentUri, fileName, saveFile, useImportDir, false, false);
}
}
public static String getNameFromContentUri(OsmandApplication app, Uri contentUri) {
try {
String name;
Cursor returnCursor = app.getContentResolver().query(contentUri, new String[] {OpenableColumns.DISPLAY_NAME}, null, null, null);
if (returnCursor != null && returnCursor.moveToFirst()) {
int columnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (columnIndex != -1) {
name = returnCursor.getString(columnIndex);
} else {
name = contentUri.getLastPathSegment();
}
} else {
name = null;
}
if (returnCursor != null && !returnCursor.isClosed()) {
returnCursor.close();
}
return name;
} catch (RuntimeException e) {
log.error(e.getMessage(), e);
return null;
}
}
private void handleGpxImport(Uri gpxFile, String fileName, boolean save, boolean useImportDir, boolean showInDetailsActivity) {
executeImportTask(new GpxImportTask(this, activity, gpxFile, fileName, save, useImportDir, showInDetailsActivity));
}
protected void handleGpxOrFavouritesImport(Uri fileUri, String fileName, boolean save, boolean useImportDir,
boolean forceImportFavourites, boolean forceImportGpx) {
executeImportTask(new GpxOrFavouritesImportTask(this, activity, fileUri, fileName, save, useImportDir, forceImportFavourites, forceImportGpx));
}
private void importFavoritesImpl(GPXFile gpxFile, String fileName, boolean forceImportFavourites) {
executeImportTask(new FavoritesImportTask(activity, gpxFile, fileName, forceImportFavourites));
}
protected void handleKmzImport(Uri kmzFile, String name, boolean save, boolean useImportDir) {
executeImportTask(new KmzImportTask(this, activity, kmzFile, name, save, useImportDir));
}
private void handleKmlImport(Uri kmlFile, String name, boolean save, boolean useImportDir) {
executeImportTask(new KmlImportTask(this, activity, kmlFile, name, save, useImportDir));
}
protected void handleObfImport(Uri obfFile, String name) {
executeImportTask(new ObfImportTask(activity, obfFile, name));
}
protected void handleSqliteTileImport(Uri uri, String name) {
executeImportTask(new SqliteTileImportTask(activity, uri, name));
}
private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras, CallbackWithObject<List<SettingsItem>> callback) {
if (extras != null && extras.containsKey(SettingsHelper.SETTINGS_VERSION_KEY) && extras.containsKey(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY)) {
int version = extras.getInt(SettingsHelper.SETTINGS_VERSION_KEY, -1);
String latestChanges = extras.getString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY);
handleOsmAndSettingsImport(intentUri, fileName, latestChanges, version, callback);
} else {
handleOsmAndSettingsImport(intentUri, fileName, null, -1, callback);
}
}
protected void handleOsmAndSettingsImport(Uri uri, String name, String latestChanges, int version,
CallbackWithObject<List<SettingsItem>> callback) {
executeImportTask(new SettingsImportTask(activity, uri, name, latestChanges, version, callback));
}
protected void handleXmlFileImport(Uri intentUri, String fileName, CallbackWithObject routingCallback) {
executeImportTask(new XmlImportTask(activity, intentUri, fileName, routingCallback));
}
private void handleUriImport(Uri uri, boolean save, boolean useImportDir) {
executeImportTask(new UriImportTask(this, activity, uri, save, useImportDir));
}
protected void handleZipImport(Uri uri, boolean save, boolean useImportDir) {
executeImportTask(new ZipImportTask(this, activity, uri, save, useImportDir));
}
@Nullable
public static String copyFile(OsmandApplication app, @NonNull File dest, @NonNull Uri uri, boolean overwrite) {
if (dest.exists() && !overwrite) {
return app.getString(R.string.file_with_name_already_exists);
}
String error = null;
InputStream in = null;
OutputStream out = null;
try {
in = app.getContentResolver().openInputStream(uri);
if (in != null) {
out = new FileOutputStream(dest);
Algorithms.streamCopy(in, out);
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
error = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
error = e.getMessage();
} catch (SecurityException e) {
e.printStackTrace();
error = e.getMessage();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return error;
}
public void chooseFileToImport(final ImportType importType, final CallbackWithObject callback) {
final MapActivity mapActivity = getMapActivity();
if (mapActivity == null) {
return;
}
final OsmandApplication app = mapActivity.getMyApplication();
Intent intent = ImportHelper.getImportTrackIntent();
ActivityResultListener listener = new ActivityResultListener(IMPORT_FILE_REQUEST, new ActivityResultListener.OnActivityResultListener() {
@Override
public void onResult(int resultCode, Intent resultData) {
MapActivity mapActivity = getMapActivity();
if (resultCode == RESULT_OK) {
Uri data = resultData.getData();
if (mapActivity == null || data == null) {
return;
}
String scheme = data.getScheme();
String fileName = "";
if ("file".equals(scheme)) {
final String path = data.getPath();
if (path != null) {
fileName = new File(path).getName();
}
} else if ("content".equals(scheme)) {
fileName = getNameFromContentUri(app, data);
}
if (fileName.endsWith(importType.getExtension())) {
if (importType.equals(ImportType.SETTINGS)) {
handleOsmAndSettingsImport(data, fileName, resultData.getExtras(), callback);
} else if (importType.equals(ImportType.ROUTING)) {
handleXmlFileImport(data, fileName, callback);
}
} else {
app.showToastMessage(app.getString(R.string.not_support_file_type_with_ext,
importType.getExtension().replaceAll("\\.", "").toUpperCase()));
}
}
}
});
mapActivity.registerActivityResultListener(listener);
mapActivity.startActivityForResult(intent, IMPORT_FILE_REQUEST);
}
public static Intent getImportTrackIntent() {
Intent intent = new Intent();
String action;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
action = Intent.ACTION_OPEN_DOCUMENT;
} else {
action = Intent.ACTION_GET_CONTENT;
}
intent.setAction(action);
intent.setType("*/*");
return intent;
}
protected void handleResult(GPXFile result, String name, boolean save,
boolean useImportDir, boolean forceImportFavourites) {
handleResult(result, name, save, useImportDir, forceImportFavourites, true);
}
protected void handleResult(final GPXFile result, final String name, final boolean save,
final boolean useImportDir, boolean forceImportFavourites, boolean showInDetailsActivity) {
if (result != null) {
if (result.error != null) {
Toast.makeText(activity, result.error.getMessage(), Toast.LENGTH_LONG).show();
if (gpxImportCompleteListener != null) {
gpxImportCompleteListener.onImportComplete(false);
}
} else {
if (save) {
executeImportTask(new SaveAsyncTask(result, name, useImportDir, showInDetailsActivity));
} else {
showGpxInDetailsActivity(result);
}
if (gpxImportCompleteListener != null) {
gpxImportCompleteListener.onImportComplete(true);
}
}
} else {
new AlertDialog.Builder(activity)
.setTitle(R.string.shared_string_import2osmand)
.setMessage(R.string.import_gpx_failed_descr)
.setNeutralButton(R.string.shared_string_permissions, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromParts("package", app.getPackageName(), null);
intent.setData(uri);
app.startActivity(intent);
if (gpxImportCompleteListener != null) {
gpxImportCompleteListener.onImportComplete(false);
}
}
})
.setNegativeButton(R.string.shared_string_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (gpxImportCompleteListener != null) {
gpxImportCompleteListener.onImportComplete(false);
}
}
})
.show();
}
if (forceImportFavourites) {
final Intent newIntent = new Intent(activity, app.getAppCustomization().getFavoritesActivity());
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.putExtra(TAB_ID, GPX_TAB);
activity.startActivity(newIntent);
}
}
private String saveImport(final GPXFile gpxFile, final String fileName, final boolean useImportDir) {
final String warning;
if (gpxFile.isEmpty() || fileName == null) {
warning = app.getString(R.string.error_reading_gpx);
} else {
final File importDir;
if (useImportDir) {
importDir = app.getAppPath(GPX_IMPORT_DIR);
} else {
importDir = app.getAppPath(GPX_INDEX_DIR);
}
//noinspection ResultOfMethodCallIgnored
importDir.mkdirs();
if (importDir.exists() && importDir.isDirectory() && importDir.canWrite()) {
final WptPt pt = gpxFile.findPointToShow();
final File toWrite = getFileToSave(fileName, importDir, pt);
boolean destinationExists = toWrite.exists();
Exception e = GPXUtilities.writeGpxFile(toWrite, gpxFile);
if (e == null) {
gpxFile.path = toWrite.getAbsolutePath();
File file = new File(gpxFile.path);
if (!destinationExists) {
GpxDataItem item = new GpxDataItem(file, gpxFile);
app.getGpxDbHelper().add(item);
} else {
GpxDataItem item = app.getGpxDbHelper().getItem(file);
if (item != null) {
app.getGpxDbHelper().clearAnalysis(item);
}
}
warning = null;
} else {
warning = app.getString(R.string.error_reading_gpx);
}
} else {
warning = app.getString(R.string.sd_dir_not_accessible);
}
}
return warning;
}
private File getFileToSave(final String fileName, final File importDir, final WptPt pt) {
final StringBuilder builder = new StringBuilder(fileName);
if ("".equals(fileName)) {
builder.append("import_").append(new SimpleDateFormat("HH-mm_EEE", Locale.US).format(new Date(pt.time))).append(GPX_FILE_EXT); //$NON-NLS-1$
}
if (fileName.endsWith(KML_SUFFIX)) {
builder.replace(builder.length() - KML_SUFFIX.length(), builder.length(), GPX_FILE_EXT);
} else if (fileName.endsWith(KMZ_SUFFIX)) {
builder.replace(builder.length() - KMZ_SUFFIX.length(), builder.length(), GPX_FILE_EXT);
} else if (!fileName.endsWith(GPX_FILE_EXT)) {
builder.append(GPX_FILE_EXT);
}
return new File(importDir, builder.toString());
}
private class SaveAsyncTask extends AsyncTask<Void, Void, String> {
private final GPXFile result;
private final String name;
private final boolean useImportDir;
private boolean showInDetailsActivity;
private SaveAsyncTask(GPXFile result, final String name, boolean useImportDir, boolean showInDetailsActivity) {
this.result = result;
this.name = name;
this.useImportDir = useImportDir;
this.showInDetailsActivity = showInDetailsActivity;
}
@Override
protected String doInBackground(Void... nothing) {
return saveImport(result, name, useImportDir);
}
@Override
protected void onPostExecute(final String warning) {
boolean success = Algorithms.isEmpty(warning);
if (gpxImportCompleteListener != null) {
gpxImportCompleteListener.onSaveComplete(success, result);
}
if (success) {
if (showInDetailsActivity) {
showGpxInDetailsActivity(result);
} else {
showPlanRouteFragment();
}
} else {
Toast.makeText(activity, warning, Toast.LENGTH_LONG).show();
}
}
private void showPlanRouteFragment() {
MeasurementToolFragment.showInstance(activity.getSupportFragmentManager(), result);
}
}
private MapActivity getMapActivity() {
if (activity instanceof MapActivity) {
return (MapActivity) activity;
} else {
return null;
}
}
private void showGpxInDetailsActivity(final GPXFile gpxFile) {
if (gpxFile.path != null) {
Intent newIntent = new Intent(activity, app.getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxFile.path);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(newIntent);
}
}
private void showGpxOnMap(final GPXFile result) {
if (mapView != null && getMapActivity() != null) {
app.getSelectedGpxHelper().setGpxFileToDisplay(result);
final WptPt moveTo = result.findPointToShow();
if (moveTo != null) {
mapView.getAnimatedDraggingThread().startMoving(moveTo.lat, moveTo.lon, mapView.getZoom(), true);
}
mapView.refreshMap();
if (getMapActivity().getDashboard().isVisible()) {
getMapActivity().getDashboard().refreshContent(true);
}
}
}
protected void importGpxOrFavourites(final GPXFile gpxFile, final String fileName, final boolean save,
final boolean useImportDir, final boolean forceImportFavourites,
final boolean forceImportGpx) {
if (gpxFile == null || gpxFile.isPointsEmpty()) {
if (forceImportFavourites) {
final DialogInterface.OnClickListener importAsTrackListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
handleResult(gpxFile, fileName, save, useImportDir, true);
break;
case DialogInterface.BUTTON_NEGATIVE:
dialog.dismiss();
break;
}
}
};
new AlertDialog.Builder(activity)
.setTitle(R.string.import_track)
.setMessage(activity.getString(R.string.import_track_desc, fileName))
.setPositiveButton(R.string.shared_string_import, importAsTrackListener)
.setNegativeButton(R.string.shared_string_cancel, importAsTrackListener)
.show();
} else {
handleResult(gpxFile, fileName, save, useImportDir, false);
}
return;
}
if (forceImportFavourites) {
importFavoritesImpl(gpxFile, fileName, true);
} else if (fileName != null) {
if (forceImportGpx) {
handleResult(gpxFile, fileName, save, useImportDir, false);
} else {
ImportGpxBottomSheetDialogFragment fragment = new ImportGpxBottomSheetDialogFragment();
fragment.setUsedOnMap(true);
fragment.setImportHelper(this);
fragment.setGpxFile(gpxFile);
fragment.setFileName(fileName);
fragment.setSave(save);
fragment.setUseImportDir(useImportDir);
activity.getSupportFragmentManager().beginTransaction()
.add(fragment, ImportGpxBottomSheetDialogFragment.TAG)
.commitAllowingStateLoss();
}
}
}
protected static List<FavouritePoint> asFavourites(OsmandApplication app, List<WptPt> wptPts, String fileName, boolean forceImportFavourites) {
final List<FavouritePoint> favourites = new ArrayList<>();
for (WptPt p : wptPts) {
if (p.name != null) {
final String fpCat;
if (p.category == null) {
if (forceImportFavourites) {
fpCat = fileName;
} else {
fpCat = "";
}
} else {
fpCat = p.category;
}
final FavouritePoint fp = new FavouritePoint(p.lat, p.lon, p.name, fpCat);
if (p.desc != null) {
fp.setDescription(p.desc);
}
fp.setAddress(p.getExtensionsToRead().get("address"));
fp.setColor(p.getColor(0));
fp.setIconIdFromName(app, p.getIconName());
fp.setBackgroundType(BackgroundType.getByTypeName(p.getBackgroundType(), DEFAULT_BACKGROUND_TYPE));
favourites.add(fp);
}
}
return favourites;
}
@SuppressWarnings("unchecked")
private <P> void executeImportTask(final AsyncTask<P, ?, ?> importTask, final P... requests) {
if (app.isApplicationInitializing()) {
app.getAppInitializer().addListener(new AppInitializer.AppInitializeListener() {
@Override
public void onProgress(AppInitializer init, AppInitializer.InitEvents event) {
}
@Override
public void onFinish(AppInitializer init) {
importTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, requests);
}
});
} else {
importTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, requests);
}
}
}

View file

@ -0,0 +1,71 @@
package net.osmand.plus.importfiles;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.plus.helpers.Kml2Gpx;
import net.osmand.util.Algorithms;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
class KmlImportTask extends BaseImportAsyncTask<Void, Void, GPXFile> {
private ImportHelper importHelper;
private Uri uri;
private String name;
private boolean save;
private boolean useImportDir;
public KmlImportTask(@NonNull ImportHelper importHelper, @NonNull FragmentActivity activity,
@NonNull Uri uri, String name, boolean save, boolean useImportDir) {
super(activity);
this.importHelper = importHelper;
this.uri = uri;
this.name = name;
this.save = save;
this.useImportDir = useImportDir;
}
@Override
protected GPXFile doInBackground(Void... nothing) {
InputStream is = null;
try {
is = app.getContentResolver().openInputStream(uri);
if (is != null) {
return loadGpxFromKml(is);
}
} catch (FileNotFoundException e) {
//
} catch (SecurityException e) {
ImportHelper.log.error(e.getMessage(), e);
} finally {
Algorithms.closeStream(is);
}
return null;
}
@Override
protected void onPostExecute(GPXFile result) {
hideProgress();
importHelper.handleResult(result, name, save, useImportDir, false);
}
protected static GPXFile loadGpxFromKml(@NonNull InputStream is) {
String result = Kml2Gpx.toGpx(is);
if (result != null) {
try {
return GPXUtilities.loadGPXFile(new ByteArrayInputStream(result.getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
return null;
}
}
return null;
}
}

View file

@ -0,0 +1,66 @@
package net.osmand.plus.importfiles;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.util.Algorithms;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static net.osmand.plus.importfiles.ImportHelper.KML_SUFFIX;
import static net.osmand.plus.importfiles.KmlImportTask.loadGpxFromKml;
class KmzImportTask extends BaseImportAsyncTask<Void, Void, GPXFile> {
private ImportHelper importHelper;
private Uri uri;
private String name;
private boolean save;
private boolean useImportDir;
public KmzImportTask(@NonNull ImportHelper importHelper, @NonNull FragmentActivity activity,
@NonNull Uri uri, @NonNull String name, boolean save, boolean useImportDir) {
super(activity);
this.importHelper = importHelper;
this.uri = uri;
this.name = name;
this.save = save;
this.useImportDir = useImportDir;
}
@Override
protected GPXFile doInBackground(Void... voids) {
InputStream is = null;
ZipInputStream zis = null;
try {
is = app.getContentResolver().openInputStream(uri);
if (is != null) {
zis = new ZipInputStream(is);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().endsWith(KML_SUFFIX)) {
return loadGpxFromKml(is);
}
}
}
} catch (Exception e) {
ImportHelper.log.error(e.getMessage(), e);
} finally {
Algorithms.closeStream(is);
Algorithms.closeStream(zis);
}
return null;
}
@Override
protected void onPostExecute(GPXFile result) {
hideProgress();
importHelper.handleResult(result, name, save, useImportDir, false);
}
}

View file

@ -0,0 +1,52 @@
package net.osmand.plus.importfiles;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import net.osmand.IProgress;
import net.osmand.IndexConstants;
import net.osmand.plus.R;
import java.io.File;
import java.util.ArrayList;
class ObfImportTask extends BaseImportAsyncTask<Void, Void, String> {
private Uri uri;
private String name;
public ObfImportTask(@NonNull FragmentActivity activity, @NonNull Uri uri, @NonNull String name) {
super(activity);
this.uri = uri;
this.name = name;
}
@Override
protected String doInBackground(Void... voids) {
String error = ImportHelper.copyFile(app, getObfDestFile(name), uri, false);
if (error == null) {
app.getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, new ArrayList<String>());
app.getDownloadThread().updateLoadedFiles();
return app.getString(R.string.map_imported_successfully);
}
return app.getString(R.string.map_import_error) + ": " + error;
}
@Override
protected void onPostExecute(String message) {
hideProgress();
app.showShortToastMessage(message);
}
@NonNull
private File getObfDestFile(@NonNull String name) {
if (name.endsWith(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT)) {
return app.getAppPath(IndexConstants.ROADS_INDEX_DIR + name);
} else if (name.endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
return app.getAppPath(IndexConstants.WIKI_INDEX_DIR + name);
}
return app.getAppPath(name);
}
}

Some files were not shown because too many files have changed in this diff Show more