mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-10 22:34:20 +00:00
Compare commits
263 Commits
21c9a58173
...
traffic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d64525897 | ||
|
|
4f2b479b2c | ||
|
|
a972552155 | ||
|
|
dc54c45482 | ||
|
|
1975b6a0f0 | ||
|
|
8683853f46 | ||
|
|
d7e34c2685 | ||
|
|
0028306b26 | ||
|
|
b5354fd1e3 | ||
|
|
964f82510a | ||
|
|
faf49fc574 | ||
|
|
60b1ad232a | ||
|
|
1bac0fd4fc | ||
|
|
ed6dcc5cb2 | ||
|
|
33b440dd71 | ||
|
|
6a20269819 | ||
|
|
8cd1b41cd2 | ||
|
|
2b630964d0 | ||
|
|
76ecd8209e | ||
|
|
82d2932ba0 | ||
|
|
85540133b3 | ||
|
|
6ded75de9c | ||
|
|
08e8ebd434 | ||
|
|
6c92264fb0 | ||
|
|
4ba0fc51a5 | ||
|
|
29c363a581 | ||
|
|
4973f4fed2 | ||
|
|
8cffa508f3 | ||
|
|
426a9661ab | ||
|
|
6dbde46dca | ||
|
|
7ed4a6ddd9 | ||
|
|
645ca792f7 | ||
|
|
cd64d14830 | ||
|
|
67b1d918ba | ||
|
|
48a3e5d4b0 | ||
|
|
d4c002851b | ||
|
|
9d4801886e | ||
|
|
5a26b72431 | ||
|
|
859b89e127 | ||
|
|
8fcf00b0ca | ||
|
|
5c2cedb19a | ||
|
|
67a3866529 | ||
|
|
90fdf0ed72 | ||
|
|
2b7ee4ba44 | ||
|
|
cd1201cb02 | ||
|
|
e6937b211a | ||
|
|
27ad70d729 | ||
|
|
a9700156db | ||
|
|
1d87e0e987 | ||
|
|
f7882636cd | ||
|
|
40fbea11e7 | ||
|
|
e87727c168 | ||
|
|
d82b545e30 | ||
|
|
781d973faa | ||
|
|
d6818786f7 | ||
|
|
615f57c604 | ||
|
|
af20e2b42b | ||
|
|
05f6dfad7b | ||
|
|
2b867a64a0 | ||
|
|
c0fd405798 | ||
|
|
207d6c833d | ||
|
|
d47aa09053 | ||
|
|
fbc150fae2 | ||
|
|
d88ed01bc1 | ||
|
|
3ec32e4415 | ||
|
|
9065f45b21 | ||
|
|
46d363ae24 | ||
|
|
0dc62c47dd | ||
|
|
3c9eeb9a75 | ||
|
|
ae23afd72e | ||
|
|
800cc0641b | ||
|
|
1b74062447 | ||
|
|
6a694c5d3e | ||
|
|
dda13b8d3d | ||
|
|
c1340a9941 | ||
|
|
a313526aed | ||
|
|
32d1a3a36e | ||
|
|
3a45740884 | ||
|
|
4e624bd04b | ||
|
|
a3d1ed83c3 | ||
|
|
38dbad0f7e | ||
|
|
7fe5823140 | ||
|
|
091d510ba1 | ||
|
|
f07c8d66d8 | ||
|
|
c9f50cdc72 | ||
|
|
2ed9bc1880 | ||
|
|
d098ecae15 | ||
|
|
9e06ec815e | ||
|
|
bf6cf27f8c | ||
|
|
bf36c875d5 | ||
|
|
30b2df89cd | ||
|
|
ba2d653a30 | ||
|
|
d6eacd7364 | ||
|
|
07c75e627e | ||
|
|
e7bde9aa05 | ||
|
|
5ba708caff | ||
|
|
48e8f32e01 | ||
|
|
38e98df6cc | ||
|
|
0713e22328 | ||
|
|
3ed31a575f | ||
|
|
ac87e3c585 | ||
|
|
ef806cf18a | ||
|
|
d46c0fec76 | ||
|
|
1d42d3b431 | ||
|
|
2663eda820 | ||
|
|
16708aae7f | ||
|
|
6963637b1b | ||
|
|
57f55f1022 | ||
|
|
01476d3dc7 | ||
|
|
90d7cadc3f | ||
|
|
3a6f21dbd1 | ||
|
|
221fe69840 | ||
|
|
167f0b8377 | ||
|
|
df7d507e1b | ||
|
|
fe737602d8 | ||
|
|
daa147a721 | ||
|
|
bd555afe61 | ||
|
|
73a70d943e | ||
|
|
dde50bd0a1 | ||
|
|
0106dc3fe5 | ||
|
|
034856f033 | ||
|
|
f53c794fdd | ||
|
|
dcab6ee5a0 | ||
|
|
edc15ac982 | ||
|
|
871cd73592 | ||
|
|
958be3dee6 | ||
|
|
06f63dcb9a | ||
|
|
bebac8d8a7 | ||
|
|
a25602dbe0 | ||
|
|
98796cd6f8 | ||
|
|
2729d07732 | ||
|
|
61b15d623d | ||
|
|
03d6847be3 | ||
|
|
3b1fca01e3 | ||
|
|
be3792b93a | ||
|
|
7283e4ecb4 | ||
|
|
75c7d146af | ||
|
|
d988ab3326 | ||
|
|
798affe0ef | ||
|
|
93a1f9d1a6 | ||
|
|
3f58c6ee20 | ||
|
|
a20d1453e0 | ||
|
|
e825753487 | ||
|
|
cc58eaa50a | ||
|
|
75197a11a8 | ||
|
|
d03b47bee0 | ||
|
|
daf344b27f | ||
|
|
121bdc4af8 | ||
|
|
6656c7e441 | ||
|
|
f32493faaa | ||
|
|
4f4d376a4a | ||
|
|
4324e329e5 | ||
|
|
9eeac05fdf | ||
|
|
b418cf659c | ||
|
|
964368f5d4 | ||
|
|
23922f1c2b | ||
|
|
f02b1538e7 | ||
|
|
dd65e89f8f | ||
|
|
f132022e60 | ||
|
|
247f88254e | ||
|
|
81a31d6b42 | ||
|
|
89d1365fee | ||
|
|
9fb08bdc56 | ||
|
|
371a58f6f9 | ||
|
|
af8b748c59 | ||
|
|
a43e83d280 | ||
|
|
04b2059ca0 | ||
|
|
ed15925251 | ||
|
|
173b5e1718 | ||
|
|
26aa5e5f54 | ||
|
|
f31541efb2 | ||
|
|
db3ed87b92 | ||
|
|
fbaa5470fd | ||
|
|
0681171d69 | ||
|
|
e3d86be324 | ||
|
|
ef3de2c781 | ||
|
|
d574b536ba | ||
|
|
2d3ca8014b | ||
|
|
df13e279b6 | ||
|
|
b48310e6a5 | ||
|
|
b98fe1999c | ||
|
|
d47713516d | ||
|
|
d72bd9e00e | ||
|
|
8cffe8fa64 | ||
|
|
ae5dea4a53 | ||
|
|
588332a23b | ||
|
|
3eb99e952c | ||
|
|
9f4b6d73ce | ||
|
|
488159e2f9 | ||
|
|
f30316d868 | ||
|
|
daaf52d27d | ||
|
|
ba9980ba36 | ||
|
|
5531b1129b | ||
|
|
394a6673e5 | ||
|
|
62ee9d5b46 | ||
|
|
2592bcf042 | ||
|
|
dd7ed98c1a | ||
|
|
76fce016bb | ||
|
|
7db32a9922 | ||
|
|
fa5608d874 | ||
|
|
185febd8d8 | ||
|
|
7a5ea64ea0 | ||
|
|
a4106505af | ||
|
|
083845a502 | ||
|
|
c6de2a25aa | ||
|
|
4c5fb21c33 | ||
|
|
f566f6f0ef | ||
|
|
9afb28aaa1 | ||
|
|
bd178932c1 | ||
|
|
2894218573 | ||
|
|
63f0799161 | ||
|
|
5b67d668bd | ||
|
|
f7adea08a2 | ||
|
|
c0c8d5da58 | ||
|
|
2ed300ca08 | ||
|
|
52a915211e | ||
|
|
18f1dfac45 | ||
|
|
a7897e2347 | ||
|
|
e3f5dd3ca8 | ||
|
|
de03995e77 | ||
|
|
74d79e5c8e | ||
|
|
e2aff53291 | ||
|
|
a39bdee0d1 | ||
|
|
136293c308 | ||
|
|
356b051036 | ||
|
|
c8d5a07262 | ||
|
|
e94c23d538 | ||
|
|
2ba3030366 | ||
|
|
3455050876 | ||
|
|
cf57942a0b | ||
|
|
3a713c477a | ||
|
|
edb1b7e784 | ||
|
|
53e80b9283 | ||
|
|
7107314e2f | ||
|
|
fafec070c9 | ||
|
|
d7facd5732 | ||
|
|
382e46af63 | ||
|
|
d0a9c564e4 | ||
|
|
a9ceec3995 | ||
|
|
73d61ff655 | ||
|
|
5cdf14386d | ||
|
|
2f6a8564cb | ||
|
|
80a7ed503e | ||
|
|
6e65e60c3d | ||
|
|
f041f910e7 | ||
|
|
dbf253c9d1 | ||
|
|
24d65bd37f | ||
|
|
16cb70a952 | ||
|
|
8827ec3c09 | ||
|
|
7be0b8a256 | ||
|
|
f0f847b214 | ||
|
|
2017907b1f | ||
|
|
bb410fc3bc | ||
|
|
6e8d400611 | ||
|
|
7b420def17 | ||
|
|
737d7b5643 | ||
|
|
9c93f421ac | ||
|
|
1574b5b7cb | ||
|
|
932dda6552 | ||
|
|
6f2f61b30a | ||
|
|
20c9fc5f45 | ||
|
|
be3e3d773b | ||
|
|
0fd7f8d573 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,6 +21,7 @@ data/symbols/**/symbols.sdf
|
||||
|
||||
data/bookmarks
|
||||
data/edits.xml
|
||||
data/traffic.xml
|
||||
data/World.mwm
|
||||
data/WorldCoasts.mwm
|
||||
data/world_mwm/*
|
||||
|
||||
@@ -10,6 +10,7 @@ CoMaps contributors:
|
||||
Bastian Greshake Tzovaras
|
||||
clover sage
|
||||
Harry Bond <me@hbond.xyz>
|
||||
NoelClick
|
||||
thesupertechie
|
||||
vikiawv
|
||||
Yannik Bloscheck
|
||||
|
||||
5
android/app/proguard-rules.pro
vendored
5
android/app/proguard-rules.pro
vendored
@@ -28,3 +28,8 @@
|
||||
# R8 crypts the source line numbers in all log messages.
|
||||
# https://github.com/organicmaps/organicmaps/issues/6559#issuecomment-1812039926
|
||||
-dontoptimize
|
||||
|
||||
# Keep classes for Android TraFF support
|
||||
-keep class app.organicmaps.sdk.traffxml.SourceImplV0_7 { *; }
|
||||
-keep class app.organicmaps.sdk.traffxml.SourceImplV0_8 { *; }
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
• OpenStreetMap-Daten vom 9. Dezember
|
||||
• Material 3 Design
|
||||
• Im OSM-Editor können nun Ladestationen hinzugefügt werden
|
||||
• Schuko und Typ E Ladestationen hinzugefügt
|
||||
• Verbesserte Suchvorschläge
|
||||
• Litauische und lettische Sprachankündigungen
|
||||
• Die Fahranweisungen wurden vergrößert
|
||||
• Der Zoomlevel passt sich an die Distanz zur nächsten Abbiegung an
|
||||
• Neue Anordnung der Einstellungen
|
||||
Weitere Einzelheiten auf codeberg.org/comaps/comaps/releases
|
||||
• OpenStreetMap Daten vom 17. Dezember
|
||||
• Map download server nun wählbar
|
||||
• Warnung über veraltete Karten hinzugefügt + Knopf zum updaten
|
||||
• Vermeidung von Parkplatzwegen im Routing
|
||||
• Neuer Zoombutton
|
||||
• Verbesserte Französchische Suchsynonme
|
||||
• OSM editor: Maximale Länge für OSM-Tags werden nun geprüft
|
||||
Mehr auf codeberg.org/comaps/comaps/releases
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
• OpenStreetMap data as of December 9
|
||||
• Use Material 3 themes
|
||||
• Support charging sockets in OSM Editor
|
||||
• Added schuko/type-E charge sockets
|
||||
• Improved search results ranking
|
||||
• Enabled Lithuanian and Latvian in voice announcements
|
||||
• Improved size of driving indications
|
||||
• Base zoom level on distance to next turn
|
||||
• Reordered settings
|
||||
• OpenStreetMap data as of December 17
|
||||
• Make map download server configurable
|
||||
• Added info about outdated maps and an update button to the selected place info card
|
||||
• Avoid using parking aisles for routing
|
||||
• Changed shape of zoom buttons
|
||||
• Improved French search synonyms
|
||||
• OSM editor: check length limit for OSM tags in value validation
|
||||
More details on codeberg.org/comaps/comaps/releases
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
• Datos de OpenStreetMap a fecha 9/12.
|
||||
• Uso de temas Material 3.
|
||||
• Compatibilidad con enchufes de recarga en Editor.
|
||||
• Se añaden enchufes de recarga schuko/tipo E.
|
||||
• Se mejora la búsqueda.
|
||||
• Se habilitan el lituano y el letón en las indicaciones de voz.
|
||||
• Se aumenta el tamaño de las indicaciones de conducción.
|
||||
• Nivel de zoom base según la distancia al siguiente giro.
|
||||
• Se han reordenado los ajustes.
|
||||
|
||||
Más detalles en codeberg.org/comaps/comaps/releases
|
||||
@@ -1,10 +1,8 @@
|
||||
• Données OpenStreetMap du 9 Décembre
|
||||
• Utilisation de Material 3
|
||||
• Support de l'édition des bornes de recharge dans l'éditeur OSM
|
||||
• Ajout du type de prise schuko/type-E
|
||||
• Amélioration de l'ordre des résultats de recherche
|
||||
• Ajout du lituanien et du letton dans le guidage vocal
|
||||
• Amélioration de la taille des instructions dans la navigation
|
||||
• Niveau de zoom basé sur la distance jusqu’au prochain virage
|
||||
• Réorganisation des paramètres
|
||||
Plus de détails sur codeberg.org/comaps/comaps/releases
|
||||
• Données OpenStreetMap du 17 décembre
|
||||
• Serveur de téléchargement de cartes configurable
|
||||
• Ajout d'un message d'avertissement pour les cartes trop anciennes
|
||||
• Évitement des allées de parking dans les itinéraires
|
||||
• Mise à jour de l'apparence des boutons de zooms
|
||||
• Amélioration des synonymes de recherche en français
|
||||
• Editeur OSM: vérification de la taille limite des tags OSM
|
||||
Plus d'informations sur codeberg.org/comaps/comaps/releases
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
• Podaci OpenStreetMap karte od 9. prosinca
|
||||
• Korištenje Material 3 tema
|
||||
• Podrška za utičnice za punjenje u OSM Editoru
|
||||
• Dodane šuko/tip-E utičnice
|
||||
• Poboljšano rangiranje rezultata pretraživanja
|
||||
• Omogućeni litvanski i latvijski jezici u glasovnim najavama
|
||||
• Povećana veličina indikatora vožnje
|
||||
• Razina zumiranja se mijenja ovisno o udaljenosti do sljedećeg skretanja
|
||||
• Promijenjen redoslijed postavki
|
||||
Više detalja na codeberg.org/comaps/comaps/releases
|
||||
@@ -1,10 +0,0 @@
|
||||
• Dane OpenStreetMap z 9 grudnia
|
||||
• Użycie motywów Material 3
|
||||
• Obsługa gniazd ładowania w Edytorze OSM
|
||||
• Dodane gniazda ładowania schuko/type-E
|
||||
• Poprawiony ranking wyników wyszukiwania
|
||||
• Dodane litewskie i łotewskie komunikaty głosowe
|
||||
• Poprawiony rozmiar znaków drogowych
|
||||
• Poziom powiększenia oparty na odległości do następnego manewru
|
||||
• Zmieniona kolejność ustawień
|
||||
Więcej szczegółów na codeberg.org/comaps/comaps/releases
|
||||
@@ -1,10 +1,8 @@
|
||||
• Dados OpenStreetMap atualizados em 9 de dezembro
|
||||
• Uso do estilo Material 3
|
||||
• Suporte para tomadas de carregamento no Editor OSM
|
||||
• Adição de tomadas de carregamento Schuko/Tipo E
|
||||
• Melhoria na classificação dos resultados de busca
|
||||
• Adição dos idiomas letão e lituano nas orientações por voz
|
||||
• Melhoria no tamanho das indicações de direção
|
||||
• Nível de zoom baseado em distância até a próxima curva
|
||||
• Configurações reordenadas
|
||||
• Dados OSM de 17/12
|
||||
• Servidor de download de mapas configurável
|
||||
• Adição de informações sobre mapas desatualizados e um botão de atualização ao cartão de informações do local selecionado
|
||||
• Evita o uso de corredores de estacionamento para roteamento
|
||||
• Formato dos botões de zoom alterado
|
||||
• Sinônimos de busca em francês aprimorados
|
||||
• Editor OSM: verificação do limite de comprimento das tags do OSM na validação de valores
|
||||
Mais detalhes em codeberg.org/comaps/comaps/releases
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
• Карты OpenStreetMap от 17 декабря
|
||||
• Возможность настройки сервера для скачивания карт
|
||||
• Добавлена информация об устаревании карт и кнопка обновления (при выборе места на карте)
|
||||
• Парковочные проезды больше не используются для транзитной маршрутизации
|
||||
• Изменены кнопки масштабирования карты
|
||||
• На карту добавлены ирригационные гидранты
|
||||
• Редактор OSM: проверка максимальной длины OSM тегов
|
||||
Подробнее на codeberg.org/comaps/comaps/releases
|
||||
@@ -1 +1 @@
|
||||
version: 2025.03.02-7-FDroid+25030207
|
||||
version: 2025.07.23-4-FDroid+25072304
|
||||
|
||||
@@ -62,6 +62,21 @@
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https" />
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.traffxml.traff.GET_CAPABILITIES"/>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.traffxml.traff.POLL"/>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.traffxml.traff.SUBSCRIBE"/>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.traffxml.traff.SUBSCRIPTION_CHANGE"/>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.traffxml.traff.UNSUBSCRIBE"/>
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<supports-screens
|
||||
|
||||
@@ -18,6 +18,7 @@ import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.CallSuper;
|
||||
@@ -25,7 +26,15 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.base.BaseMwmFragmentActivity;
|
||||
import app.organicmaps.dialog.CustomMapServerDialog;
|
||||
import app.organicmaps.downloader.MapManagerHelper;
|
||||
import app.organicmaps.intent.Factory;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
@@ -38,11 +47,7 @@ import app.organicmaps.sdk.util.StringUtils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -54,6 +59,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
private MaterialTextView mTvMessage;
|
||||
private LinearProgressIndicator mProgress;
|
||||
private MaterialButton mBtnDownload;
|
||||
private MaterialButton mBtnAdvanced;
|
||||
private MaterialCheckBox mChbDownloadCountry;
|
||||
|
||||
private String mCurrentCountry;
|
||||
@@ -267,6 +273,14 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
mProgress = findViewById(R.id.progressbar);
|
||||
mBtnDownload = findViewById(R.id.btn_download_resources);
|
||||
mChbDownloadCountry = findViewById(R.id.chb_download_country);
|
||||
mBtnAdvanced = findViewById(R.id.btn_advanced);
|
||||
|
||||
mBtnAdvanced.setOnClickListener(v -> {
|
||||
CustomMapServerDialog.show(this, url -> {
|
||||
prepareFilesDownload(false);
|
||||
});
|
||||
});
|
||||
mBtnAdvanced.setEnabled(true);
|
||||
|
||||
mBtnListeners = new View.OnClickListener[BTN_COUNT];
|
||||
mBtnNames = new String[BTN_COUNT];
|
||||
@@ -291,6 +305,11 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
mBtnDownload.setOnClickListener(mBtnListeners[action]);
|
||||
mBtnDownload.setText(mBtnNames[action]);
|
||||
|
||||
// Allow changing server only when idle or after an error.
|
||||
boolean advancedEnabled = (action == DOWNLOAD || action == TRY_AGAIN || action == RESUME);
|
||||
mBtnAdvanced.setEnabled(advancedEnabled);
|
||||
mBtnAdvanced.setAlpha(advancedEnabled ? 1f : 0.5f);
|
||||
}
|
||||
|
||||
private void doDownload()
|
||||
@@ -359,6 +378,9 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
|
||||
private void finishFilesDownload(int result)
|
||||
{
|
||||
mBtnAdvanced.setEnabled(true);
|
||||
mBtnAdvanced.setAlpha(1f);
|
||||
|
||||
if (result == ERR_NO_MORE_FILES)
|
||||
{
|
||||
// World and WorldCoasts has been downloaded, we should register maps again to correctly add them to the model.
|
||||
@@ -428,12 +450,16 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
.setTitle(titleId)
|
||||
.setMessage(messageId)
|
||||
.setCancelable(true)
|
||||
.setOnCancelListener((dialog) -> setAction(PAUSE))
|
||||
.setOnCancelListener((dialog) -> setAction(RESUME))
|
||||
.setPositiveButton(R.string.try_again,
|
||||
(dialog, which) -> {
|
||||
setAction(TRY_AGAIN);
|
||||
onTryAgainClicked();
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
(dialog, which) -> {
|
||||
setAction(RESUME);
|
||||
})
|
||||
.setOnDismissListener(dialog -> mAlertDialog = null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package app.organicmaps.dialog;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
|
||||
public final class CustomMapServerDialog
|
||||
{
|
||||
public interface OnUrlAppliedListener
|
||||
{
|
||||
void onUrlApplied(@NonNull String url);
|
||||
}
|
||||
|
||||
private CustomMapServerDialog() {}
|
||||
|
||||
public static void show(@NonNull Context context,
|
||||
@Nullable OnUrlAppliedListener listener)
|
||||
{
|
||||
View dialogView = LayoutInflater.from(context)
|
||||
.inflate(R.layout.dialog_custom_map_server, null);
|
||||
TextInputLayout til = dialogView.findViewById(R.id.til_custom_map_server);
|
||||
TextInputEditText edit = dialogView.findViewById(R.id.edit_custom_map_server);
|
||||
|
||||
SharedPreferences prefs =
|
||||
PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String current = prefs.getString(context.getString(R.string.pref_custom_map_download_url), "");
|
||||
edit.setText(current);
|
||||
|
||||
MaterialAlertDialogBuilder builder =
|
||||
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
|
||||
.setTitle(R.string.download_resources_custom_url_title)
|
||||
.setMessage(R.string.download_resources_custom_url_message)
|
||||
.setView(dialogView)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.save, null);
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(dlg -> {
|
||||
Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
ok.setOnClickListener(v -> {
|
||||
String url = edit.getText() != null ? edit.getText().toString().trim() : "";
|
||||
|
||||
if (!url.isEmpty()
|
||||
&& !url.startsWith("http://")
|
||||
&& !url.startsWith("https://"))
|
||||
{
|
||||
til.setError(context.getString(R.string.download_resources_custom_url_error_scheme));
|
||||
return;
|
||||
}
|
||||
|
||||
til.setError(null);
|
||||
|
||||
String normalizedUrl = Framework.normalizeServerUrl(url);
|
||||
|
||||
prefs.edit()
|
||||
.putString(context.getString(R.string.pref_custom_map_download_url), normalizedUrl)
|
||||
.apply();
|
||||
|
||||
// Apply to native
|
||||
Framework.applyCustomMapDownloadUrl(context, normalizedUrl);
|
||||
|
||||
if (listener != null)
|
||||
listener.onUrlApplied(normalizedUrl);
|
||||
|
||||
dialog.dismiss();
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ public class LayersUtils
|
||||
availableLayers.add(Mode.OUTDOORS);
|
||||
availableLayers.add(Mode.ISOLINES);
|
||||
availableLayers.add(Mode.SUBWAY);
|
||||
availableLayers.add(Mode.TRAFFIC);
|
||||
return availableLayers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,31 @@ package app.organicmaps.settings;
|
||||
import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.preference.EditTextPreference;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.MultiSelectListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.dialog.CustomMapServerDialog;
|
||||
import app.organicmaps.downloader.OnmapDownloader;
|
||||
import app.organicmaps.editor.LanguagesFragment;
|
||||
import app.organicmaps.editor.ProfileActivity;
|
||||
@@ -28,6 +42,7 @@ import app.organicmaps.sdk.routing.RoutingOptions;
|
||||
import app.organicmaps.sdk.search.SearchRecents;
|
||||
import app.organicmaps.sdk.settings.MapLanguageCode;
|
||||
import app.organicmaps.sdk.settings.UnitLocale;
|
||||
import app.organicmaps.sdk.traffxml.AndroidTransport;
|
||||
import app.organicmaps.sdk.util.Config;
|
||||
import app.organicmaps.sdk.util.NetworkPolicy;
|
||||
import app.organicmaps.sdk.util.PowerManagment;
|
||||
@@ -35,11 +50,12 @@ import app.organicmaps.sdk.util.SharedPropertiesUtils;
|
||||
import app.organicmaps.sdk.util.log.LogsManager;
|
||||
import app.organicmaps.util.ThemeSwitcher;
|
||||
import app.organicmaps.util.Utils;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements LanguagesFragment.Listener
|
||||
{
|
||||
@@ -61,6 +77,10 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
initAutoDownloadPrefsCallbacks();
|
||||
initLargeFontSizePrefsCallbacks();
|
||||
initTransliterationPrefsCallbacks();
|
||||
initTrafficHttpEnabledPrefsCallbacks();
|
||||
initTrafficHttpUrlPrefsCallbacks();
|
||||
initTrafficAppsPrefs();
|
||||
initTrafficLegacyEnabledPrefsCallbacks();
|
||||
init3dModePrefsCallbacks();
|
||||
initPerspectivePrefsCallbacks();
|
||||
initAutoZoomPrefsCallbacks();
|
||||
@@ -73,6 +93,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
initScreenSleepEnabledPrefsCallbacks();
|
||||
initShowOnLockScreenPrefsCallbacks();
|
||||
initLeftButtonPrefs();
|
||||
initCustomMapDownloadUrlPrefsCallbacks();
|
||||
}
|
||||
|
||||
private void initLeftButtonPrefs()
|
||||
@@ -136,6 +157,46 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
pref.setSummary(locale.getDisplayLanguage());
|
||||
}
|
||||
|
||||
private void updateTrafficHttpUrlSummary()
|
||||
{
|
||||
final Preference pref = getPreference(getString(R.string.pref_traffic_http_url));
|
||||
String summary = Config.getTrafficHttpUrl();
|
||||
if (summary.length() == 0)
|
||||
pref.setSummary(R.string.traffic_http_url_not_set);
|
||||
else
|
||||
pref.setSummary(summary);
|
||||
}
|
||||
|
||||
private void updateTrafficAppsSummary()
|
||||
{
|
||||
final MultiSelectListPreference pref = getPreference(getString(R.string.pref_traffic_apps));
|
||||
/*
|
||||
* If the preference is disabled, it has not been initialized. This is the case if no TraFF
|
||||
* apps were found. The code below would crash when trying to access the entries, and there
|
||||
* is no need to update the summary if the setting cannot be changed.
|
||||
*/
|
||||
if (!pref.isEnabled())
|
||||
return;
|
||||
String[] apps = Config.getTrafficApps();
|
||||
if (apps.length == 0)
|
||||
pref.setSummary(R.string.traffic_apps_none_selected);
|
||||
else
|
||||
{
|
||||
String summary = "";
|
||||
for (int i = 0; i < apps.length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
summary = summary + ", ";
|
||||
int index = pref.findIndexOfValue(apps[i]);
|
||||
if (i >= 0)
|
||||
summary = summary + pref.getEntries()[index];
|
||||
else
|
||||
summary = summary + apps[i];
|
||||
}
|
||||
pref.setSummary(summary);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRoutingSettingsPrefsSummary()
|
||||
{
|
||||
final Preference pref = getPreference(getString(R.string.prefs_routing));
|
||||
@@ -163,6 +224,8 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
updateVoiceInstructionsPrefsSummary();
|
||||
updateRoutingSettingsPrefsSummary();
|
||||
updateMapLanguageCodeSummary();
|
||||
updateTrafficHttpUrlSummary();
|
||||
updateTrafficAppsSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -224,6 +287,91 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
});
|
||||
}
|
||||
|
||||
private void initTrafficHttpEnabledPrefsCallbacks()
|
||||
{
|
||||
final Preference pref = getPreference(getString(R.string.pref_traffic_http_enabled));
|
||||
|
||||
((TwoStatePreference)pref).setChecked(Config.getTrafficHttpEnabled());
|
||||
pref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
final boolean oldVal = Config.getTrafficHttpEnabled();
|
||||
final boolean newVal = (Boolean) newValue;
|
||||
if (oldVal != newVal)
|
||||
Config.setTrafficHttpEnabled(newVal);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initTrafficHttpUrlPrefsCallbacks()
|
||||
{
|
||||
final Preference pref = getPreference(getString(R.string.pref_traffic_http_url));
|
||||
|
||||
((EditTextPreference)pref).setText(Config.getTrafficHttpUrl());
|
||||
pref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
final String oldVal = Config.getTrafficHttpUrl();
|
||||
final String newVal = (String) newValue;
|
||||
if (!oldVal.equals(newVal))
|
||||
Config.setTrafficHttpUrl(newVal);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initTrafficAppsPrefs()
|
||||
{
|
||||
final MultiSelectListPreference pref = getPreference(getString(R.string.pref_traffic_apps));
|
||||
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
List<ResolveInfo> receivers = pm.queryBroadcastReceivers(new Intent(AndroidTransport.ACTION_TRAFF_GET_CAPABILITIES), 0);
|
||||
|
||||
if (receivers == null || receivers.isEmpty())
|
||||
{
|
||||
pref.setSummary(R.string.traffic_apps_not_available);
|
||||
pref.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
pref.setEnabled(true);
|
||||
|
||||
List<String> entryList = new ArrayList<>(receivers.size());
|
||||
List<String> valueList = new ArrayList<>(receivers.size());
|
||||
|
||||
for (ResolveInfo receiver : receivers)
|
||||
{
|
||||
// friendly name
|
||||
entryList.add(receiver.loadLabel(pm).toString());
|
||||
// actual value (we just need the package name, broadcasts are sent to any receiver in the package)
|
||||
valueList.add(receiver.activityInfo.applicationInfo.packageName);
|
||||
}
|
||||
|
||||
pref.setEntries(entryList.toArray(new CharSequence[0]));
|
||||
pref.setEntryValues(valueList.toArray(new CharSequence[0]));
|
||||
|
||||
pref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
// newValue is a Set<String>, each item is a package ID
|
||||
String[] apps = ((Set<String>)newValue).toArray(new String[0]);
|
||||
Config.setTrafficApps(apps);
|
||||
updateTrafficAppsSummary();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initTrafficLegacyEnabledPrefsCallbacks()
|
||||
{
|
||||
final Preference pref = getPreference(getString(R.string.pref_traffic_legacy_enabled));
|
||||
|
||||
((TwoStatePreference)pref).setChecked(Config.getTrafficLegacyEnabled());
|
||||
pref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
final boolean oldVal = Config.getTrafficLegacyEnabled();
|
||||
final boolean newVal = (Boolean) newValue;
|
||||
if (oldVal != newVal)
|
||||
Config.setTrafficLegacyEnabled(newVal);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initUseMobileDataPrefsCallbacks()
|
||||
{
|
||||
final ListPreference mobilePref = getPreference(getString(R.string.pref_use_mobile_data));
|
||||
@@ -535,6 +683,34 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
});
|
||||
}
|
||||
|
||||
private void initCustomMapDownloadUrlPrefsCallbacks()
|
||||
{
|
||||
Preference customUrlPref = getPreference(getString(R.string.pref_custom_map_download_url));
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
|
||||
String current = prefs.getString(getString(R.string.pref_custom_map_download_url), "");
|
||||
String normalizedUrl = Framework.normalizeServerUrl(current);
|
||||
|
||||
// Initial summary
|
||||
customUrlPref.setSummary(normalizedUrl.isEmpty()
|
||||
? getString(R.string.download_resources_custom_url_summary_none)
|
||||
: normalizedUrl);
|
||||
|
||||
// Sync native
|
||||
Framework.applyCustomMapDownloadUrl(requireContext(), normalizedUrl);
|
||||
|
||||
// Show dialog
|
||||
customUrlPref.setOnPreferenceClickListener(preference -> {
|
||||
CustomMapServerDialog.show(requireContext(), url -> {
|
||||
preference.setSummary(url.isEmpty()
|
||||
? getString(R.string.download_resources_custom_url_summary_none)
|
||||
: url);
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void removePreference(@NonNull String categoryKey, @NonNull Preference preference)
|
||||
{
|
||||
final PreferenceCategory category = getPreference(categoryKey);
|
||||
|
||||
@@ -700,22 +700,27 @@ public class PlacePageView extends Fragment
|
||||
|
||||
if (shouldEnableEditPlace)
|
||||
{
|
||||
mTvEditPlace.setEnabled(true);
|
||||
mTvAddPlace.setEnabled(true);
|
||||
mTvEditPlace.setOnClickListener(this);
|
||||
mTvAddPlace.setOnClickListener(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTvEditPlace.setOnClickListener((v) -> {
|
||||
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
|
||||
});
|
||||
mTvAddPlace.setOnClickListener((v) -> {
|
||||
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
|
||||
});
|
||||
|
||||
String countryId = MapManager.nativeGetSelectedCountry();
|
||||
|
||||
if (countryId != null)
|
||||
if (countryId != null && MapManager.nativeIsMapTooOldToEdit(countryId))
|
||||
{
|
||||
// map editing is disabled because the map is too old
|
||||
mTvEditPlace.setEnabled(true);
|
||||
mTvAddPlace.setEnabled(true);
|
||||
mTvEditPlace.setOnClickListener((v) -> {
|
||||
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
|
||||
});
|
||||
mTvAddPlace.setOnClickListener((v) -> {
|
||||
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
|
||||
});
|
||||
|
||||
CountryItem map = CountryItem.fill(countryId);
|
||||
|
||||
if (map.status == CountryItem.STATUS_UPDATABLE || map.status == CountryItem.STATUS_DONE
|
||||
@@ -740,6 +745,12 @@ public class PlacePageView extends Fragment
|
||||
mapTooOldDescription.setText(R.string.place_page_app_too_old_description);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// map editing is disabled for other reasons
|
||||
mTvEditPlace.setEnabled(false);
|
||||
mTvAddPlace.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
final int editButtonColor =
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/bg_panel"/>
|
||||
<solid android:color="@color/bg_window"/>
|
||||
<corners android:radius="100dp"/>
|
||||
</shape>
|
||||
@@ -2,5 +2,5 @@
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/bg_panel"/>
|
||||
<solid android:color="@color/bg_window"/>
|
||||
</shape>
|
||||
11
android/app/src/main/res/drawable/ic_cloud_download.xml
Normal file
11
android/app/src/main/res/drawable/ic_cloud_download.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?colorControlNormal"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="960"
|
||||
android:viewportWidth="960">
|
||||
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M260,800Q169,800 104.5,737Q40,674 40,583Q40,505 87,444Q134,383 210,366Q227,294 295,229Q363,164 440,164Q473,164 496.5,187.5Q520,211 520,244L520,486L584,424L640,480L480,640L320,480L376,424L440,486L440,244Q364,258 322,317.5Q280,377 280,440L260,440Q202,440 161,481Q120,522 120,580Q120,638 161,679Q202,720 260,720L740,720Q782,720 811,691Q840,662 840,620Q840,578 811,549Q782,520 740,520L680,520L680,440Q680,392 658,350.5Q636,309 600,280L600,187Q674,222 717,290.5Q760,359 760,440L760,440L760,440Q829,448 874.5,499.5Q920,551 920,620Q920,695 867.5,747.5Q815,800 740,800L260,800ZM480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442L480,442Q480,442 480,442Q480,442 480,442Z"/>
|
||||
|
||||
</vector>
|
||||
@@ -11,6 +11,18 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@+id/button_container"
|
||||
android:layout_gravity="center">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_advanced"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_settings"
|
||||
app:iconTint="?iconTint"
|
||||
android:contentDescription="@string/download_resources_custom_url_title"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_margin="@dimen/margin_half" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
22
android/app/src/main/res/layout/dialog_custom_map_server.xml
Normal file
22
android/app/src/main/res/layout/dialog_custom_map_server.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/til_custom_map_server"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/margin_base"
|
||||
android:paddingEnd="@dimen/margin_base"
|
||||
android:paddingTop="@dimen/margin_base"
|
||||
android:paddingBottom="@dimen/margin_half"
|
||||
android:hint="@string/download_resources_custom_url_title"
|
||||
app:placeholderText="@string/download_resources_custom_url_hint"
|
||||
app:endIconMode="clear_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_custom_map_server"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textUri"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
@@ -24,7 +24,7 @@
|
||||
android:id="@+id/items_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?panel">
|
||||
android:background="?windowBackgroundForced">
|
||||
<include
|
||||
layout="@layout/item_missed_map"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
android:id="@+id/items_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?panel"
|
||||
android:background="?windowBackgroundForced"
|
||||
android:listSelector="?clickableBackground"
|
||||
android:drawSelectorOnTop="true"/>
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
android:layout_below="@id/tv__bookmark_set_title"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="@dimen/margin_quadruple"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:background="?selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingTop="@dimen/margin_quarter_plus"
|
||||
android:paddingBottom="@dimen/margin_half_plus"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="?attr/cardBackground"
|
||||
android:background="?cardBackground"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@@ -11,7 +11,6 @@
|
||||
style="@style/MwmWidget.ToolbarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?colorPrimary"
|
||||
android:gravity="end|center_vertical"
|
||||
android:theme="@style/MwmWidget.ToolbarTheme">
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
app:srcCompat="@drawable/ic_done"
|
||||
android:layout_width="?actionBarSize"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:scaleType="centerInside"
|
||||
android:contentDescription="@string/save" />
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?panel"/>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
style="@style/MwmWidget.ToolbarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?colorPrimary"
|
||||
android:gravity="end|center_vertical"
|
||||
android:theme="@style/MwmWidget.ToolbarTheme">
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?panel">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:background="?colorPrimary"
|
||||
android:elevation="@dimen/dp_0"
|
||||
app:elevation="@dimen/dp_0">
|
||||
<include
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="@dimen/altitude_chart_container_padding_left">
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:background="?dividerHorizontal"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?panel"
|
||||
android:background="?windowBackgroundForced"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_half_plus"
|
||||
android:layout_marginBottom="@dimen/margin_quarter"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:background="?selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/margin_quarter"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?panel"
|
||||
android:background="?cardBackground"
|
||||
android:padding="@dimen/margin_base"
|
||||
android:text="@string/editor_focus_map_on_location"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar_point_chooser" />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
android:id="@+id/pp_buttons_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?ppButtonsBackground"
|
||||
android:background="?windowBackgroundForced"
|
||||
android:orientation="horizontal"
|
||||
android:layout_gravity="bottom">
|
||||
<include layout="@layout/item_divider" />
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:layout_width="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_alignParentStart="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:srcCompat="?homeAsUpIndicator"
|
||||
android:scaleType="center"
|
||||
tools:src="@drawable/ic_expand_more" />
|
||||
@@ -143,7 +143,7 @@
|
||||
android:id="@+id/driving_options_btn_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/drivingOptionsViewBg"
|
||||
android:background="?drivingOptionsViewBg"
|
||||
android:foreground="@drawable/shadow_top"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
@@ -151,7 +151,7 @@
|
||||
android:id="@+id/driving_options_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:minHeight="@dimen/height_block_base">
|
||||
<LinearLayout
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
android:id="@+id/back"
|
||||
android:layout_width="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:srcCompat="?homeAsUpIndicator"
|
||||
android:scaleType="center"
|
||||
tools:src="@drawable/ic_expand_more"
|
||||
@@ -52,7 +52,7 @@
|
||||
android:layout_height="?actionBarSize"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="0"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/clear_the_search"
|
||||
android:scaleType="center"
|
||||
app:srcCompat="@drawable/ic_close"/>
|
||||
@@ -63,7 +63,7 @@
|
||||
android:layout_height="?actionBarSize"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="0"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="center"
|
||||
app:srcCompat="@drawable/ic_mic_white"
|
||||
|
||||
@@ -489,7 +489,7 @@
|
||||
<string name="placepage_edit_bookmark_button">Rediger bogmærke</string>
|
||||
<string name="placepage_personal_notes_hint">Personlige notater (tekst eller html)</string>
|
||||
<string name="editor_reset_edits_message">Kassér alle lokale ændringer?</string>
|
||||
<string name="editor_reset_edits_button">Kassér</string>
|
||||
<string name="editor_reset_edits_button">Kassér ændringer</string>
|
||||
<string name="editor_remove_place_message">Slet tilføjet sted?</string>
|
||||
<string name="editor_remove_place_button">Slet</string>
|
||||
<string name="editor_place_doesnt_exist">Stedet eksisterer ikke</string>
|
||||
|
||||
@@ -502,7 +502,7 @@
|
||||
<string name="placepage_edit_bookmark_button">Lesezeichen bearbeiten</string>
|
||||
<string name="placepage_personal_notes_hint">Persönliche Notizen (Text oder html)</string>
|
||||
<string name="editor_reset_edits_message">Alle lokalen Änderungen verwerfen?</string>
|
||||
<string name="editor_reset_edits_button">Verwerfen</string>
|
||||
<string name="editor_reset_edits_button">Änderungen verwerfen</string>
|
||||
<string name="editor_remove_place_message">Hinzugefügtes Objekt löschen?</string>
|
||||
<string name="editor_remove_place_button">Löschen</string>
|
||||
<string name="editor_place_doesnt_exist">Dieser Ort existiert nicht</string>
|
||||
@@ -902,9 +902,17 @@
|
||||
<item quantity="other">%d min</item>
|
||||
</plurals>
|
||||
<string name="editor_business_vacant_button">Geschäft steht leer</string>
|
||||
<string name="editor_mark_business_vacant_title">Geschäft als leerstehend markieren</string>
|
||||
<string name="editor_mark_business_vacant_title">Geschäft auf leerstehend setzen</string>
|
||||
<string name="editor_submit">Absenden</string>
|
||||
<string name="editor_mark_business_vacant_description">Wenn das Unternehmen ausgezogen ist und die Fläche leer und bereit für die nächste Miete ist.</string>
|
||||
<string name="editor_mark_business_vacant_description">Verwenden Sie diese Option, wenn das Geschäft ausgezogen ist und ein neues Geschäft die leerstehenden Räume übernehmen könnte.</string>
|
||||
<string name="charge_socket_schuko">Schuko</string>
|
||||
<string name="power_management">Energiemanagement</string>
|
||||
<string name="place_page_map_too_old_title">Kartendaten veraltet</string>
|
||||
<string name="place_page_map_too_old_description">Die aktuellen Kartendaten sind sehr alt, bitte aktualisiere die Karte.</string>
|
||||
<string name="place_page_app_too_old_description">Die aktuellen Kartendaten sind sehr alt, bitte aktualisiere die CoMaps-App.</string>
|
||||
<string name="place_page_update_too_old_map">Kartenregion aktualisieren</string>
|
||||
<string name="place_page_too_old_to_edit">OpenStreetMap-Bearbeitung ist deaktiviert, da die Kartendaten zu alt sind.</string>
|
||||
<string name="prefs_speed_cameras_information">Blitzerwarnungen sind in Ländern deaktiviert, in denen Warnungen durch lokale Gesetze verboten sind.</string>
|
||||
<string name="navigation_start_tts_message">"Navigation wird gestartet, Sprache der Sprachansagen: "</string>
|
||||
<string name="navigation_start_tts_disabled_message">Sprachansagen deaktiviert: TTS-Engine nicht verfügbar</string>
|
||||
</resources>
|
||||
|
||||
@@ -497,7 +497,7 @@
|
||||
<string name="placepage_edit_bookmark_button">Muuda järjehoidjat</string>
|
||||
<string name="placepage_personal_notes_hint">Isiklikud märkmed (tekst või html)</string>
|
||||
<string name="editor_reset_edits_message">Kas loobud kõigist kohalikest muudatustest?</string>
|
||||
<string name="editor_reset_edits_button">Loobu</string>
|
||||
<string name="editor_reset_edits_button">Loobu muudatustest</string>
|
||||
<string name="editor_remove_place_message">Kas kustutad lisatud koha?</string>
|
||||
<string name="editor_remove_place_button">Kustuta</string>
|
||||
<string name="editor_place_doesnt_exist">Kohta pole olemas</string>
|
||||
@@ -911,4 +911,10 @@
|
||||
<string name="place_page_update_too_old_map">Uuenda piirkonna kaardiandmeid</string>
|
||||
<string name="place_page_too_old_to_edit">Kuna kaardiandmed on liiga vanad, siis OpenStreetMapi muutmise võimalus on lülitatud välja.</string>
|
||||
<string name="navigation_start_tts_disabled_message">Hääljuhiste kasutamine on lülitatud välja: kõnesünteesimootorit pole saadaval</string>
|
||||
<string name="download_resources_custom_url_summary_none">Pole määratud</string>
|
||||
<string name="advanced">Täiendavad seadistused</string>
|
||||
<string name="download_resources_custom_url_title">Sinu oma kaardiserver</string>
|
||||
<string name="download_resources_custom_url_message">Kui tahad kasutada oma kaardiserverit, siis lisa ta siia. CoMapsi vaikimisi serveri kasutamiseks jäta tühjaks.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Palun sisesta täismahuline võrguaadress, mille alguses on https:// ja lõpus /</string>
|
||||
</resources>
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<!-- Text in About screen -->
|
||||
<string name="about_proposition_3">• آفلاین، چابک و جمع و جور</string>
|
||||
<!-- Text in About screen -->
|
||||
<string name="about_developed_by_enthusiasts">منبع کاملا باز، نه برای سود، تصمیم گیری شفاف و امور مالی شفاف.</string>
|
||||
<string name="about_developed_by_enthusiasts">ویدابُن بُوَندگ، نه ازبرای سود، وزیریدن اود تیسهای مالی رو راست.</string>
|
||||
<!-- The button that opens system location settings -->
|
||||
<string name="location_settings">پیکربندیهای گیاگ</string>
|
||||
<string name="close">بستن</string>
|
||||
<string name="unsupported_phone">متأسفانه دستگاه شما از آن پشتیبانی نمیکندبرنامه برای اجرا به OpenGL نیازمند است.</string>
|
||||
<string name="unsupported_phone">برنامه به OpenGL نیازمند است.شوربختانه، از دستگاه شما پشتیبانی نمیشود.</string>
|
||||
<string name="download">بارگیری</string>
|
||||
<!-- Used in DownloadResources startup screen -->
|
||||
<string name="not_enough_free_space_on_sdcard">لطفا مقداری از فضای ذخیرهسازی را آزاد نمایید</string>
|
||||
<string name="download_resources">قبل از استفاده از اپلیکیشن, اجازه دهید تا ما نقشه جهانی را بر روی موبایل شما دانلود کنیم. \nمقدار %s از حافظه شما اشغال می شود.</string>
|
||||
<string name="not_enough_free_space_on_sdcard">لطفا پیش از بکارگیری برنامه، نخست کمی جا در کارت SD/ویر USB آزاد کنید</string>
|
||||
<string name="download_resources">پیش از بکارگیری برنامه, لطفا نقشه پیشنمایش جهانی را بر روی دستگاه خویش بارگیری کنید.\nاندازه %s از ویر شما را میگیرد.</string>
|
||||
<string name="download_resources_continue">برو به نقشه</string>
|
||||
<string name="downloading_country_can_proceed">بارگیری میشود %1$s (%2$s). شما اکنون میتوانید\nبه نقشه بروید.</string>
|
||||
<string name="download_country_ask">بارگیری %1$s؟ (%2$s)</string>
|
||||
@@ -64,7 +64,7 @@
|
||||
<!-- "Add new bookmark list" dialog title -->
|
||||
<string name="add_new_set">افزودن پهرستی نو</string>
|
||||
<!-- Should be used in the bookmarks-only context, see bookmarks_and_tracks if tracks are also implied. -->
|
||||
<string name="bookmarks">نشانهها</string>
|
||||
<string name="bookmarks">نشانگها</string>
|
||||
<!-- "Bookmarks and Tracks" dialog title, also sync it with iphone/plist.txt -->
|
||||
<string name="bookmarks_and_tracks">نشانهها و مسیر ها</string>
|
||||
<!-- Add bookmark dialog - bookmark name -->
|
||||
@@ -138,7 +138,7 @@
|
||||
<!-- Notes field in Bookmarks view -->
|
||||
<string name="description">یادداشتها</string>
|
||||
<!-- message title of loading file -->
|
||||
<string name="load_kmz_title">در حال بارگیری نشانهها</string>
|
||||
<string name="load_kmz_title">بارگذاری نشانگها</string>
|
||||
<!-- Kmz file successful loading -->
|
||||
<string name="load_kmz_successful">نشانهها با موفقیت بارگذاری شد!شما می توانید آنها را در نقشه یا بخش مدیریت نشانهها بیابید.</string>
|
||||
<!-- Kml file loading failed -->
|
||||
@@ -784,4 +784,6 @@
|
||||
<string name="backup_interval_every_week">هفتگی</string>
|
||||
<string name="backup_interval_manual_only">خاموش (تنها به شیوه دستی)</string>
|
||||
<string name="backup_interval_every_day">روزانه</string>
|
||||
<string name="disconnect_usb_cable">برای بکارگیری CoMaps، لطفا USB را بگسلانید یا کارتویر را اندرون گذارید.</string>
|
||||
<string name="bookmark_set_name">نام پهرست نشانگها</string>
|
||||
</resources>
|
||||
|
||||
@@ -373,4 +373,6 @@
|
||||
<string name="offline_explanation_title">Mappys Dhywarlinen</string>
|
||||
<string name="category_shopping">Gwerthjiow</string>
|
||||
<string name="edit">Golegi</string>
|
||||
<string name="downloader_no_space_title">Nyns eus lowr dalghuster</string>
|
||||
<string name="translated_om_site_url">https://comaps.app/</string>
|
||||
</resources>
|
||||
|
||||
@@ -851,4 +851,6 @@
|
||||
<string name="place_page_update_too_old_map">Atjaunināt karšu apgabalu</string>
|
||||
<string name="place_page_too_old_to_edit">OpenStreetMap labošana ir atspējota, jo kartes dati ir pārāk veci.</string>
|
||||
<string name="navigation_start_tts_disabled_message">Balss norādes atspējotas: nav pieejams teksta pārveidošanas runā dzinējs</string>
|
||||
<string name="prefs_speed_cameras_information">Brīdinājumi par ātruma noteikšanas kamerā ir atspējoti valstīs, kurās šādus brīdinājumus aizliedz vietējais likums.</string>
|
||||
<string name="navigation_start_tts_message">"Uzsāk navigāciju, balss norāžu valoda: "</string>
|
||||
</resources>
|
||||
|
||||
@@ -503,7 +503,7 @@
|
||||
<string name="placepage_edit_bookmark_button">Rediger bokmerke</string>
|
||||
<string name="placepage_personal_notes_hint">Personlige notater (tekst eller html)</string>
|
||||
<string name="editor_reset_edits_message">Forkaste alle lokale endringer?</string>
|
||||
<string name="editor_reset_edits_button">Forkast</string>
|
||||
<string name="editor_reset_edits_button">Forkast endringer</string>
|
||||
<string name="editor_remove_place_message">Slette tillagt sted?</string>
|
||||
<string name="editor_remove_place_button">Slett</string>
|
||||
<string name="editor_place_doesnt_exist">Sted finnes ikke</string>
|
||||
@@ -906,4 +906,10 @@
|
||||
<string name="place_page_too_old_to_edit">OpenStreetMap-redigering er deaktivert fordi kartdataene er for gamle.</string>
|
||||
<string name="osm_note_hint">Alternativt, så kan du legge til et notat i OpenStreetMap, slik at noen andre kan redigere eller legge til stedet.</string>
|
||||
<string name="osm_note_toast">Notatet vil bli sendt til OpenStreetMap</string>
|
||||
<string name="advanced">Avansert</string>
|
||||
<string name="download_resources_custom_url_summary_none">Ikke angitt</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Angi en fullstendig nettadresse som starter med https:// og slutter med /</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_message">Overstyr standardserveren som brukes til nedlasting av kart. La det stå tomt for å bruke CoMaps standardserver.</string>
|
||||
<string name="download_resources_custom_url_title">Tilpasset kartserver</string>
|
||||
</resources>
|
||||
|
||||
@@ -88,19 +88,6 @@
|
||||
<item name="android:textAppearanceSmall">@style/TextAppearance.Small</item>
|
||||
<item name="android:textAppearanceMedium">@style/TextAppearance.Medium</item>
|
||||
<item name="android:textAppearanceLarge">@style/TextAppearance.Large</item>
|
||||
<item name="fontHeadline1">@style/TextAppearance.Headline1</item>
|
||||
<item name="fontHeadline2">@style/TextAppearance.Headline2</item>
|
||||
<item name="fontHeadline3">@style/TextAppearance.Headline3</item>
|
||||
<item name="fontHeadline4">@style/TextAppearance.Headline4</item>
|
||||
<item name="fontHeadline5">@style/TextAppearance.MaterialComponents.Headline5</item>
|
||||
<item name="fontHeadline6">@style/TextAppearance.Headline6</item>
|
||||
<item name="fontSubtitle1">@style/TextAppearance.Subtitle1</item>
|
||||
<item name="fontSubtitle2">@style/TextAppearance.Subtitle2</item>
|
||||
<item name="fontBody1">@style/TextAppearance.Body1</item>
|
||||
<item name="fontBody2">@style/TextAppearance.Body2</item>
|
||||
<item name="fontButton">@style/TextAppearance.Button</item>
|
||||
<item name="fontCaption">@style/TextAppearance.Caption</item>
|
||||
<item name="fontOverline">@style/TextAppearance.Overline</item>
|
||||
<item name="drivingOptionsViewBg">@color/bg_primary_dark</item>
|
||||
<item name="elevationProfilePropertyBg">@drawable/bg_rounded_rect</item>
|
||||
<item name="elevationProfilePropIconTint">@color/white_secondary</item>
|
||||
|
||||
@@ -909,4 +909,10 @@
|
||||
<string name="prefs_speed_cameras_information">Avisos de câmaras de velocidade estão desativados em países onde alertas estão proibidos por lei.</string>
|
||||
<string name="navigation_start_tts_message">"Iniciando Navegação, idioma das instruções por voz: "</string>
|
||||
<string name="navigation_start_tts_disabled_message">Instruções por voz desativadas: nenhum motor de TTS disponível</string>
|
||||
<string name="advanced">Avançadas</string>
|
||||
<string name="download_resources_custom_url_title">Servidor de Mapa Personalizado</string>
|
||||
<string name="download_resources_custom_url_message">Substitui o servidor de download de mapas normal. Deixe em branco para usar o servidor do CoMaps padrão.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Indefinido</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Por favor insira um URL inteiro começando com https:// e acabando com /</string>
|
||||
</resources>
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
<!-- Preference title -->
|
||||
<string name="google_play_services">Serviciul de Localizare Fuzionat Google</string>
|
||||
<!-- Preference text -->
|
||||
<string name="pref_use_google_play">Un serviciu proprietar care combină GPS, Wi-Fi, rețelele celulare etc. pentru a-ți determina locația mai precisă. Se poate conecta la serverele Google.</string>
|
||||
<string name="pref_use_google_play">Un serviciu proprietar care combină GPS, Wi-Fi, rețelele celulare etc. pentru a-ți determina locația mai precis. Se poate conecta la serverele Google.</string>
|
||||
<!-- Preference title -->
|
||||
<!-- Preference description -->
|
||||
<!-- Text for routing error dialog -->
|
||||
@@ -460,7 +460,7 @@
|
||||
<string name="osm_presentation">Date OpenStreetMap create de comunitate la data de %s. Aflați mai multe despre cum să editați și să actualizați harta la OpenStreetMap.org</string>
|
||||
<!-- OSM explanation on Android login screen -->
|
||||
<string name="login_osm_presentation">OpenStreetMap.org (OSM) este un proiect comunitar pentru construirea unei hărți libere și deschise. Este principala sursă de date cartografice în CoMaps și funcționează similar cu Wikipedia. Puteți adăuga sau edita locuri, iar acestea devin disponibile pentru milioane de utilizatori din întreaga lume. \nAlăturați-vă comunității și ajutați la crearea unei hărți mai bune pentru toată lumea!</string>
|
||||
<string name="login_to_make_edits_visible">Creați un cont OpenStreetMap sau conectați-vă pentru a vă publica edițiile de hartă în întreaga lume</string>
|
||||
<string name="login_to_make_edits_visible">Creați un cont OpenStreetMap sau conectați-vă pentru a vă publica editările hărții pentru întreaga lume</string>
|
||||
<!-- Downloaded 10 **of** 20 <- it is that "of" -->
|
||||
<string name="downloader_of">%1$d din %2$d</string>
|
||||
<string name="download_over_mobile_header">Vrei să descarci prin rețeaua de telefonie mobilă?</string>
|
||||
@@ -475,7 +475,7 @@
|
||||
<!-- Hint of the input field in the OSM note section of the editor -->
|
||||
<string name="editor_note_hint">Descrieți erorile de pe hartă sau lucrurile care nu pot fi editate cu CoMaps</string>
|
||||
<!-- Information about OSM at the top of the editing page -->
|
||||
<string name="editor_about_osm">Edițiile dvs. sunt încărcate în baza de date publică <a href="https://wiki.openstreetmap.org/wiki/About_OpenStreetMap">OpenStreetMap</a>. Vă rugăm să nu adăugați informații personale sau protejate prin drepturi de autor.</string>
|
||||
<string name="editor_about_osm">Editările dvs. sunt încărcate în baza de date publică <a href="https://wiki.openstreetmap.org/wiki/About_OpenStreetMap">OpenStreetMap</a>. Vă rugăm să nu adăugați informații personale sau protejate prin drepturi de autor.</string>
|
||||
<string name="editor_more_about_osm">Mai multe despre OpenStreetMap</string>
|
||||
<string name="editor_osm_history">Istoricul dvs. de editare</string>
|
||||
<string name="editor_osm_notes">Note privind datele hărții dvs</string>
|
||||
@@ -889,4 +889,13 @@
|
||||
<string name="list_description_empty">Editează lista ca să adaugi o descriere</string>
|
||||
<string name="charging_station_available_sockets">Conectori</string>
|
||||
<string name="charge_socket_unknown_other">Alte tipuri necunoscute</string>
|
||||
<string name="place_page_map_too_old_title">Harta este prea veche</string>
|
||||
<string name="place_page_map_too_old_description">Harta dvs. este foarte veche, vă rugăm actualizați-o.</string>
|
||||
<string name="place_page_app_too_old_description">Harta dvs. este foarte veche, vă rugăm actualizați CoMaps.</string>
|
||||
<string name="place_page_update_too_old_map">Actualizează harta</string>
|
||||
<string name="place_page_too_old_to_edit">Editarea OpenStreetMap este dezactivată pentru că harta descărcată este prea veche.</string>
|
||||
<string name="prefs_speed_cameras_information">Avertizările pentru radare sunt dezactivate unde avertizarea este interzisă de legea locală.</string>
|
||||
<string name="navigation_start_tts_disabled_message">Instrucțiuni vocale dezactivate: Nu este disponibil niciun sistem TTS</string>
|
||||
<string name="charge_socket_count">Număr</string>
|
||||
<string name="unknown_count">Necunoscut</string>
|
||||
</resources>
|
||||
|
||||
@@ -893,4 +893,5 @@
|
||||
<string name="unknown_count">bilinmiyor</string>
|
||||
<string name="error_value_must_be_positive">Değer pozitif olmalıdır</string>
|
||||
<string name="error_invalid_number">Geçersiz sayı</string>
|
||||
<string name="avoid_paved">Asfalt yollardan kaçın</string>
|
||||
</resources>
|
||||
|
||||
@@ -511,7 +511,7 @@
|
||||
<string name="placepage_edit_bookmark_button">编辑书签</string>
|
||||
<string name="placepage_personal_notes_hint">个人注记(文字或 html)</string>
|
||||
<string name="editor_reset_edits_message">舍弃所有本地更改?</string>
|
||||
<string name="editor_reset_edits_button">舍弃</string>
|
||||
<string name="editor_reset_edits_button">舍弃更改</string>
|
||||
<string name="editor_remove_place_message">删除已添加的地点?</string>
|
||||
<string name="editor_remove_place_button">删除</string>
|
||||
<string name="editor_place_doesnt_exist">该地点不存在</string>
|
||||
@@ -917,4 +917,10 @@
|
||||
<string name="place_page_app_too_old_description">您当前的地图数据非常旧,请更新 CoMaps 应用。</string>
|
||||
<string name="place_page_update_too_old_map">更新地图区域</string>
|
||||
<string name="place_page_too_old_to_edit">由于地图数据太旧,OpenStreetMap 编辑被禁用。</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">未设置</string>
|
||||
<string name="download_resources_custom_url_error_scheme">请输入以 https:// 开头、以 / 结尾的完整 URL</string>
|
||||
<string name="advanced">高级</string>
|
||||
<string name="download_resources_custom_url_title">自定义地图服务器</string>
|
||||
<string name="download_resources_custom_url_message">覆盖用于地图下载的默认地图下载服务器。留空则使用 CoMaps 默认服务器。</string>
|
||||
</resources>
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
<string name="pref_settings_general" translatable="false">GeneralSettings</string>
|
||||
<string name="pref_navigation" translatable="false">Navigation</string>
|
||||
<string name="pref_information" translatable="false">Information</string>
|
||||
<string name="pref_traffic" translatable="false">Traffic</string>
|
||||
<string name="pref_traffic_http_enabled" translatable="false">TrafficHttpEnabled</string>
|
||||
<string name="pref_traffic_http_url" translatable="false">TrafficHttpUrl</string>
|
||||
<string name="pref_traffic_apps" translatable="false">TrafficApps</string>
|
||||
<string name="pref_traffic_legacy_enabled" translatable="false">TrafficLegacyEnabled</string>
|
||||
<string name="pref_transliteration" translatable="false">Transliteration</string>
|
||||
<string name="pref_power_management" translatable="false">PowerManagment</string>
|
||||
<string name="pref_keep_screen_on" translatable="false">KeepScreenOn</string>
|
||||
@@ -43,6 +48,8 @@
|
||||
<string name="pref_backup" translatable="false">Backup</string>
|
||||
<string name="pref_left_button" translatable="false">LeftButton</string>
|
||||
<string name="pref_power" translatable="false">pref_power</string>
|
||||
<string name="pref_custom_map_download_url" translatable="false">CustomMapDownloadUrl</string>
|
||||
<string name="pref_advanced" translatable="false">pref_advanced</string>
|
||||
|
||||
<string name="notification_ticker_ltr" translatable="false">%1$s: %2$s</string>
|
||||
<string name="notification_ticker_rtl" translatable="false">%2$s :%1$s</string>
|
||||
|
||||
@@ -215,6 +215,7 @@
|
||||
<!-- Settings information group in settings screen -->
|
||||
<string name="prefs_group_information">Information</string>
|
||||
<string name="prefs_group_route">Navigation</string>
|
||||
<string name="prefs_group_traffic">Traffic information</string>
|
||||
<string name="pref_zoom_title">Zoom buttons</string>
|
||||
<string name="pref_zoom_summary">Display on the map</string>
|
||||
<!-- Settings «Map» category: «Night style» title -->
|
||||
@@ -544,7 +545,7 @@
|
||||
<string name="placepage_edit_bookmark_button">Edit Bookmark</string>
|
||||
<string name="placepage_personal_notes_hint">Personal notes (text or html)</string>
|
||||
<string name="editor_reset_edits_message">Discard all local changes?</string>
|
||||
<string name="editor_reset_edits_button">Discard</string>
|
||||
<string name="editor_reset_edits_button">Discard changes</string>
|
||||
<string name="editor_remove_place_message">Delete added place?</string>
|
||||
<string name="editor_remove_place_button">Delete</string>
|
||||
<string name="editor_place_doesnt_exist">Place does not exist</string>
|
||||
@@ -799,6 +800,24 @@
|
||||
<string name="enable_show_on_lock_screen_description">When enabled, the app will work on the lockscreen even when the device is locked.</string>
|
||||
<!-- Current language of the map! -->
|
||||
<string name="change_map_locale">Map language</string>
|
||||
<!-- Enable live traffic data via HTTP (title) -->
|
||||
<string name="traffic_http_enabled">Enable live traffic data</string>
|
||||
<!-- Enable live traffic data via HTTP (description) -->
|
||||
<string name="traffic_http_enabled_description">When enabled, the app will periodically retrieve traffic information from the configured URL.</string>
|
||||
<!-- URL for live traffic data -->
|
||||
<string name="traffic_http_url">Traffic service URL</string>
|
||||
<!-- Status message indicating that user did not set a traffic URL yet. -->
|
||||
<string name="traffic_http_url_not_set">Not set</string>
|
||||
<!-- TraFF 0.8 apps from which to receive data (title) -->
|
||||
<string name="traffic_apps">Use data from TraFF applications</string>
|
||||
<!-- Status message indicating that no TraFF 0.8 apps are installed -->
|
||||
<string name="traffic_apps_not_available">No apps installed</string>
|
||||
<!-- Status message indicating that no TraFF 0.8 apps are currently selected -->
|
||||
<string name="traffic_apps_none_selected">No apps salected</string>
|
||||
<!-- Enable traffic data from TraFF 0.7 apps (title) -->
|
||||
<string name="traffic_legacy_enabled">Use data from legacy TraFF applications</string>
|
||||
<!-- Enable traffic data from TraFF 0.7 apps (description) -->
|
||||
<string name="traffic_legacy_enabled_description">When enabled, the app will receive and process traffic data from legacy TraFF applications.</string>
|
||||
<!-- OpenStreetMap text on splash screen -->
|
||||
<string name="splash_subtitle">Map data from OpenStreetMap</string>
|
||||
<!-- Telegram group url for the "?" About page -->
|
||||
@@ -966,4 +985,12 @@
|
||||
<string name="offline_explanation_title">Offline Maps</string>
|
||||
<string name="offline_explanation_text">A map needs to be downloaded to view and navigate the area.\nDownload maps for areas you want to travel.</string>
|
||||
<string name="list_description_empty">Edit the list to add a description</string>
|
||||
<!-- Settings: Advanced group -->
|
||||
<string name="advanced">Advanced</string>
|
||||
<!-- Custom Download URL -->
|
||||
<string name="download_resources_custom_url_title">Custom Map Server</string>
|
||||
<string name="download_resources_custom_url_message">Override the default map download server used for map downloads. Leave empty to use CoMaps default server.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Not set</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Please enter a full URL starting with https:// and ending with /</string>
|
||||
</resources>
|
||||
|
||||
@@ -69,19 +69,4 @@
|
||||
<attr name="elevationProfileSelectedPointTriangle" format="reference" />
|
||||
<attr name="elevationProfileFloatingTriangle" format="reference" />
|
||||
</declare-styleable>
|
||||
<declare-styleable name="ThemeAttrs.Fonts">
|
||||
<attr name="fontHeadline1" format="reference" />
|
||||
<attr name="fontHeadline2" format="reference" />
|
||||
<attr name="fontHeadline3" format="reference" />
|
||||
<attr name="fontHeadline4" format="reference" />
|
||||
<attr name="fontHeadline5" format="reference" />
|
||||
<attr name="fontHeadline6" format="reference" />
|
||||
<attr name="fontSubtitle1" format="reference" />
|
||||
<attr name="fontSubtitle2" format="reference" />
|
||||
<attr name="fontBody1" format="reference" />
|
||||
<attr name="fontBody2" format="reference" />
|
||||
<attr name="fontButton" format="reference" />
|
||||
<attr name="fontCaption" format="reference" />
|
||||
<attr name="fontOverline" format="reference" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
||||
@@ -93,19 +93,6 @@
|
||||
<item name="android:textAppearanceSmallInverse">@style/TextAppearance.Small.Inverse</item>
|
||||
<item name="android:textAppearanceMediumInverse">@style/TextAppearance.Medium.Inverse</item>
|
||||
<item name="android:textAppearanceLargeInverse">@style/TextAppearance.Large.Inverse</item>
|
||||
<item name="fontHeadline1">@style/TextAppearance.Headline1</item>
|
||||
<item name="fontHeadline2">@style/TextAppearance.Headline2</item>
|
||||
<item name="fontHeadline3">@style/TextAppearance.Headline3</item>
|
||||
<item name="fontHeadline4">@style/TextAppearance.Headline4</item>
|
||||
<item name="fontHeadline5">@style/TextAppearance.MaterialComponents.Headline5</item>
|
||||
<item name="fontHeadline6">@style/TextAppearance.Headline6</item>
|
||||
<item name="fontSubtitle1">@style/TextAppearance.Subtitle1</item>
|
||||
<item name="fontSubtitle2">@style/TextAppearance.Subtitle2</item>
|
||||
<item name="fontBody1">@style/TextAppearance.Body1</item>
|
||||
<item name="fontBody2">@style/TextAppearance.Body2</item>
|
||||
<item name="fontButton">@style/TextAppearance.Button</item>
|
||||
<item name="fontCaption">@style/TextAppearance.Caption</item>
|
||||
<item name="fontOverline">@style/TextAppearance.Overline</item>
|
||||
<item name="drivingOptionsViewBg">@color/bg_primary_dark</item>
|
||||
<item name="elevationProfilePropertyBg">@drawable/bg_rounded_rect</item>
|
||||
<item name="elevationProfilePropIconTint">@color/black_secondary</item>
|
||||
|
||||
@@ -144,7 +144,8 @@
|
||||
</intent>
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/pref_power"
|
||||
android:title="@string/power_management"
|
||||
android:order="4">
|
||||
@@ -190,7 +191,38 @@
|
||||
android:defaultValue="true"
|
||||
android:widgetLayout="@layout/preference_switch"
|
||||
android:order="5"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceCategory>
|
||||
|
||||
<androidx.preference.PreferenceCategory
|
||||
android:key="@string/pref_traffic"
|
||||
android:title="@string/prefs_group_traffic"
|
||||
android:order="4">
|
||||
<SwitchPreferenceCompat
|
||||
android:key="@string/pref_traffic_http_enabled"
|
||||
android:title="@string/traffic_http_enabled"
|
||||
app:singleLineTitle="false"
|
||||
android:summary="@string/traffic_http_enabled_description"
|
||||
android:defaultValue="true"
|
||||
android:order="1"/>
|
||||
<EditTextPreference
|
||||
android:key="@string/pref_traffic_http_url"
|
||||
android:title="@string/traffic_http_url"
|
||||
app:singleLineTitle="false"
|
||||
android:order="2"/>
|
||||
<MultiSelectListPreference
|
||||
android:key="@string/pref_traffic_apps"
|
||||
android:title="@string/traffic_apps"
|
||||
app:singleLineTitle="false"
|
||||
android:order="3"/>
|
||||
<SwitchPreferenceCompat
|
||||
android:key="@string/pref_traffic_legacy_enabled"
|
||||
android:title="@string/traffic_legacy_enabled"
|
||||
app:singleLineTitle="false"
|
||||
android:summary="@string/traffic_legacy_enabled_description"
|
||||
android:defaultValue="true"
|
||||
android:order="4"/>
|
||||
</androidx.preference.PreferenceCategory>
|
||||
|
||||
<androidx.preference.PreferenceCategory
|
||||
android:key="@string/pref_privacy"
|
||||
android:title="@string/privacy"
|
||||
@@ -212,5 +244,18 @@
|
||||
android:defaultValue="true"
|
||||
android:widgetLayout="@layout/preference_switch"
|
||||
android:order="2"/>
|
||||
|
||||
</androidx.preference.PreferenceCategory>
|
||||
|
||||
<androidx.preference.PreferenceCategory
|
||||
android:key="@string/pref_advanced"
|
||||
android:title="@string/advanced"
|
||||
android:order="6">
|
||||
<Preference
|
||||
android:key="@string/pref_custom_map_download_url"
|
||||
android:title="@string/download_resources_custom_url_title"
|
||||
app:icon="@drawable/ic_cloud_download"
|
||||
android:order="1" />
|
||||
</androidx.preference.PreferenceCategory>
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
||||
@@ -124,6 +124,7 @@ dependencies {
|
||||
implementation libs.androidx.lifecycle.process
|
||||
implementation libs.androidx.media
|
||||
implementation libs.androidx.recyclerview
|
||||
implementation libs.androidx.preference
|
||||
implementation libs.android.material
|
||||
|
||||
testImplementation libs.junit
|
||||
|
||||
@@ -17,6 +17,7 @@ set(SRC
|
||||
app/organicmaps/sdk/opengl/gl3stub.h
|
||||
app/organicmaps/sdk/platform/GuiThread.hpp
|
||||
app/organicmaps/sdk/platform/AndroidPlatform.hpp
|
||||
app/organicmaps/sdk/traffxml/AndroidTraffSource.hpp
|
||||
app/organicmaps/sdk/util/Distance.hpp
|
||||
app/organicmaps/sdk/util/FeatureIdBuilder.hpp
|
||||
app/organicmaps/sdk/vulkan/android_vulkan_context_factory.hpp
|
||||
@@ -76,6 +77,8 @@ set(SRC
|
||||
app/organicmaps/sdk/platform/PThreadImpl.cpp
|
||||
app/organicmaps/sdk/platform/SecureStorage.cpp
|
||||
app/organicmaps/sdk/platform/SocketImpl.cpp
|
||||
app/organicmaps/sdk/traffxml/AndroidTraffSource.cpp
|
||||
app/organicmaps/sdk/traffxml/SourceImpl.cpp
|
||||
app/organicmaps/sdk/util/Config.cpp
|
||||
app/organicmaps/sdk/util/GeoUtils.cpp
|
||||
app/organicmaps/sdk/util/HttpClient.cpp
|
||||
@@ -127,6 +130,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||
# icu
|
||||
# agg
|
||||
# vulkan_wrapper
|
||||
traffxml
|
||||
|
||||
# Android libs
|
||||
log
|
||||
|
||||
@@ -42,12 +42,16 @@ using namespace std::placeholders;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unique_ptr<MapFilesDownloader> & LegacyDownloader()
|
||||
{
|
||||
static auto downloader = storage::GetDownloader();
|
||||
return downloader;
|
||||
}
|
||||
|
||||
static std::vector<platform::CountryFile> g_filesToDownload;
|
||||
static int g_totalDownloadedBytes;
|
||||
static int g_totalBytesToDownload;
|
||||
static std::shared_ptr<HttpRequest> g_currentRequest;
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C"
|
||||
@@ -152,11 +156,11 @@ JNIEXPORT jint JNICALL Java_app_organicmaps_sdk_DownloadResourcesLegacyActivity_
|
||||
return ERR_NO_MORE_FILES;
|
||||
|
||||
/// @todo One downloader instance with cached servers. All this routine will be refactored some time.
|
||||
static auto downloader = storage::GetDownloader();
|
||||
auto & downloader = LegacyDownloader();
|
||||
storage::Storage const & storage = g_framework->GetStorage();
|
||||
downloader->SetDataVersion(storage.GetCurrentDataVersion());
|
||||
|
||||
downloader->EnsureMetaConfigReady([&storage, ptr = jni::make_global_ref(listener)]()
|
||||
downloader->EnsureMetaConfigReady([&storage, ptr = jni::make_global_ref(listener), &downloader]()
|
||||
{
|
||||
auto const & curFile = g_filesToDownload.back();
|
||||
auto const fileName = curFile.GetFileName(MapFileType::Map);
|
||||
@@ -177,4 +181,12 @@ JNIEXPORT void JNICALL Java_app_organicmaps_sdk_DownloadResourcesLegacyActivity_
|
||||
LOG(LDEBUG, ("cancelCurrentFile, currentRequest=", g_currentRequest));
|
||||
g_currentRequest.reset();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_app_organicmaps_sdk_DownloadResourcesLegacyActivity_nativeResetMetaConfig(JNIEnv *,
|
||||
jclass)
|
||||
{
|
||||
auto & downloader = LegacyDownloader();
|
||||
if (downloader)
|
||||
downloader->ResetMetaConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1505,6 +1505,22 @@ JNIEXPORT void JNICALL Java_app_organicmaps_sdk_Framework_nativeGet3dMode(JNIEnv
|
||||
env->SetBooleanField(result, buildingsField, buildings);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_app_organicmaps_sdk_Framework_nativeSetCustomMapDownloadUrl(JNIEnv * env, jclass,
|
||||
jstring url)
|
||||
{
|
||||
std::string nativeUrl = jni::ToNativeString(env, url);
|
||||
GetPlatform().SetCustomMapServerUrl(nativeUrl);
|
||||
|
||||
if (g_framework)
|
||||
{
|
||||
frm()->GetStorage().ResetMapDownloadMetaConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LINFO, ("nativeSetCustomMapDownloadUrl: framework not created yet, skipping ResetMapDownloadMetaConfig"));
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_app_organicmaps_sdk_Framework_nativeSetAutoZoomEnabled(JNIEnv * env, jclass,
|
||||
jboolean enabled)
|
||||
{
|
||||
|
||||
@@ -182,6 +182,8 @@ public:
|
||||
void Set3dMode(bool allow3d, bool allow3dBuildings);
|
||||
void Get3dMode(bool & allow3d, bool & allow3dBuildings);
|
||||
|
||||
TrafficManager & GetTrafficManager() { return m_work.GetTrafficManager(); }
|
||||
|
||||
void SetMapLanguageCode(std::string const & languageCode);
|
||||
std::string GetMapLanguageCode();
|
||||
|
||||
|
||||
@@ -587,4 +587,11 @@ JNIEXPORT jstring JNICALL Java_app_organicmaps_sdk_downloader_MapManager_nativeG
|
||||
storage::CountryId const & res = g_framework->GetPlacePageInfo().GetCountryId();
|
||||
return (res == storage::kInvalidCountryId ? nullptr : jni::ToJavaString(env, res));
|
||||
}
|
||||
|
||||
// static native boolean nativeIsMapTooOldToEdit(String countryId);
|
||||
JNIEXPORT jboolean JNICALL Java_app_organicmaps_sdk_downloader_MapManager_nativeIsMapTooOldToEdit(JNIEnv *env, jclass clazz,
|
||||
jstring country_id)
|
||||
{
|
||||
return GetStorage().IsMapTooOldToEdit(jni::ToNativeString(env, country_id));
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "app/organicmaps/sdk/Framework.hpp"
|
||||
|
||||
#include "app/organicmaps/sdk/platform/AndroidPlatform.hpp"
|
||||
#include "app/organicmaps/sdk/traffxml/AndroidTraffSource.hpp"
|
||||
|
||||
#include "app/organicmaps/sdk/core/jni_helper.hpp"
|
||||
|
||||
@@ -34,6 +35,26 @@ JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeInitFramework(
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
jmethodID const methodId = jni::GetMethodID(env, *onComplete, "run", "()V");
|
||||
env->CallVoidMethod(*onComplete, methodId);
|
||||
|
||||
ASSERT(g_framework, ("g_framework must be non-null"));
|
||||
|
||||
/*
|
||||
* Add traffic sources for Android.
|
||||
*/
|
||||
jclass configClass = env->FindClass("app/organicmaps/sdk/util/Config");
|
||||
jmethodID const getTrafficLegacyEnabledId = jni::GetStaticMethodID(env, configClass,
|
||||
"getTrafficLegacyEnabled", "()Z");
|
||||
jmethodID const applyTrafficLegacyEnabledId = jni::GetStaticMethodID(env, configClass,
|
||||
"applyTrafficLegacyEnabled", "(Z)V");
|
||||
jmethodID const getTrafficAppsId = jni::GetStaticMethodID(env, configClass,
|
||||
"getTrafficApps", "()[Ljava/lang/String;");
|
||||
jmethodID const applyTrafficAppsId = jni::GetStaticMethodID(env, configClass,
|
||||
"applyTrafficApps", "([Ljava/lang/String;)V");
|
||||
|
||||
env->CallStaticVoidMethod(configClass, applyTrafficLegacyEnabledId,
|
||||
env->CallStaticBooleanMethod(configClass, getTrafficLegacyEnabledId));
|
||||
env->CallStaticVoidMethod(configClass, applyTrafficAppsId,
|
||||
(jobjectArray)env->CallStaticObjectMethod(configClass, getTrafficAppsId));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#include "AndroidTraffSource.hpp"
|
||||
|
||||
#include "app/organicmaps/sdk/core/jni_helper.hpp"
|
||||
|
||||
namespace traffxml {
|
||||
void AndroidTraffSourceV0_7::Create(TraffSourceManager & manager)
|
||||
{
|
||||
std::unique_ptr<AndroidTraffSourceV0_7> source = std::unique_ptr<AndroidTraffSourceV0_7>(new AndroidTraffSourceV0_7(manager));
|
||||
manager.RegisterSource(std::move(source));
|
||||
}
|
||||
|
||||
AndroidTraffSourceV0_7::AndroidTraffSourceV0_7(TraffSourceManager & manager)
|
||||
: TraffSource(manager)
|
||||
{
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
|
||||
static jclass const implClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/traffxml/SourceImplV0_7");
|
||||
|
||||
static jmethodID const implConstructor = jni::GetConstructorID(env, implClass, "(Landroid/content/Context;J)V");
|
||||
|
||||
jlong nativeManager = reinterpret_cast<jlong>(&manager);
|
||||
|
||||
jobject implObject = env->NewObject(
|
||||
implClass, implConstructor, android::Platform::Instance().GetContext(), nativeManager);
|
||||
|
||||
m_implObject = env->NewGlobalRef(implObject);
|
||||
|
||||
m_subscribeImpl = jni::GetMethodID(env, m_implObject, "subscribe", "(Ljava/lang/String;)V");
|
||||
m_unsubscribeImpl = jni::GetMethodID(env, m_implObject, "unsubscribe", "()V");
|
||||
}
|
||||
|
||||
AndroidTraffSourceV0_7::~AndroidTraffSourceV0_7()
|
||||
{
|
||||
jni::GetEnv()->DeleteGlobalRef(m_implObject);
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_7::Close()
|
||||
{
|
||||
Unsubscribe();
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_7::Subscribe(std::set<MwmSet::MwmId> & mwms)
|
||||
{
|
||||
jni::GetEnv()->CallVoidMethod(m_implObject, m_subscribeImpl, nullptr);
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_7::Unsubscribe()
|
||||
{
|
||||
jni::GetEnv()->CallVoidMethod(m_implObject, m_unsubscribeImpl);
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_8::Create(TraffSourceManager & manager, std::string const & packageId)
|
||||
{
|
||||
std::unique_ptr<AndroidTraffSourceV0_8> source = std::unique_ptr<AndroidTraffSourceV0_8>(new AndroidTraffSourceV0_8(manager, packageId));
|
||||
manager.RegisterSource(std::move(source));
|
||||
}
|
||||
|
||||
AndroidTraffSourceV0_8::AndroidTraffSourceV0_8(TraffSourceManager & manager, std::string const & packageId)
|
||||
: TraffSource(manager)
|
||||
{
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
|
||||
static jclass const implClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/traffxml/SourceImplV0_8");
|
||||
|
||||
static jmethodID const implConstructor = jni::GetConstructorID(env, implClass, "(Landroid/content/Context;JLjava/lang/String;)V");
|
||||
|
||||
jlong nativeManager = reinterpret_cast<jlong>(&manager);
|
||||
|
||||
jobject implObject = env->NewObject(
|
||||
implClass, implConstructor, android::Platform::Instance().GetContext(), nativeManager, jni::ToJavaString(env, packageId));
|
||||
|
||||
m_implObject = env->NewGlobalRef(implObject);
|
||||
|
||||
m_subscribeImpl = jni::GetMethodID(env, m_implObject, "subscribe", "(Ljava/lang/String;)V");
|
||||
m_changeSubscriptionImpl = jni::GetMethodID(env, m_implObject, "changeSubscription", "(Ljava/lang/String;)V");
|
||||
m_unsubscribeImpl = jni::GetMethodID(env, m_implObject, "unsubscribe", "()V");
|
||||
|
||||
// TODO packageId (if we need that at all here)
|
||||
}
|
||||
|
||||
AndroidTraffSourceV0_8::~AndroidTraffSourceV0_8()
|
||||
{
|
||||
jni::GetEnv()->DeleteGlobalRef(m_implObject);
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_8::Close()
|
||||
{
|
||||
Unsubscribe();
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_8::Subscribe(std::set<MwmSet::MwmId> & mwms)
|
||||
{
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
std::string data = "<filter_list>\n"
|
||||
+ GetMwmFilters(mwms)
|
||||
+ "</filter_list>";
|
||||
|
||||
env->CallVoidMethod(m_implObject, m_subscribeImpl, jni::ToJavaString(env, data));
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_8::ChangeSubscription(std::set<MwmSet::MwmId> & mwms)
|
||||
{
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
std::string data = "<filter_list>\n"
|
||||
+ GetMwmFilters(mwms)
|
||||
+ "</filter_list>";
|
||||
|
||||
env->CallVoidMethod(m_implObject, m_changeSubscriptionImpl, jni::ToJavaString(env, data));
|
||||
}
|
||||
|
||||
void AndroidTraffSourceV0_8::Unsubscribe()
|
||||
{
|
||||
jni::GetEnv()->CallVoidMethod(m_implObject, m_unsubscribeImpl);
|
||||
}
|
||||
} // namespace traffxml
|
||||
@@ -0,0 +1,199 @@
|
||||
#pragma once
|
||||
|
||||
#include "traffxml/traff_source.hpp"
|
||||
|
||||
namespace traffxml
|
||||
{
|
||||
/**
|
||||
* @brief A TraFF source which relies on Android Binder for message delivery, using version 0.7 of the TraFF protocol.
|
||||
*
|
||||
* TraFF 0.7 does not support subscriptions. Messages are broadcast as the payload to a `FEED` intent.
|
||||
*/
|
||||
class AndroidTraffSourceV0_7 : public TraffSource
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new `AndroidTraffSourceV0_7` instance and registers it with the traffic manager.
|
||||
*
|
||||
* @param manager The traffic manager to register the new instance with
|
||||
*/
|
||||
static void Create(TraffSourceManager & manager);
|
||||
|
||||
virtual ~AndroidTraffSourceV0_7() override;
|
||||
|
||||
/**
|
||||
* @brief Prepares the traffic source for unloading.
|
||||
*/
|
||||
// TODO do we need a close operation here?
|
||||
// TODO move this to the parent class and override it here?
|
||||
void Close();
|
||||
|
||||
/**
|
||||
* @brief Subscribes to a traffic service.
|
||||
*
|
||||
* TraFF 0.7 does not support subscriptions. This implementation registers a broadcast receiver.
|
||||
*
|
||||
* @param mwms The MWMs for which data is needed (not used by this implementation).
|
||||
*/
|
||||
virtual void Subscribe(std::set<MwmSet::MwmId> & mwms) override;
|
||||
|
||||
/**
|
||||
* @brief Changes an existing traffic subscription.
|
||||
*
|
||||
* This implementation does nothing, as TraFF 0.7 does not support subscriptions.
|
||||
*
|
||||
* @param mwms The new set of MWMs for which data is needed.
|
||||
*/
|
||||
virtual void ChangeSubscription(std::set<MwmSet::MwmId> & mwms) override {};
|
||||
|
||||
/**
|
||||
* @brief Unsubscribes from a traffic service we are subscribed to.
|
||||
*
|
||||
* TraFF 0.7 does not support subscriptions. This implementation unregisters the broadcast
|
||||
* receiver which was registered by `Subscribe()`.
|
||||
*/
|
||||
virtual void Unsubscribe() override;
|
||||
|
||||
/**
|
||||
* @brief Whether this source should be polled.
|
||||
*
|
||||
* Prior to calling `Poll()` on a source, the caller should always first call `IsPollNeeded()` and
|
||||
* poll the source only if the result is true.
|
||||
*
|
||||
* This implementation always returns false, as message delivery on Android uses `FEED` (push).
|
||||
*
|
||||
* @return true if the source should be polled, false if not.
|
||||
*/
|
||||
virtual bool IsPollNeeded() override { return false; };
|
||||
|
||||
/**
|
||||
* @brief Polls the traffic service for updates.
|
||||
*
|
||||
* This implementation does nothing, as message delivery on Android uses `FEED` (push).
|
||||
*/
|
||||
virtual void Poll() override {};
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructs a new `AndroidTraffSourceV0_7`.
|
||||
* @param manager The `TrafficSourceManager` instance to register the source with.
|
||||
*/
|
||||
AndroidTraffSourceV0_7(TraffSourceManager & manager);
|
||||
|
||||
private:
|
||||
// TODO “subscription” (i.e. broadcast receiver) state
|
||||
|
||||
/**
|
||||
* @brief The Java implementation class instance.
|
||||
*/
|
||||
jobject m_implObject;
|
||||
|
||||
/**
|
||||
* @brief The Java subscribe method.
|
||||
*/
|
||||
jmethodID m_subscribeImpl;
|
||||
|
||||
/**
|
||||
* @brief The Java unsubscribe method.
|
||||
*/
|
||||
jmethodID m_unsubscribeImpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A TraFF source which relies on Android Binder for message delivery, using version 0.8 of the TraFF protocol.
|
||||
*
|
||||
* TraFF 0.8 supports subscriptions. Messages are announced through a `FEED` intent, whereupon the
|
||||
* consumer can retrieve them from a content provider.
|
||||
*/
|
||||
class AndroidTraffSourceV0_8 : public TraffSource
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new `AndroidTraffSourceV0_8` instance and registers it with the traffic manager.
|
||||
*
|
||||
* @param manager The traffic manager to register the new instance with
|
||||
* @param packageId The package ID of the app providing the TraFF source.
|
||||
*/
|
||||
static void Create(TraffSourceManager & manager, std::string const & packageId);
|
||||
|
||||
virtual ~AndroidTraffSourceV0_8() override;
|
||||
|
||||
/**
|
||||
* @brief Prepares the traffic source for unloading.
|
||||
*
|
||||
* If there is still an active subscription, it unsubscribes, but without processing the result
|
||||
* received from the service. Otherwise, teardown is a no-op.
|
||||
*/
|
||||
// TODO move this to the parent class and override it here?
|
||||
void Close();
|
||||
|
||||
/**
|
||||
* @brief Subscribes to a traffic service.
|
||||
*
|
||||
* @param mwms The MWMs for which data is needed.
|
||||
*/
|
||||
virtual void Subscribe(std::set<MwmSet::MwmId> & mwms) override;
|
||||
|
||||
/**
|
||||
* @brief Changes an existing traffic subscription.
|
||||
*
|
||||
* @param mwms The new set of MWMs for which data is needed.
|
||||
*/
|
||||
virtual void ChangeSubscription(std::set<MwmSet::MwmId> & mwms) override;
|
||||
|
||||
/**
|
||||
* @brief Unsubscribes from a traffic service we are subscribed to.
|
||||
*/
|
||||
virtual void Unsubscribe() override;
|
||||
|
||||
/**
|
||||
* @brief Whether this source should be polled.
|
||||
*
|
||||
* Prior to calling `Poll()` on a source, the caller should always first call `IsPollNeeded()` and
|
||||
* poll the source only if the result is true.
|
||||
*
|
||||
* This implementation always returns false, as message delivery on Android uses `FEED` (push).
|
||||
*
|
||||
* @return true if the source should be polled, false if not.
|
||||
*/
|
||||
virtual bool IsPollNeeded() override { return false; };
|
||||
|
||||
/**
|
||||
* @brief Polls the traffic service for updates.
|
||||
*
|
||||
* This implementation does nothing, as message delivery on Android uses `FEED` (push).
|
||||
*/
|
||||
virtual void Poll() override {};
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructs a new `AndroidTraffSourceV0_8`.
|
||||
* @param manager The `TrafficSourceManager` instance to register the source with.
|
||||
* @param packageId The package ID of the app providing the TraFF source.
|
||||
*/
|
||||
AndroidTraffSourceV0_8(TraffSourceManager & manager, std::string const & packageId);
|
||||
|
||||
private:
|
||||
// TODO subscription state
|
||||
|
||||
/**
|
||||
* @brief The Java implementation class instance.
|
||||
*/
|
||||
jobject m_implObject;
|
||||
|
||||
/**
|
||||
* @brief The Java subscribe method.
|
||||
*/
|
||||
jmethodID m_subscribeImpl;
|
||||
|
||||
/**
|
||||
* @brief The Java changeSubscription method.
|
||||
*/
|
||||
jmethodID m_changeSubscriptionImpl;
|
||||
|
||||
/**
|
||||
* @brief The Java unsubscribe method.
|
||||
*/
|
||||
jmethodID m_unsubscribeImpl;
|
||||
};
|
||||
} // namespace traffxml
|
||||
@@ -0,0 +1,34 @@
|
||||
// TODO which of the two do we need? (jni_helper includes jni)
|
||||
//#include <jni>
|
||||
#include "app/organicmaps/sdk/core/jni_helper.hpp"
|
||||
|
||||
#include "traffxml/traff_source.hpp"
|
||||
#include "traffxml/traff_model_xml.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_sdk_traffxml_SourceImpl_onFeedReceivedImpl(JNIEnv * env, jclass thiz, jlong nativeManager, jstring feed)
|
||||
{
|
||||
std::string feedStd = jni::ToNativeString(env, feed);
|
||||
pugi::xml_document document;
|
||||
traffxml::TraffFeed parsedFeed;
|
||||
|
||||
if (!document.load_string(feedStd.c_str()))
|
||||
{
|
||||
LOG(LWARNING, ("Feed is not a well-formed XML document"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!traffxml::ParseTraff(document, std::nullopt, parsedFeed))
|
||||
{
|
||||
LOG(LWARNING, ("Feed is not a valid TraFF feed"));
|
||||
return;
|
||||
}
|
||||
|
||||
traffxml::TraffSourceManager & manager = *reinterpret_cast<traffxml::TraffSourceManager*>(nativeManager);
|
||||
manager.ReceiveFeed(parsedFeed);
|
||||
}
|
||||
}
|
||||
@@ -119,4 +119,74 @@ JNIEXPORT void JNICALL Java_app_organicmaps_sdk_util_Config_nativeSetTranslitera
|
||||
frm()->SaveTransliteration(value);
|
||||
frm()->AllowTransliteration(value);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_app_organicmaps_sdk_util_Config_nativeGetTrafficHttpEnabled(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return frm()->LoadTrafficHttpEnabled();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_sdk_util_Config_nativeSetTrafficHttpEnabled(JNIEnv * env, jclass thiz,
|
||||
jboolean value)
|
||||
{
|
||||
frm()->SaveTrafficHttpEnabled(value);
|
||||
frm()->SetTrafficHttpEnabled(value);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_app_organicmaps_sdk_util_Config_nativeGetTrafficHttpUrl(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
std::string value = frm()->LoadTrafficHttpUrl();
|
||||
return jni::ToJavaString(env, value);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_sdk_util_Config_nativeSetTrafficHttpUrl(JNIEnv * env, jclass thiz,
|
||||
jstring value)
|
||||
{
|
||||
frm()->SaveTrafficHttpUrl(jni::ToNativeString(env, value));
|
||||
frm()->SetTrafficHttpUrl(jni::ToNativeString(env, value));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_sdk_util_Config_applyTrafficLegacyEnabled(JNIEnv * env, jclass thiz,
|
||||
jboolean value)
|
||||
{
|
||||
TrafficManager & tm = g_framework->GetTrafficManager();
|
||||
tm.RemoveTraffSourceIf([](traffxml::TraffSource* source) {
|
||||
if (traffxml::AndroidTraffSourceV0_7* traffSource = dynamic_cast<traffxml::AndroidTraffSourceV0_7*>(source))
|
||||
{
|
||||
traffSource->Close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
});
|
||||
if (value)
|
||||
traffxml::AndroidTraffSourceV0_7::Create(tm);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_sdk_util_Config_applyTrafficApps(JNIEnv * env, jclass thiz, jobjectArray value)
|
||||
{
|
||||
jsize valueLen = env->GetArrayLength(value);
|
||||
TrafficManager & tm = g_framework->GetTrafficManager();
|
||||
tm.RemoveTraffSourceIf([](traffxml::TraffSource* source) {
|
||||
if (traffxml::AndroidTraffSourceV0_8* traffSource = dynamic_cast<traffxml::AndroidTraffSourceV0_8*>(source))
|
||||
{
|
||||
traffSource->Close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
});
|
||||
for (jsize i = 0; i < valueLen; i++)
|
||||
{
|
||||
jstring jAppId = (jstring)env->GetObjectArrayElement(value, i);
|
||||
std::string appId = jni::ToNativeString(env, jAppId);
|
||||
traffxml::AndroidTraffSourceV0_8::Create(tm, appId);
|
||||
env->DeleteLocalRef(jAppId);
|
||||
}
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -27,4 +27,5 @@ public class DownloadResourcesLegacyActivity
|
||||
public static native int nativeGetBytesToDownload();
|
||||
public static native int nativeStartNextFileDownload(Listener listener);
|
||||
public static native void nativeCancelCurrentFile();
|
||||
public static native void nativeResetMetaConfig();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package app.organicmaps.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Size;
|
||||
|
||||
import app.organicmaps.sdk.api.ParsedRoutingData;
|
||||
import app.organicmaps.sdk.api.ParsedSearchRequest;
|
||||
import app.organicmaps.sdk.api.RequestType;
|
||||
@@ -23,6 +26,7 @@ import app.organicmaps.sdk.routing.RoutingRecommendationListener;
|
||||
import app.organicmaps.sdk.routing.TransitRouteInfo;
|
||||
import app.organicmaps.sdk.settings.SpeedCameraMode;
|
||||
import app.organicmaps.sdk.util.Constants;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@@ -348,4 +352,20 @@ public class Framework
|
||||
|
||||
public static native void nativeMemoryWarning();
|
||||
public static native void nativeSaveRoute();
|
||||
public static native void nativeSetCustomMapDownloadUrl(String url);
|
||||
|
||||
public static void applyCustomMapDownloadUrl(@NonNull Context context, @Nullable String url)
|
||||
{
|
||||
nativeSetCustomMapDownloadUrl(normalizeServerUrl(url));
|
||||
// Reset the legacy downloader too (world/coasts).
|
||||
app.organicmaps.sdk.DownloadResourcesLegacyActivity.nativeResetMetaConfig();
|
||||
}
|
||||
|
||||
public static String normalizeServerUrl(@Nullable String url)
|
||||
{
|
||||
String out = url != null ? url.trim() : "";
|
||||
if (!out.isEmpty() && !out.endsWith("/"))
|
||||
out = out + "/";
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@ package app.organicmaps.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.Icon;
|
||||
import app.organicmaps.sdk.downloader.Android7RootCertificateWorkaround;
|
||||
@@ -25,6 +28,7 @@ import app.organicmaps.sdk.util.SharedPropertiesUtils;
|
||||
import app.organicmaps.sdk.util.StorageUtils;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
import app.organicmaps.sdk.util.log.LogsManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class OrganicMaps implements DefaultLifecycleObserver
|
||||
@@ -167,6 +171,11 @@ public final class OrganicMaps implements DefaultLifecycleObserver
|
||||
/* isTablet */ false);
|
||||
Config.setStoragePath(writablePath);
|
||||
|
||||
// Use the same prefs as SettingsPrefsFragment
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
final String savedUrl = prefs.getString(mContext.getString(R.string.pref_custom_map_download_url), "");
|
||||
Framework.nativeSetCustomMapDownloadUrl(savedUrl.trim());
|
||||
|
||||
mPlatformInitialized = true;
|
||||
Logger.i(TAG, "Platform initialized");
|
||||
}
|
||||
|
||||
@@ -261,4 +261,9 @@ public final class MapManager
|
||||
* Returns country ID which the current PP object points to, or {@code null}.
|
||||
*/
|
||||
public static native @Nullable String nativeGetSelectedCountry();
|
||||
|
||||
/**
|
||||
* Returns true when the map exists and is too old for map editing.
|
||||
*/
|
||||
public static native boolean nativeIsMapTooOldToEdit(String countryId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright © 2017–2020 traffxml.org.
|
||||
*
|
||||
* Relicensed to CoMaps by the original author.
|
||||
*/
|
||||
|
||||
package app.organicmaps.sdk.traffxml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.organicmaps.sdk.traffxml.Version;
|
||||
import app.organicmaps.sdk.traffxml.AndroidTransport;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentFilter.MalformedMimeTypeException;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class AndroidConsumer {
|
||||
/**
|
||||
* Creates an Intent filter which matches the Intents a TraFF consumer needs to receive.
|
||||
*
|
||||
* <p>Different filters are available for consumers implementing different versions of the TraFF
|
||||
* specification.
|
||||
*
|
||||
* @param version The version of the TraFF specification (one of the constants in {@link org.traffxml.traff.Version})
|
||||
*
|
||||
* @return An intent filter matching the necessary Intents
|
||||
*/
|
||||
public static IntentFilter createIntentFilter(int version) {
|
||||
IntentFilter res = new IntentFilter();
|
||||
switch (version) {
|
||||
case Version.V0_7:
|
||||
res.addAction(AndroidTransport.ACTION_TRAFF_PUSH);
|
||||
break;
|
||||
case Version.V0_8:
|
||||
res.addAction(AndroidTransport.ACTION_TRAFF_PUSH);
|
||||
res.addDataScheme(AndroidTransport.CONTENT_SCHEMA);
|
||||
try {
|
||||
res.addDataType(AndroidTransport.MIME_TYPE_TRAFF);
|
||||
} catch (MalformedMimeTypeException e) {
|
||||
// as long as the constant is a well-formed MIME type, this exception never gets thrown
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid version code: " + version);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a TraFF intent to a source.
|
||||
*
|
||||
* <p>This encapsulates most of the low-level Android handling.
|
||||
*
|
||||
* <p>If the recipient specified in {@code packageName} declares multiple receivers for the intent in its
|
||||
* manifest, a separate intent will be delivered to each of them. The intent will not be delivered to
|
||||
* receivers registered at runtime.
|
||||
*
|
||||
* <p>All intents are sent as explicit ordered broadcasts. This means two things:
|
||||
*
|
||||
* <p>Any app which declares a matching receiver in its manifest will be woken up to process the intent.
|
||||
* This works even with certain Android 7 builds which restrict intent delivery to apps which are not
|
||||
* currently running.
|
||||
*
|
||||
* <p>It is safe for the recipient to unconditionally set result data. If the recipient does not set
|
||||
* result data, the result will have a result code of
|
||||
* {@link org.traffxml.transport.android.AndroidTransport#RESULT_INTERNAL_ERROR}, no data and no extras.
|
||||
*
|
||||
* @param context The context
|
||||
* @param action The intent action.
|
||||
* @param data The intent data (for TraFF, this is the content provider URI), or null
|
||||
* @param extras The extras for the intent
|
||||
* @param packageName The package name for the intent recipient, or null to deliver the intent to all matching receivers
|
||||
* @param receiverPermission A permission which the recipient must hold, or null if not required
|
||||
* @param resultReceiver A BroadcastReceiver which will receive the result for the intent
|
||||
*/
|
||||
public static void sendTraffIntent(Context context, String action, Uri data, Bundle extras, String packageName,
|
||||
String receiverPermission, BroadcastReceiver resultReceiver) {
|
||||
Intent outIntent = new Intent(action);
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0);
|
||||
if (receivers != null)
|
||||
for (ResolveInfo receiver : receivers) {
|
||||
if ((packageName != null) && !packageName.equals(receiver.activityInfo.applicationInfo.packageName))
|
||||
continue;
|
||||
ComponentName cn = new ComponentName(receiver.activityInfo.applicationInfo.packageName,
|
||||
receiver.activityInfo.name);
|
||||
outIntent = new Intent(action);
|
||||
if (data != null)
|
||||
outIntent.setData(data);
|
||||
if (extras != null)
|
||||
outIntent.putExtras(extras);
|
||||
outIntent.setComponent(cn);
|
||||
context.sendOrderedBroadcast (outIntent,
|
||||
receiverPermission,
|
||||
resultReceiver,
|
||||
null, // scheduler,
|
||||
AndroidTransport.RESULT_INTERNAL_ERROR, // initialCode,
|
||||
null, // initialData,
|
||||
null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright © 2019–2020 traffxml.org.
|
||||
*
|
||||
* Relicensed to CoMaps by the original author.
|
||||
*/
|
||||
|
||||
package app.organicmaps.sdk.traffxml;
|
||||
|
||||
public class AndroidTransport {
|
||||
/**
|
||||
* Intent to poll a peer for its capabilities.
|
||||
*
|
||||
* <p>This is a broadcast intent and must be sent as an explicit broadcast.
|
||||
*/
|
||||
public static final String ACTION_TRAFF_GET_CAPABILITIES = "org.traffxml.traff.GET_CAPABILITIES";
|
||||
|
||||
/**
|
||||
* Intent to send a heartbeat to a peer.
|
||||
*
|
||||
* <p>This is a broadcast intent and must be sent as an explicit broadcast.
|
||||
*/
|
||||
public static final String ACTION_TRAFF_HEARTBEAT = "org.traffxml.traff.GET_HEARTBEAT";
|
||||
|
||||
/**
|
||||
* Intent to poll a source for information.
|
||||
*
|
||||
* <p>This is a broadcast intent and must be sent as an explicit broadcast.
|
||||
*
|
||||
* <p>Polling is a legacy feature on Android and deprecated in TraFF 0.8 (rather than polling, TraFF 0.8
|
||||
* applications query the content provider). Therefore, poll operations are subscriptionless, and the
|
||||
* source should either reply with all messages it currently holds, or ignore the request.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String ACTION_TRAFF_POLL = "org.traffxml.traff.POLL";
|
||||
|
||||
/**
|
||||
* Intent for a push feed.
|
||||
*
|
||||
* <p>This is a broadcast intent. It can be used in different forms:
|
||||
*
|
||||
* <p>As of TraFF 0.8, it must be sent as an explicit broadcast and include the
|
||||
* {@link #EXTRA_SUBSCRIPTION_ID} extra. The intent data must be a URI to the content provider from which
|
||||
* the messages can be retrieved. The {@link #EXTRA_FEED} extra is not supported. The feed is part of a
|
||||
* subscription and will contain only changes over feeds sent previously as part of the same
|
||||
* subscription.
|
||||
*
|
||||
* <p>Legacy applications omit the {@link #EXTRA_SUBSCRIPTION_ID} extra and may send it as an implicit
|
||||
* broadcast. If an application supports both legacy transport and TraFF 0.8 or later, it must include
|
||||
* the {@link #EXTRA_PACKAGE} extra. The feed is sent in the {@link #EXTRA_FEED} extra, as legacy
|
||||
* applications may not support content providers. If sent as a response to a subscriptionless poll, the
|
||||
* source should include all messages it holds, else the set of messages included is at the discretion of
|
||||
* the source.
|
||||
*
|
||||
* <p>Future applications may reintroduce unsolicited push operations for certain scenarios.
|
||||
*/
|
||||
public static final String ACTION_TRAFF_PUSH = "org.traffxml.traff.FEED";
|
||||
|
||||
/**
|
||||
* Intent for a subscription request.
|
||||
*
|
||||
* <p>This is a broadcast intent and must be sent as an explicit broadcast.
|
||||
*
|
||||
* <p>The filter list must be specified in the {@link #EXTRA_FILTER_LIST} extra.
|
||||
*
|
||||
* <p>The sender must indicate its package name in the {@link #EXTRA_PACKAGE} extra.
|
||||
*/
|
||||
public static final String ACTION_TRAFF_SUBSCRIBE = "org.traffxml.traff.SUBSCRIBE";
|
||||
|
||||
/**
|
||||
* Intent for a subscription change request,
|
||||
*
|
||||
* <p>This is a broadcast intent and must be sent as an explicit broadcast.
|
||||
*
|
||||
* <p>This intent must have {@link #EXTRA_SUBSCRIPTION_ID} set to the ID of an existing subscription between
|
||||
* the calling consumer and the source which receives the broadcast.
|
||||
*
|
||||
* <p>The new filter list must be specified in the {@link #EXTRA_FILTER_LIST} extra.
|
||||
*/
|
||||
public static final String ACTION_TRAFF_SUBSCRIPTION_CHANGE = "org.traffxml.traff.SUBSCRIPTION_CHANGE";
|
||||
|
||||
/**
|
||||
* Intent for an unsubscribe request,
|
||||
*
|
||||
* <p>This is a broadcast intent and must be sent as an explicit broadcast.
|
||||
*
|
||||
* <p>This intent must have {@link #EXTRA_SUBSCRIPTION_ID} set to the ID of an existing subscription between
|
||||
* the calling consumer and the source which receives the broadcast. It signals that the consumer is no
|
||||
* longer interested in receiving messages related to that subscription, and that the source should stop
|
||||
* sending updates. Unsubscribing from a nonexistent subscription is a no-op.
|
||||
*/
|
||||
public static final String ACTION_TRAFF_UNSUBSCRIBE = "org.traffxml.traff.UNSUBSCRIBE";
|
||||
|
||||
/**
|
||||
* Name for the column which holds the message data.
|
||||
*/
|
||||
public static final String COLUMN_DATA = "data";
|
||||
|
||||
/**
|
||||
* Schema for TraFF content URIs.
|
||||
*/
|
||||
public static final String CONTENT_SCHEMA = "content";
|
||||
|
||||
/**
|
||||
* String representations of TraFF result codes
|
||||
*/
|
||||
public static final String[] ERROR_STRINGS = {
|
||||
"unknown (0)",
|
||||
"invalid request (1)",
|
||||
"subscription rejected by the source (2)",
|
||||
"requested area not covered (3)",
|
||||
"requested area partially covered (4)",
|
||||
"subscription ID not recognized by the source (5)",
|
||||
"unknown (6)",
|
||||
"source reported an internal error (7)"
|
||||
};
|
||||
|
||||
/**
|
||||
* Extra which contains the capabilities of the peer.
|
||||
*
|
||||
* <p>This is a String extra. It contains a {@code capabilities} XML element.
|
||||
*/
|
||||
public static final String EXTRA_CAPABILITIES = "capabilities";
|
||||
|
||||
/**
|
||||
* Extra which contains a TraFF feed.
|
||||
*
|
||||
* <p>This is a String extra. It contains a {@code feed} XML element.
|
||||
*
|
||||
* <p>The sender should be careful to keep the size of this extra low, as Android has a 1 MByte limit on all
|
||||
* pending Binder transactions. However, there is no feedback to the sender about the capacity still
|
||||
* available, or whether a request exceeds that limit. Therefore, senders should keep the size if each
|
||||
* feed significantly below that limit. If necessary, they should split up a feed into multiple smaller
|
||||
* ones and send them with a delay in between.
|
||||
*
|
||||
* <p>This mechanism is deprecated since TraFF 0.8 and peers are no longer required to support it. Peers
|
||||
* which support TraFF 0.8 must rely on content providers for message transport.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String EXTRA_FEED = "feed";
|
||||
|
||||
/**
|
||||
* Extra which contains a filter list.
|
||||
*
|
||||
* <p>This is a String extra. It contains a {@code filter_list} XML element.
|
||||
*/
|
||||
public static final String EXTRA_FILTER_LIST = "filter_list";
|
||||
|
||||
/**
|
||||
* Extra which contains the package name of the app sending it.
|
||||
*
|
||||
* <p>This is a String extra.
|
||||
*/
|
||||
public static final String EXTRA_PACKAGE = "package";
|
||||
|
||||
/**
|
||||
* Extra which contains a subscription ID.
|
||||
*
|
||||
* <p>This is a String extra.
|
||||
*/
|
||||
public static final String EXTRA_SUBSCRIPTION_ID = "subscription_id";
|
||||
|
||||
/**
|
||||
* Extra which contains the timeout duration for a subscription.
|
||||
*
|
||||
* <p>This is an integer extra.
|
||||
*/
|
||||
public static final String EXTRA_TIMEOUT = "timeout";
|
||||
|
||||
/**
|
||||
* The MIME type for TraFF content providers.
|
||||
*/
|
||||
public static final String MIME_TYPE_TRAFF = "vnd.android.cursor.dir/org.traffxml.message";
|
||||
|
||||
/**
|
||||
* The operation completed successfully.
|
||||
*/
|
||||
public static final int RESULT_OK = -1;
|
||||
|
||||
/**
|
||||
* An internal error prevented the recipient from fulfilling the request.
|
||||
*/
|
||||
public static final int RESULT_INTERNAL_ERROR = 7;
|
||||
|
||||
/**
|
||||
* A nonexistent operation was attempted, or an operation was attempted with incomplete or otherwise
|
||||
* invalid data.
|
||||
*/
|
||||
public static final int RESULT_INVALID = 1;
|
||||
|
||||
/**
|
||||
* The subscription was rejected, and no messages will be sent.
|
||||
*/
|
||||
public static final int RESULT_SUBSCRIPTION_REJECTED = 2;
|
||||
|
||||
/**
|
||||
* The subscription was rejected because the source will never provide messages matching the selection.
|
||||
*/
|
||||
public static final int RESULT_NOT_COVERED = 3;
|
||||
|
||||
/**
|
||||
* The subscription was accepted but the source can only provide messages for parts of the selection.
|
||||
*/
|
||||
public static final int RESULT_PARTIALLY_COVERED = 4;
|
||||
|
||||
/**
|
||||
* The request failed because it refers to a subscription which does not exist between the source and
|
||||
* consumer involved.
|
||||
*/
|
||||
public static final int RESULT_SUBSCRIPTION_UNKNOWN = 5;
|
||||
|
||||
/**
|
||||
* The request failed because the aggregator does not accept unsolicited push requests from the sensor.
|
||||
*/
|
||||
public static final int RESULT_PUSH_REJECTED = 6;
|
||||
|
||||
public static String formatTraffError(int code) {
|
||||
if ((code < 0) || (code >= ERROR_STRINGS.length))
|
||||
return String.format("unknown (%d)", code);
|
||||
else
|
||||
return ERROR_STRINGS[code];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package app.organicmaps.sdk.traffxml;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Abstract superclass for TraFF source implementations.
|
||||
*/
|
||||
public abstract class SourceImpl extends BroadcastReceiver
|
||||
{
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param context The application context
|
||||
*/
|
||||
public SourceImpl(Context context, long nativeManager)
|
||||
{
|
||||
super();
|
||||
this.context = context;
|
||||
this.nativeManager = nativeManager;
|
||||
}
|
||||
|
||||
protected Context context;
|
||||
|
||||
/**
|
||||
* The native `TraffSourceManager` instance.
|
||||
*/
|
||||
protected long nativeManager;
|
||||
|
||||
/**
|
||||
* Subscribes to a traffic source.
|
||||
*
|
||||
* @param filterList The filter list in XML format
|
||||
*/
|
||||
public abstract void subscribe(String filterList);
|
||||
|
||||
/**
|
||||
* Changes an existing traffic subscription.
|
||||
*
|
||||
* @param filterList The filter list in XML format
|
||||
*/
|
||||
public abstract void changeSubscription(String filterList);
|
||||
|
||||
/**
|
||||
* Unsubscribes from a traffic source we are subscribed to.
|
||||
*/
|
||||
public abstract void unsubscribe();
|
||||
|
||||
/**
|
||||
* Forwards a newly received TraFF feed to the traffic module for processing.
|
||||
*
|
||||
* Called when a TraFF feed is received. This is a wrapper around {@link #onFeedReceivedImpl(long, String)}.
|
||||
*
|
||||
* @param feed The TraFF feed
|
||||
*/
|
||||
protected void onFeedReceived(String feed)
|
||||
{
|
||||
onFeedReceivedImpl(nativeManager, feed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards a newly received TraFF feed to the traffic module for processing.
|
||||
*
|
||||
* Called when a TraFF feed is received.
|
||||
*
|
||||
* @param nativeManager The native `TraffSourceManager` instance
|
||||
* @param feed The TraFF feed
|
||||
*/
|
||||
protected static native void onFeedReceivedImpl(long nativeManager, String feed);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package app.organicmaps.sdk.traffxml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
/**
|
||||
* Implementation for a TraFF 0.7 source.
|
||||
*/
|
||||
public class SourceImplV0_7 extends SourceImpl
|
||||
{
|
||||
private PackageManager pm;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param context The application context
|
||||
*/
|
||||
public SourceImplV0_7(Context context, long nativeManager)
|
||||
{
|
||||
super(context, nativeManager);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to a traffic source.
|
||||
*
|
||||
* @param filterList The filter list in XML format
|
||||
*/
|
||||
@Override
|
||||
public void subscribe(String filterList)
|
||||
{
|
||||
IntentFilter traffFilter07 = new IntentFilter();
|
||||
traffFilter07.addAction(AndroidTransport.ACTION_TRAFF_PUSH);
|
||||
|
||||
this.context.registerReceiver(this, traffFilter07);
|
||||
|
||||
// Broadcast a poll intent to all TraFF 0.7-only receivers
|
||||
Intent outIntent = new Intent(AndroidTransport.ACTION_TRAFF_POLL);
|
||||
pm = this.context.getPackageManager();
|
||||
List<ResolveInfo> receivers07 = pm.queryBroadcastReceivers(outIntent, 0);
|
||||
List<ResolveInfo> receivers08 = pm.queryBroadcastReceivers(new Intent(AndroidTransport.ACTION_TRAFF_GET_CAPABILITIES), 0);
|
||||
if (receivers07 != null)
|
||||
{
|
||||
/*
|
||||
* Get receivers which support only TraFF 0.7 and poll them.
|
||||
* If there are no TraFF 0.7 sources at the moment, we register the receiver nonetheless.
|
||||
* That way, if any new sources are added during the session, we get any messages they send.
|
||||
*/
|
||||
if (receivers08 != null)
|
||||
receivers07.removeAll(receivers08);
|
||||
for (ResolveInfo receiver : receivers07)
|
||||
{
|
||||
ComponentName cn = new ComponentName(receiver.activityInfo.applicationInfo.packageName,
|
||||
receiver.activityInfo.name);
|
||||
outIntent = new Intent(AndroidTransport.ACTION_TRAFF_POLL);
|
||||
outIntent.setComponent(cn);
|
||||
this.context.sendBroadcast(outIntent, Manifest.permission.ACCESS_COARSE_LOCATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes an existing traffic subscription.
|
||||
*
|
||||
* This implementation does nothing, as TraFF 0.7 does not support subscriptions.
|
||||
*
|
||||
* @param filterList The filter list in XML format
|
||||
*/
|
||||
@Override
|
||||
public void changeSubscription(String filterList)
|
||||
{
|
||||
// NOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from a traffic source we are subscribed to.
|
||||
*/
|
||||
@Override
|
||||
public void unsubscribe()
|
||||
{
|
||||
this.context.unregisterReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
if (intent == null)
|
||||
return;
|
||||
|
||||
if (intent.getAction().equals(AndroidTransport.ACTION_TRAFF_PUSH))
|
||||
{
|
||||
/* 0.7 feed */
|
||||
String packageName = intent.getStringExtra(AndroidTransport.EXTRA_PACKAGE);
|
||||
/*
|
||||
* If the feed comes from a TraFF 0.8+ source, skip it (this may happen with “bilingual”
|
||||
* TraFF 0.7/0.8 sources). That ensures the only way to get information from such sources is
|
||||
* through a TraFF 0.8 subscription. Fetching the list from scratch each time ensures that
|
||||
* apps installed during runtime get considered.)
|
||||
*/
|
||||
if (packageName != null)
|
||||
{
|
||||
for (ResolveInfo info : pm.queryBroadcastReceivers(new Intent(AndroidTransport.ACTION_TRAFF_GET_CAPABILITIES), 0))
|
||||
if (packageName.equals(info.resolvePackageName))
|
||||
return;
|
||||
}
|
||||
String feed = intent.getStringExtra(AndroidTransport.EXTRA_FEED);
|
||||
if (feed == null)
|
||||
{
|
||||
Logger.w(this.getClass().getSimpleName(), "empty feed, ignoring");
|
||||
}
|
||||
else
|
||||
{
|
||||
onFeedReceived(feed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
package app.organicmaps.sdk.traffxml;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentFilter.MalformedMimeTypeException;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
/**
|
||||
* Implementation for a TraFF 0.8 source.
|
||||
*/
|
||||
public class SourceImplV0_8 extends SourceImpl
|
||||
{
|
||||
|
||||
private String packageName;
|
||||
private String subscriptionId = null;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param context The application context
|
||||
* @param packageName The package name for the source
|
||||
*/
|
||||
public SourceImplV0_8(Context context, long nativeManager, String packageName)
|
||||
{
|
||||
super(context, nativeManager);
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to a traffic source.
|
||||
*
|
||||
* @param filterList The filter list in XML format
|
||||
*/
|
||||
@Override
|
||||
public void subscribe(String filterList)
|
||||
{
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AndroidTransport.ACTION_TRAFF_PUSH);
|
||||
filter.addDataScheme(AndroidTransport.CONTENT_SCHEMA);
|
||||
try
|
||||
{
|
||||
filter.addDataType(AndroidTransport.MIME_TYPE_TRAFF);
|
||||
}
|
||||
catch (MalformedMimeTypeException e)
|
||||
{
|
||||
// as long as the constant is a well-formed MIME type, this exception never gets thrown
|
||||
// TODO revisit logging
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
context.registerReceiver(this, filter);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putString(AndroidTransport.EXTRA_PACKAGE, context.getPackageName());
|
||||
extras.putString(AndroidTransport.EXTRA_FILTER_LIST, filterList);
|
||||
AndroidConsumer.sendTraffIntent(context, AndroidTransport.ACTION_TRAFF_SUBSCRIBE, null,
|
||||
extras, packageName, Manifest.permission.ACCESS_COARSE_LOCATION, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes an existing traffic subscription.
|
||||
*
|
||||
* @param filterList The filter list in XML format
|
||||
*/
|
||||
@Override
|
||||
public void changeSubscription(String filterList)
|
||||
{
|
||||
Bundle extras = new Bundle();
|
||||
extras.putString(AndroidTransport.EXTRA_SUBSCRIPTION_ID, subscriptionId);
|
||||
extras.putString(AndroidTransport.EXTRA_FILTER_LIST, filterList);
|
||||
AndroidConsumer.sendTraffIntent(context, AndroidTransport.ACTION_TRAFF_SUBSCRIPTION_CHANGE, null,
|
||||
extras, packageName, Manifest.permission.ACCESS_COARSE_LOCATION, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from a traffic source we are subscribed to.
|
||||
*/
|
||||
@Override
|
||||
public void unsubscribe()
|
||||
{
|
||||
Bundle extras = new Bundle();
|
||||
extras.putString(AndroidTransport.EXTRA_SUBSCRIPTION_ID, subscriptionId);
|
||||
AndroidConsumer.sendTraffIntent(this.context, AndroidTransport.ACTION_TRAFF_UNSUBSCRIBE, null,
|
||||
extras, packageName, Manifest.permission.ACCESS_COARSE_LOCATION, this);
|
||||
|
||||
this.context.unregisterReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
if (intent == null)
|
||||
return;
|
||||
|
||||
if (intent.getAction().equals(AndroidTransport.ACTION_TRAFF_PUSH))
|
||||
{
|
||||
Uri uri = intent.getData();
|
||||
if (uri != null)
|
||||
{
|
||||
/* 0.8 feed */
|
||||
String subscriptionId = intent.getStringExtra(AndroidTransport.EXTRA_SUBSCRIPTION_ID);
|
||||
if (subscriptionId.equals(this.subscriptionId))
|
||||
fetchMessages(context, uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.w(this.getClass().getSimpleName(), "no URI in feed, ignoring");
|
||||
} // uri != null
|
||||
} else if (intent.getAction().equals(AndroidTransport.ACTION_TRAFF_SUBSCRIBE)) {
|
||||
if (this.getResultCode() != AndroidTransport.RESULT_OK) {
|
||||
Bundle extras = this.getResultExtras(true);
|
||||
if (extras != null)
|
||||
Logger.e(this.getClass().getSimpleName(), String.format("subscription to %s failed, %s",
|
||||
extras.getString(AndroidTransport.EXTRA_PACKAGE), AndroidTransport.formatTraffError(this.getResultCode())));
|
||||
else
|
||||
Logger.e(this.getClass().getSimpleName(), String.format("subscription failed, %s",
|
||||
AndroidTransport.formatTraffError(this.getResultCode())));
|
||||
if (this.getResultCode() == AndroidTransport.RESULT_INTERNAL_ERROR)
|
||||
Logger.e(this.getClass().getSimpleName(), "Make sure the TraFF source app has at least coarse location permission, even when running in background");
|
||||
return;
|
||||
}
|
||||
Bundle extras = this.getResultExtras(true);
|
||||
String data = this.getResultData();
|
||||
String packageName = extras.getString(AndroidTransport.EXTRA_PACKAGE);
|
||||
if (!this.packageName.equals(packageName))
|
||||
return;
|
||||
String subscriptionId = extras.getString(AndroidTransport.EXTRA_SUBSCRIPTION_ID);
|
||||
if (subscriptionId == null) {
|
||||
Logger.e(this.getClass().getSimpleName(),
|
||||
String.format("subscription to %s failed: no subscription ID returned", packageName));
|
||||
return;
|
||||
} else if (packageName == null) {
|
||||
Logger.e(this.getClass().getSimpleName(), "subscription failed: no package name");
|
||||
return;
|
||||
} else if (data == null) {
|
||||
Logger.w(this.getClass().getSimpleName(),
|
||||
String.format("subscription to %s successful (ID: %s) but no content URI was supplied. "
|
||||
+ "This is an issue with the source and may result in delayed message retrieval.",
|
||||
packageName, subscriptionId));
|
||||
this.subscriptionId = subscriptionId;
|
||||
return;
|
||||
}
|
||||
Logger.d(this.getClass().getSimpleName(),
|
||||
"subscription to " + packageName + " successful, ID: " + subscriptionId);
|
||||
this.subscriptionId = subscriptionId;
|
||||
fetchMessages(context, Uri.parse(data));
|
||||
} else if (intent.getAction().equals(AndroidTransport.ACTION_TRAFF_SUBSCRIPTION_CHANGE)) {
|
||||
if (this.getResultCode() != AndroidTransport.RESULT_OK) {
|
||||
Bundle extras = this.getResultExtras(true);
|
||||
if (extras != null)
|
||||
Logger.e(this.getClass().getSimpleName(),
|
||||
String.format("subscription change for %s failed: %s",
|
||||
extras.getString(AndroidTransport.EXTRA_SUBSCRIPTION_ID),
|
||||
AndroidTransport.formatTraffError(this.getResultCode())));
|
||||
else
|
||||
Logger.e(this.getClass().getSimpleName(),
|
||||
String.format("subscription change failed: %s",
|
||||
AndroidTransport.formatTraffError(this.getResultCode())));
|
||||
return;
|
||||
}
|
||||
Bundle extras = intent.getExtras();
|
||||
String data = this.getResultData();
|
||||
String subscriptionId = extras.getString(AndroidTransport.EXTRA_SUBSCRIPTION_ID);
|
||||
if (subscriptionId == null) {
|
||||
Logger.w(this.getClass().getSimpleName(),
|
||||
"subscription change successful but the source did not specify the subscription ID. "
|
||||
+ "This is an issue with the source and may result in delayed message retrieval. "
|
||||
+ "URI: " + data);
|
||||
return;
|
||||
} else if (!subscriptionId.equals(this.subscriptionId)) {
|
||||
return;
|
||||
} else if (data == null) {
|
||||
Logger.w(this.getClass().getSimpleName(),
|
||||
String.format("subscription change for %s successful but no content URI was supplied. "
|
||||
+ "This is an issue with the source and may result in delayed message retrieval.",
|
||||
subscriptionId));
|
||||
return;
|
||||
}
|
||||
Logger.d(this.getClass().getSimpleName(),
|
||||
"subscription change for " + subscriptionId + " successful");
|
||||
fetchMessages(context, Uri.parse(data));
|
||||
} else if (intent.getAction().equals(AndroidTransport.ACTION_TRAFF_UNSUBSCRIBE)) {
|
||||
String subscriptionId = intent.getStringExtra(AndroidTransport.EXTRA_SUBSCRIPTION_ID);
|
||||
if (subscriptionId.equals(this.subscriptionId))
|
||||
this.subscriptionId = null;
|
||||
// TODO is there anything to do here? (Comment below is from Navit)
|
||||
/*
|
||||
* If we ever unsubscribe for reasons other than that we are shutting down or got a feed for
|
||||
* a subscription we don’t recognize, or if we start keeping a persistent list of
|
||||
* subscriptions, we need to delete the subscription from our list. Until then, there is
|
||||
* nothing to do here: either the subscription isn’t in the list, or we are about to shut
|
||||
* down and the whole list is about to get discarded.
|
||||
*/
|
||||
} else if (intent.getAction().equals(AndroidTransport.ACTION_TRAFF_HEARTBEAT)) {
|
||||
String subscriptionId = intent.getStringExtra(AndroidTransport.EXTRA_SUBSCRIPTION_ID);
|
||||
if (subscriptionId.equals(this.subscriptionId)) {
|
||||
Logger.d(this.getClass().getSimpleName(),
|
||||
String.format("got a heartbeat from %s for subscription %s; sending result",
|
||||
intent.getStringExtra(AndroidTransport.EXTRA_PACKAGE), subscriptionId));
|
||||
this.setResult(AndroidTransport.RESULT_OK, null, null);
|
||||
}
|
||||
} // intent.getAction()
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches TraFF messages from a content provider.
|
||||
*
|
||||
* @param context The context to use for the content resolver
|
||||
* @param uri The content provider URI
|
||||
*/
|
||||
private void fetchMessages(Context context, Uri uri) {
|
||||
try {
|
||||
Cursor cursor = context.getContentResolver().query(uri, new String[] {AndroidTransport.COLUMN_DATA}, null, null, null);
|
||||
if (cursor == null)
|
||||
return;
|
||||
if (cursor.getCount() < 1) {
|
||||
cursor.close();
|
||||
return;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder("<feed>\n");
|
||||
while (cursor.moveToNext())
|
||||
builder.append(cursor.getString(cursor.getColumnIndex(AndroidTransport.COLUMN_DATA))).append("\n");
|
||||
builder.append("</feed>");
|
||||
cursor.close();
|
||||
onFeedReceived(builder.toString());
|
||||
} catch (Exception e) {
|
||||
Logger.w(this.getClass().getSimpleName(),
|
||||
String.format("Unable to fetch messages from %s", uri.toString()), e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright © 2019–2020 traffxml.org.
|
||||
*
|
||||
* Relicensed to CoMaps by the original author.
|
||||
*/
|
||||
|
||||
package app.organicmaps.sdk.traffxml;
|
||||
|
||||
/**
|
||||
* Constants for versions.
|
||||
*/
|
||||
public class Version {
|
||||
/** Version 0.7: introduced transport on Android. */
|
||||
public static final int V0_7 = 7;
|
||||
|
||||
/** Version 0.8: introduced subscriptions and HTTP transport. */
|
||||
public static final int V0_8 = 8;
|
||||
}
|
||||
@@ -70,6 +70,16 @@ public final class Config
|
||||
* True if the first start animation has been seen.
|
||||
*/
|
||||
private static final String KEY_MISC_FIRST_START_DIALOG_SEEN = "FirstStartDialogSeen";
|
||||
|
||||
/**
|
||||
* Whether feeds from legacy TraFF applications (TraFF 0.7, Android transport) are enabled.
|
||||
*/
|
||||
private static final String KEY_TRAFFIC_LEGACY_ENABLED = "TrafficLegacyEnabled";
|
||||
|
||||
/**
|
||||
* TraFF (0.8+) applications from which to request traffic data.
|
||||
*/
|
||||
private static final String KEY_TRAFFIC_APPS = "TrafficApps";
|
||||
|
||||
private Config() {}
|
||||
|
||||
@@ -393,6 +403,63 @@ public final class Config
|
||||
nativeSetTransliteration(value);
|
||||
}
|
||||
|
||||
public static boolean getTrafficHttpEnabled()
|
||||
{
|
||||
return nativeGetTrafficHttpEnabled();
|
||||
}
|
||||
|
||||
public static void setTrafficHttpEnabled(boolean value)
|
||||
{
|
||||
nativeSetTrafficHttpEnabled(value);
|
||||
}
|
||||
|
||||
public static String getTrafficHttpUrl()
|
||||
{
|
||||
return nativeGetTrafficHttpUrl();
|
||||
}
|
||||
|
||||
public static void setTrafficHttpUrl(String value)
|
||||
{
|
||||
nativeSetTrafficHttpUrl(value);
|
||||
}
|
||||
|
||||
public static String[] getTrafficApps()
|
||||
{
|
||||
String appString = getString(KEY_TRAFFIC_APPS, "");
|
||||
if (appString.length() == 0)
|
||||
return new String[0];
|
||||
return appString.split(",");
|
||||
}
|
||||
|
||||
public static void setTrafficApps(String[] value)
|
||||
{
|
||||
String valueString = "";
|
||||
for (int i = 0; i < value.length; i++)
|
||||
{
|
||||
valueString = valueString + value[i];
|
||||
if ((i + 1) < value.length)
|
||||
valueString = valueString + ",";
|
||||
}
|
||||
setString(KEY_TRAFFIC_APPS, valueString);
|
||||
applyTrafficApps(value);
|
||||
}
|
||||
|
||||
public static boolean getTrafficLegacyEnabled()
|
||||
{
|
||||
return getBool(KEY_TRAFFIC_LEGACY_ENABLED, false);
|
||||
}
|
||||
|
||||
public static void setTrafficLegacyEnabled(boolean value)
|
||||
{
|
||||
setBool(KEY_TRAFFIC_LEGACY_ENABLED, value);
|
||||
applyTrafficLegacyEnabled(value);
|
||||
}
|
||||
|
||||
public static boolean isNY()
|
||||
{
|
||||
return getBool("NY");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getDonateUrl()
|
||||
{
|
||||
@@ -536,4 +603,10 @@ public final class Config
|
||||
private static native void nativeSetLargeFontsSize(boolean value);
|
||||
private static native boolean nativeGetTransliteration();
|
||||
private static native void nativeSetTransliteration(boolean value);
|
||||
private static native boolean nativeGetTrafficHttpEnabled();
|
||||
private static native void nativeSetTrafficHttpEnabled(boolean value);
|
||||
private static native String nativeGetTrafficHttpUrl();
|
||||
private static native void nativeSetTrafficHttpUrl(String value);
|
||||
private static native void applyTrafficApps(String[] value);
|
||||
private static native void applyTrafficLegacyEnabled(boolean value);
|
||||
}
|
||||
|
||||
@@ -707,7 +707,7 @@
|
||||
<string name="type.natural.beach.sand">Playa de arena</string>
|
||||
<string name="type.natural.beach.gravel">Playa de grava</string>
|
||||
<string name="type.natural.cape">Cabo</string>
|
||||
<string name="type.natural.cave_entrance">Cueva</string>
|
||||
<string name="type.natural.cave_entrance">Entrada de cueva</string>
|
||||
<string name="type.natural.cliff">Acantilado</string>
|
||||
<string name="type.natural.earth_bank">Talud de tierra</string>
|
||||
<string name="type.man_made.embankment">Terraplén</string>
|
||||
@@ -743,7 +743,7 @@
|
||||
<string name="type.natural.wetland.marsh">Ciénaga</string>
|
||||
<string name="type.noexit">Sin salida</string>
|
||||
<string name="type.office">Oficina</string>
|
||||
<string name="type.office.company">Oficina</string>
|
||||
<string name="type.office.company">Oficina de compañía</string>
|
||||
<string name="type.office.estate_agent">Agente inmobiliario</string>
|
||||
<string name="type.office.government">Oficina gubernamental</string>
|
||||
<string name="type.office.insurance">Oficina de seguros</string>
|
||||
@@ -784,13 +784,13 @@
|
||||
<string name="type.place.state">Estado</string>
|
||||
<string name="type.place.state.USA">Estado</string>
|
||||
<!-- Named part of a city or town, bigger than place=quarter (Wiki: https://wiki.openstreetmap.org/wiki/Tag:place%3Dsuburb) -->
|
||||
<string name="type.place.suburb">Barrio</string>
|
||||
<string name="type.place.suburb">Suburbio</string>
|
||||
<string name="type.place.town">Pueblo</string>
|
||||
<string name="type.place.village">Pueblo</string>
|
||||
<string name="type.power">Energía</string>
|
||||
<string name="type.power.generator">Generador</string>
|
||||
<string name="type.power.generator.solar">Generador solar</string>
|
||||
<string name="type.power.generator.wind">Generador de viento</string>
|
||||
<string name="type.power.generator.wind">Aerogenerador</string>
|
||||
<string name="type.power.generator.gas">Planta termoeléctrica de gas</string>
|
||||
<string name="type.power.generator.hydro">Planta hidroeléctrica</string>
|
||||
<string name="type.power.line">Línea eléctrica</string>
|
||||
@@ -849,10 +849,10 @@
|
||||
<string name="type.railway.station">Estación de tren</string>
|
||||
<string name="type.railway.station.funicular">Funicular</string>
|
||||
<string name="type.railway.station.light_rail">Estación de tren</string>
|
||||
<string name="type.railway.station.light_rail.berlin">Estación de tren</string>
|
||||
<string name="type.railway.station.light_rail.berlin">Estación de tren (S-Bahn)</string>
|
||||
<string name="type.railway.station.light_rail.london">Estación de tren</string>
|
||||
<string name="type.railway.station.light_rail.porto">Estación de tren</string>
|
||||
<string name="type.railway.station.monorail">Estación de tren</string>
|
||||
<string name="type.railway.station.light_rail.porto">Estación de metro</string>
|
||||
<string name="type.railway.station.monorail">Estación de monoriel</string>
|
||||
<string name="type.railway.station.subway">Estación de metro</string>
|
||||
<string name="type.railway.station.subway.adana">Estación de metro</string>
|
||||
<string name="type.railway.station.subway.algiers">Estación de metro</string>
|
||||
@@ -1122,7 +1122,7 @@
|
||||
<string name="type.shop.doityourself">Tienda de bricolaje</string>
|
||||
<string name="type.shop.dry_cleaning">Tintorería</string>
|
||||
<string name="type.shop.electronics">Electrónica</string>
|
||||
<string name="type.shop.erotic">Sex Shop</string>
|
||||
<string name="type.shop.erotic">Tienda erótica</string>
|
||||
<string name="type.shop.fabric">Tienda de telas</string>
|
||||
<string name="type.shop.farm">Tienda de alimentos de granja</string>
|
||||
<string name="type.shop.fashion_accessories">Accesorios de moda</string>
|
||||
@@ -1207,7 +1207,7 @@
|
||||
<string name="type.shop.tobacco">Tabaco</string>
|
||||
<string name="type.shop.trade">Suministros comerciales</string>
|
||||
<string name="type.shop.watches">Relojes</string>
|
||||
<string name="type.shop.wholesale">Almacén al por mayor</string>
|
||||
<string name="type.shop.wholesale">Tienda al por mayor</string>
|
||||
<string name="type.sport">Deporte</string>
|
||||
<string name="type.sport.american_football">Fútbol americano</string>
|
||||
<string name="type.sport.archery">Tiro al arco</string>
|
||||
@@ -1247,7 +1247,7 @@
|
||||
<string name="type.tourism.aquarium">Acuario</string>
|
||||
<!-- Typically serviced, staff is present and food is available (compared to wilderness_hut). -->
|
||||
<string name="type.tourism.alpine_hut">Albergue de montaña</string>
|
||||
<string name="type.tourism.apartment">Apartamento de vacaciones</string>
|
||||
<string name="type.tourism.apartment">Apartamento vacacional</string>
|
||||
<string name="type.tourism.artwork">Obra de arte</string>
|
||||
<string name="type.tourism.artwork.architecture">Arte arquitectónico</string>
|
||||
<string name="type.tourism.artwork.painting">Pintura</string>
|
||||
|
||||
@@ -1494,4 +1494,5 @@
|
||||
<string name="type.spherical_buoy.safe_water">Faarvaatri kerapoi</string>
|
||||
<string name="type.man_made.mast.communication">Sidemast</string>
|
||||
<string name="type.shop.beauty.nails">Küünestuudio</string>
|
||||
<string name="type.amenity.hydrant">Kastmishüdrant</string>
|
||||
</resources>
|
||||
|
||||
@@ -1500,4 +1500,5 @@
|
||||
<string name="type.shop.beauty.nails">Nagelsalon</string>
|
||||
<string name="type.amenity.food_sharing">Voedsel delen</string>
|
||||
<string name="type.amenity.give_box">Giftenkist</string>
|
||||
<string name="type.amenity.hydrant">Watertappunt|waterkraan</string>
|
||||
</resources>
|
||||
|
||||
@@ -1501,4 +1501,5 @@
|
||||
<string name="type.natural.tree">Árvore</string>
|
||||
<string name="type.shop.beauty.nails">Salão de Unhas</string>
|
||||
<string name="type.xmas.tree">Árvore de Natal</string>
|
||||
<string name="type.amenity.hydrant">Boca de Rega</string>
|
||||
</resources>
|
||||
|
||||
@@ -369,4 +369,100 @@
|
||||
<string name="type.cuisine.breakfast">Zajtrk</string>
|
||||
<string name="type.cuisine.bubble_tea">Čaj s tapiokinimi kroglicami (\'Bubble Tea\')</string>
|
||||
<string name="type.cuisine.chicken">Piščanec</string>
|
||||
<string name="type.cuisine.greek">Grška kuhinja</string>
|
||||
<string name="type.cuisine.hungarian">Madžarska kuhinja</string>
|
||||
<string name="type.cuisine.ice_cream">Sladoled</string>
|
||||
<string name="type.cuisine.indian">Indijska kuhinja</string>
|
||||
<string name="type.cuisine.indonesian">Indonezijska kuhinja</string>
|
||||
<string name="type.cuisine.international">Mednarodna kuhinja</string>
|
||||
<string name="type.cuisine.irish">Irska kuhinja</string>
|
||||
<string name="type.cuisine.italian">Italijanska kuhinja</string>
|
||||
<string name="type.cuisine.italian_pizza">Italijanska kuhinja, pica</string>
|
||||
<string name="type.cuisine.japanese">Japonska kuhinja</string>
|
||||
<string name="type.cuisine.korean">Korejska kuhinja</string>
|
||||
<string name="type.cuisine.lao">Laoška kuhinja</string>
|
||||
<string name="type.cuisine.lebanese">Libanonska kuhinja</string>
|
||||
<string name="type.cuisine.local">Krajevna kuhinja</string>
|
||||
<string name="type.cuisine.malaysian">Malezijska kuhinja</string>
|
||||
<string name="type.cuisine.mediterranean">Sredozemska kuhinja</string>
|
||||
<string name="type.cuisine.mexican">Mehiška kuhinja</string>
|
||||
<string name="type.cuisine.moroccan">Maroška kuhinja</string>
|
||||
<string name="type.cuisine.oriental">Orientalska kuhinja</string>
|
||||
<string name="type.cuisine.pancake">Palačinke</string>
|
||||
<string name="type.cuisine.pasta">Testenine</string>
|
||||
<string name="type.cuisine.persian">Perzijska kuhinja</string>
|
||||
<string name="type.cuisine.peruvian">Perujska kuhinja</string>
|
||||
<string name="type.cuisine.pizza">Pica</string>
|
||||
<string name="type.cuisine.polish">Poljska kuhinja</string>
|
||||
<string name="type.cuisine.portuguese">Portugalska kuhinja</string>
|
||||
<string name="type.cuisine.russian">Ruska kuhinja</string>
|
||||
<string name="type.cuisine.sandwich">Sendvič</string>
|
||||
<string name="type.cuisine.sausage">Salama</string>
|
||||
<string name="type.cuisine.savory_pancakes">Slane palačinke</string>
|
||||
<string name="type.cuisine.seafood">Morska hrana</string>
|
||||
<string name="type.cuisine.soba">Soba (ajdovi rezanci)</string>
|
||||
<string name="type.cuisine.spanish">Španska kuhinja</string>
|
||||
<string name="type.cuisine.steak_house">Zrezkarnica</string>
|
||||
<string name="type.cuisine.sushi">Suši</string>
|
||||
<string name="type.cuisine.tea">Čaj</string>
|
||||
<string name="type.cuisine.turkish">Turška kuhinja</string>
|
||||
<string name="type.cuisine.vegan">Veganska kuhinja</string>
|
||||
<string name="type.cuisine.vegetarian">Vegetarijanska kuhinja</string>
|
||||
<string name="type.cuisine.vietnamese">Vietnamska kuhinja</string>
|
||||
<string name="type.emergency">V sili</string>
|
||||
<string name="type.emergency.access_point">Reševalno mesto</string>
|
||||
<string name="type.emergency.assembly_point">Zbirno mesto</string>
|
||||
<string name="type.emergency.life_ring">Reševalni obroč</string>
|
||||
<string name="type.emergency.defibrillator">Defibrilator</string>
|
||||
<string name="type.emergency.fire_hydrant">Požarni hidrant</string>
|
||||
<string name="type.amenity.hydrant">Namakalni hidrant</string>
|
||||
<string name="type.emergency.phone">Telefon v sili</string>
|
||||
<string name="type.emergency.lifeguard">Reševalec</string>
|
||||
<string name="type.beacon.cardinal.east">Glavni usmerjevalni znak</string>
|
||||
<string name="type.beacon.cardinal.north">Glavni usmerjevalni znak</string>
|
||||
<string name="type.beacon.cardinal.south">Glavni usmerjevalni znak</string>
|
||||
<string name="type.beacon.cardinal.west">Glavni usmerjevalni znak</string>
|
||||
<string name="type.beacon.isolated_danger">Usmerjevalni znak ločene nevarnosti</string>
|
||||
<string name="type.craft.caterer">Ponudnik cateringa</string>
|
||||
<string name="type.cuisine.balkan">Balkanska kuhinja</string>
|
||||
<string name="type.cuisine.barbecue">Jedi na žaru</string>
|
||||
<string name="type.cuisine.bavarian">Bavarska kuhinja</string>
|
||||
<string name="type.cuisine.brazilian">Brazilska kuhinja</string>
|
||||
<string name="type.cuisine.burger">Burger</string>
|
||||
<string name="type.cuisine.buschenschank">Vinotoč (Buschenschank)</string>
|
||||
<string name="type.cuisine.deli">Delkatesa</string>
|
||||
<string name="type.cuisine.regional">Regionalna kuhinja</string>
|
||||
<string name="type.cuisine.tapas">Tapas (španski prigrizki)</string>
|
||||
<string name="type.cuisine.thai">Tajska kuhinja</string>
|
||||
<string name="type.beacon.lateral.port">Bočni usmerjevalni znak</string>
|
||||
<string name="type.beacon.lateral.starboard">Bočni usmerjevalni znak</string>
|
||||
<string name="type.beacon.safe_water">Znak varne plovne poti</string>
|
||||
<string name="type.beacon.special_purpose">Usmerjevalni znak posebnega namena</string>
|
||||
<string name="type.buoy.cardinal.east">Glavna boja</string>
|
||||
<string name="type.buoy.cardinal.north">Glavna boja</string>
|
||||
<string name="type.buoy.cardinal.south">Glavna boja</string>
|
||||
<string name="type.buoy.cardinal.west">Glavna boja</string>
|
||||
<string name="type.lateral.port">Pristanišče</string>
|
||||
<string name="type.cardinal.east">Vzhod</string>
|
||||
<string name="type.cardinal.north">Sever</string>
|
||||
<string name="type.cardinal.south">Jug</string>
|
||||
<string name="type.cardinal.west">Zahod</string>
|
||||
<string name="type.emergency.mountain_rescue">Postaja gorskih reševalcev</string>
|
||||
<string name="type.entrance">Vhod</string>
|
||||
<string name="type.entrance.main">Glavni vhod</string>
|
||||
<string name="type.entrance.house">Vhod hiše</string>
|
||||
<string name="type.entrance.garage">Vhod garaže</string>
|
||||
<string name="type.entrance.service">Servisni vhod</string>
|
||||
<string name="type.entrance.entry">Vstop (samo)</string>
|
||||
<string name="type.entrance.exit">Izhod (samo)</string>
|
||||
<string name="type.healthcare.laboratory">Zdravstveni laboratorij</string>
|
||||
<string name="type.healthcare.psychotherapist">Psihoterapevt</string>
|
||||
<string name="type.highway.cycleway.tunnel">Predor</string>
|
||||
<string name="type.highway.elevator">Dvigalo</string>
|
||||
<string name="type.highway.footway">Pešpot</string>
|
||||
<string name="type.highway.footway.sidewalk">Pločnik</string>
|
||||
<string name="type.highway.footway.crossing">Prehod za pešce</string>
|
||||
<string name="type.highway.footway.area">Površina za pešce</string>
|
||||
<string name="type.highway.footway.bridge">Most za pešce</string>
|
||||
<string name="type.highway.footway.tunnel">Predor za pešce</string>
|
||||
</resources>
|
||||
|
||||
@@ -1399,4 +1399,5 @@
|
||||
<string name="type.amenity.ranger_station">Orman Bekçisi</string>
|
||||
<string name="type.amenity.bench.backless">Sırtı Açık Bank</string>
|
||||
<string name="type.amenity.charging_station.motorcar.small">Araç Şarj Noktası</string>
|
||||
<string name="type.amenity.sailing_school">Denizcilik Okulu</string>
|
||||
</resources>
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
<string name="pref_file_name" translatable="false">OrganicMapsPrefs</string>
|
||||
<string name="pref_enable_logging" translatable="false">EnableLogging</string>
|
||||
<string name="pref_emulate_bad_external_storage" translatable="false">EmulateBadExternalStorage</string>
|
||||
<string name="pref_custom_map_download_url" translatable="false">CustomMapDownloadUrl</string>
|
||||
</resources>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"shop-farm|@category_food|@shop": "Farm food",
|
||||
"shop-garden_centre|@shop": "4Garden Centre|U+1F3E1",
|
||||
"shop-grocery|@category_food|@shop": "Grocery",
|
||||
"shop-health_food|@category_food|@shop": "7Health food|7Healthy food|healthfood|organic|vegan|vegetarian",
|
||||
"shop-health_food|@category_food|@shop": "7Health food|7Healthy food|healthfood|organic",
|
||||
"shop-hearing_aids|@shop": "7Hearing Aids",
|
||||
"shop-mobile_phone|@shop": "4Cell Phones|4Mobile Phones|6smartphones|electronics store|U+1F4F1|U+1F4F2",
|
||||
"shop-florist|@shop": "4Florist|U+1F337|U+1F338|U+1F339|U+1F33A|U+1F33B|U+1F33C|U+1F490|U+1F33E|4flowers|flower shop|floral shop|floral arrangements|same day flowers|bouquet",
|
||||
|
||||
@@ -220,13 +220,13 @@
|
||||
"tourism-motel|@category_hotel": "3Motel|auberge de jeunesse",
|
||||
"tourism-alpine_hut|@category_hotel": "Refuge de montagne|auberge de jeunesse|cabane alpine",
|
||||
"shop-hairdresser": "3Coiffeur|salon de coiffure",
|
||||
"aeroway-aerodrome": "3Aéroport|3aérodrome|3avion",
|
||||
"aeroway-aerodrome": "3Aéroport|3aérodrome|3avion|3aérogare",
|
||||
"leisure-stadium": "4Stade|4sport",
|
||||
"leisure-playground|@category_children": "Terrain de jeu|aire de jeu",
|
||||
"leisure-sports_centre|leisure-sports_centre-sport-american_football|leisure-sports_centre-sport-archery|leisure-sports_centre-sport-athletics|leisure-sports_centre-sport-australian_football|leisure-sports_centre-sport-badminton|leisure-sports_centre-sport-baseball|leisure-sports_centre-sport-basketball|leisure-sports_centre-sport-beachvolleyball|leisure-sports_centre-sport-bowls|leisure-sports_centre-sport-climbing|leisure-sports_centre-sport-cricket|leisure-sports_centre-sport-curling|leisure-sports_centre-sport-equestrian|leisure-sports_centre-sport-field_hockey|leisure-sports_centre-sport-futsal|leisure-sports_centre-sport-golf|leisure-sports_centre-sport-gymnastics|leisure-sports_centre-sport-handball|leisure-sports_centre-sport-ice_hockey|leisure-sports_centre-sport-multi|leisure-sports_centre-sport-padel|leisure-sports_centre-sport-pelota|leisure-sports_centre-sport-scuba_diving|leisure-sports_centre-sport-shooting|leisure-sports_centre-sport-skateboard|leisure-sports_centre-sport-skiing|leisure-sports_centre-sport-soccer|leisure-sports_centre-sport-table_tennis|leisure-sports_centre-sport-tennis|leisure-sports_centre-sport-volleyball|leisure-sports_centre-sport-yoga": "Centre sportif|sport",
|
||||
"leisure-playground|@category_children": "Terrain de jeu|aire de jeu|parc de jeux|espace de jeu",
|
||||
"leisure-sports_centre|leisure-sports_centre-sport-american_football|leisure-sports_centre-sport-archery|leisure-sports_centre-sport-athletics|leisure-sports_centre-sport-australian_football|leisure-sports_centre-sport-badminton|leisure-sports_centre-sport-baseball|leisure-sports_centre-sport-basketball|leisure-sports_centre-sport-beachvolleyball|leisure-sports_centre-sport-bowls|leisure-sports_centre-sport-climbing|leisure-sports_centre-sport-cricket|leisure-sports_centre-sport-curling|leisure-sports_centre-sport-equestrian|leisure-sports_centre-sport-field_hockey|leisure-sports_centre-sport-futsal|leisure-sports_centre-sport-golf|leisure-sports_centre-sport-gymnastics|leisure-sports_centre-sport-handball|leisure-sports_centre-sport-ice_hockey|leisure-sports_centre-sport-multi|leisure-sports_centre-sport-padel|leisure-sports_centre-sport-pelota|leisure-sports_centre-sport-scuba_diving|leisure-sports_centre-sport-shooting|leisure-sports_centre-sport-skateboard|leisure-sports_centre-sport-skiing|leisure-sports_centre-sport-soccer|leisure-sports_centre-sport-table_tennis|leisure-sports_centre-sport-tennis|leisure-sports_centre-sport-volleyball|leisure-sports_centre-sport-yoga": "Centre sportif|salle omnisports|complexe sportif|sport",
|
||||
"leisure-golf_course": "Terrain de golf|Parcours de golf",
|
||||
"leisure-miniature_golf": "Minigolf",
|
||||
"leisure-escape_game": "Salle d'évasion",
|
||||
"leisure-escape_game": "Salle d'évasion|escape game",
|
||||
"leisure-pitch": "Terrain de sport|sport",
|
||||
"leisure-swimming_pool": "4Piscine|sport",
|
||||
"sport-american_football": "Football américain",
|
||||
@@ -245,12 +245,12 @@
|
||||
"sport-gymnastics": "Gymnastique",
|
||||
"sport-handball": "Handball",
|
||||
"sport-scuba_diving": "Plongée sous-marine",
|
||||
"sport-shooting": "Stand de tir|Centre de tir",
|
||||
"sport-shooting": "Stand de tir|Centre de tir|champ de tir|salle de tir",
|
||||
"sport-skateboard": "Skateboard",
|
||||
"sport-skiing": "Ski",
|
||||
"sport-soccer": "Football",
|
||||
"sport-swimming": "Piscine|Natation",
|
||||
"sport-table_tennis": "Tennis de table",
|
||||
"sport-table_tennis": "Tennis de table|Ping Pong",
|
||||
"sport-tennis": "Tennis",
|
||||
"sport-padel": "Padel",
|
||||
"sport-volleyball": "Volley-ball",
|
||||
@@ -272,27 +272,27 @@
|
||||
"natural-water-pond|@waterbody": "Étang|bassin",
|
||||
"natural-water-lake|@waterbody": "Lac",
|
||||
"natural-water-reservoir|landuse-reservoir|@waterbody": "5Réservoir",
|
||||
"waterway-river|waterway-stream|natural-water-river": "Rivière|fleuve",
|
||||
"waterway-river|waterway-stream|natural-water-river": "Rivière|fleuve|ruisseau|cours d'eau|torrent",
|
||||
"waterway-canal": "Canal",
|
||||
"shop-car_repair": "3Réparation d'automobiles|3garage|4station service|voiture|auto|garagiste|mécano|mécanicien automobile",
|
||||
"tourism-camp_site|@category_hotel": "4Camping|terrain de camping",
|
||||
"tourism-caravan_site|@category_rv||@category_hotel": "4Parc caravanier|VR|caravane|camping-car",
|
||||
"office": "Bureau|compagnie",
|
||||
"office-company": "Bureaux d'entreprise",
|
||||
"office-government": "Administration publique",
|
||||
"office-lawyer": "Cabinet d'avocat",
|
||||
"office-government": "Administration publique|service public|fonction publique|service civil|services administratifs",
|
||||
"office-lawyer": "Cabinet d'avocat|bureau d'avocat",
|
||||
"office-telecommunication": "Opérateur mobile",
|
||||
"craft-beekeeper": "Apiculteur",
|
||||
"craft-blacksmith": "Forgeron",
|
||||
"craft-brewery": "Brasserie artisanale|Brasseur",
|
||||
"craft-brewery": "Brasserie artisanale|Brasseur|micro-brasserie",
|
||||
"craft-caterer": "Traiteur",
|
||||
"craft-carpenter": "Menuisier|charpentier",
|
||||
"craft-confectionery": "Confiseur",
|
||||
"craft-electrician": "4Électricien",
|
||||
"craft-electronics_repair": "Réparation d'appareils électroniques",
|
||||
"craft-gardener": "Paysagiste",
|
||||
"craft-gardener": "Paysagiste|jardinier",
|
||||
"craft-grinding_mill": "Moulin",
|
||||
"craft-handicraft": "Artisanat",
|
||||
"craft-handicraft": "Artisanat|fait-main|métiers d'art",
|
||||
"craft-hvac": "Chauffage, ventilation et climatisation",
|
||||
"craft-metal_construction": "5Métallo|métallurgiste",
|
||||
"craft-key_cutter": "Reproduction de clé",
|
||||
@@ -302,7 +302,7 @@
|
||||
"craft-plumber": "Plombier",
|
||||
"craft-sawmill": "Scierie",
|
||||
"craft-shoemaker": "Cordonnier",
|
||||
"craft-winery": "Chai",
|
||||
"craft-winery": "Chai|établissement vinicole",
|
||||
"craft-tailor": "5Tailleur",
|
||||
"area:highway-footway|area:highway-pedestrian|area:highway-steps|place-square": "Place",
|
||||
"place-sea": "Mer",
|
||||
@@ -320,11 +320,11 @@
|
||||
"shop-copyshop": "Boutique de photocopies|5Imprimerie",
|
||||
"shop-photo|@shop": "5Matériel de photographie|5Photographie|Cadres",
|
||||
"shop-camera|@shop": "Boutique d'appareils photo",
|
||||
"shop-travel_agency": "Agence de voyages|Voyages organisés",
|
||||
"shop-travel_agency": "Agence de voyages|Voyages organisés|agence de tourisme|voyagiste",
|
||||
"shop-outdoor|@shop": "Matériel de loisirs de plein air|Randonnée|Escalade|Camping",
|
||||
"shop-dry_cleaning": "Nettoyage à sec|Pressing|Lavage",
|
||||
"shop-tyres|@shop": "Pneu|Pneus",
|
||||
"amenity-car_wash": "Station de lavage|lavage-autp",
|
||||
"amenity-car_wash": "Station de lavage|lavage-auto|lavage de voiture",
|
||||
"amenity-veterinary": "Docteur vétérinaire|véto|Clinique vétérinaire",
|
||||
"@charging_station": "Borne de recharge|station de recharge|4voiture électrique|4recharge|IRVE",
|
||||
"amenity-charging_station-bicycle|@charging_station": "Chargement des vélos",
|
||||
@@ -332,14 +332,14 @@
|
||||
"amenity-bicycle_parking": "Parking à vélo|Stationnement vélo",
|
||||
"amenity-waste_basket": "Poubelle",
|
||||
"emergency-phone": "3Téléphone d'urgence",
|
||||
"leisure-fitness_centre": "Centre fitness|salle de gym|salle de sport",
|
||||
"leisure-fitness_centre": "Centre fitness|salle de gym|salle de sport|centre de remise en forme",
|
||||
"leisure-sauna": "3Sauna",
|
||||
"shop-car_repair-tyres|shop-car_repair": "Réparation de pneus",
|
||||
"shop-chemist|@shop": "4Droguerie",
|
||||
"shop-pet|@shop": "5Animalerie",
|
||||
"tourism-zoo|@category_tourism|@category_children": "Zoo|Parc Animalier",
|
||||
"shop-pet|@shop": "5Animalerie|magasin d'animaux",
|
||||
"tourism-zoo|@category_tourism|@category_children": "Zoo|Parc Animalier|ménagerie|parc zoologique",
|
||||
"attraction-animal": "Enclos pour animaux",
|
||||
"tourism-information-office|amenity-ranger_station|@category_tourism": "Office de tourisme|syndicat d'initiative",
|
||||
"tourism-information-office|amenity-ranger_station|@category_tourism": "Office de tourisme|syndicat d'initiative|bureau d'information touristique",
|
||||
"tourism-information-visitor_centre|amenity-ranger_station|@category_tourism": "centre de visite",
|
||||
"amenity-community_centre": "Centre communautaire|Salle polyvalente|Salle des fêtes",
|
||||
"amenity-compressed_air": "Air comprimé",
|
||||
@@ -350,14 +350,14 @@
|
||||
"amenity-vending_machine-drinks": "Distributeur de boissons|cannettes",
|
||||
"amenity-vending_machine-food|@category_food": "Distributeur d'aliments|Aliments",
|
||||
"amenity-vending_machine-parking_tickets|@category_parking": "Horodateur|parcmètre",
|
||||
"amenity-vending_machine-public_transport_tickets|@category_transport": "Distributeur de billets de transport en commun|ticket de bus",
|
||||
"amenity-vending_machine-public_transport_tickets|@category_transport": "Distributeur de billets de transport en commun|ticket de bus|ticket de tram|ticket de métro",
|
||||
"amenity-vending_machine-newspapers": "Distributeur de journaux|Journaux",
|
||||
"amenity-vending_machine-sweets": "Distributeur de bonbons|Bonbons",
|
||||
"amenity-vending_machine-excrement_bags": "5Distributeur de sacs à excréments",
|
||||
"amenity-parcel_locker|@category_post": "Consigne automatique pour colis|3locker",
|
||||
"shop-outpost": "Point de retrait",
|
||||
"building-garage": "Garage",
|
||||
"highway-rest_area|highway-services": "Aire de repos|Aire de service",
|
||||
"highway-rest_area|highway-services": "Aire de repos|Aire de service|relais routier",
|
||||
"man_made-chimney": "Cheminée",
|
||||
"man_made-tower|man_made-flare": "Tour",
|
||||
"shop-bookmaker|@gambling": "Bookmaker",
|
||||
@@ -371,12 +371,12 @@
|
||||
"tourism-information-board": "Panneau d'informations",
|
||||
"tourism-information-map": "Carte touristique|Plan",
|
||||
"aerialway-station": "Remontées mécaniques",
|
||||
"aeroway-helipad": "Hélisurface",
|
||||
"barrier-border_control": "Contrôle aux frontières",
|
||||
"aeroway-helipad": "Hélisurface|zone d'atterrissage pour hélicoptères",
|
||||
"barrier-border_control": "Contrôle aux frontières|contrôle frontalier",
|
||||
"leisure-water_park|@category_tourism|@category_children": "Centre aquatique|Parc aquatique",
|
||||
"man_made-water_tower": "Château d'eau",
|
||||
"man_made-windmill": "Moulin",
|
||||
"natural-cave_entrance": "4Grotte",
|
||||
"natural-cave_entrance": "4Grotte|caverne",
|
||||
"natural-volcano|@mountain": "4Volcan",
|
||||
"office-estate_agent": "Agence immobilière|agent immobilier",
|
||||
"waterway-lock_gate": "Écluse",
|
||||
@@ -387,24 +387,24 @@
|
||||
"leisure-resort|@category_hotel": "Complexe touristique",
|
||||
"amenity-biergarten|@category_eat|@category_nightlife": "5Biergarten",
|
||||
"amenity-driving_school": "4Auto-école|École de conduite",
|
||||
"amenity-music_school": "École de musique",
|
||||
"amenity-music_school": "École de musique|conservatoire de musique",
|
||||
"amenity-language_school": "École de langue",
|
||||
"amenity-ice_cream": "Stand de crème glacée|Marchand de glaces|Glacier",
|
||||
"amenity-internet_cafe": "5Cybercafé",
|
||||
"amenity-motorcycle_parking": "Parking moto|Stationnement moto",
|
||||
"amenity-parking_space-disabled|@category_parking": "Place de stationnement handicapé|Stationnement PMR|Parking PMR",
|
||||
"amenity-nursing_home": "Maison de retraite|résidence pour personnes âgées",
|
||||
"amenity-nursing_home": "Maison de retraite|résidence pour personnes âgées|EHPAD",
|
||||
"amenity-payment_terminal": "Terminal de paiement",
|
||||
"amenity-public_bath": "Bain public",
|
||||
"amenity-shower": "Douche",
|
||||
"emergency-assembly_point": "Point de rassemblement d'urgence",
|
||||
"emergency-defibrillator": "4Défibrillateur|DAE",
|
||||
"emergency-fire_hydrant": "Bouche d’incendie|bouche de incendie|borne d’incendie|borne de incendie|Borne hydratante|Poteau d’incendie|Hydrant|Hydrante",
|
||||
"amenity-hydrant": "Bouche d’puisage|bouche de puisage|borne d’puisage|bourne de puisage|Hydrant|Hydrante",
|
||||
"emergency-lifeguard": "Sauveteur d’urgence|Sauveteur",
|
||||
"emergency-fire_hydrant": "Bouche d’incendie|borne d’incendie|Poteau d’incendie|Hydrant",
|
||||
"amenity-hydrant": "Bouche de puisage|borne de puisage|Hydrant",
|
||||
"emergency-lifeguard": "Sauveteur d’urgence",
|
||||
"emergency-mountain_rescue": "Sauveteurs en montagne d’urgence",
|
||||
"leisure-fitness_station": "Station de fitness|Parcours de santé",
|
||||
"office-insurance": "Bureau d’assurance|assureur|Agent d'assurance",
|
||||
"office-insurance": "Bureau d’assurance|assureur|Agent d'assurance|courtier en assurance|compagnie d'assurance",
|
||||
"office-ngo": "Bureau d'ONG|organisation non gouvernementale|Bureau ONG",
|
||||
"shop-erotic|@shop": "Boutique érotique",
|
||||
"shop-massage": "Salon de massage",
|
||||
@@ -416,10 +416,10 @@
|
||||
"shop-tattoo": "Salon de tatouage|tatoueur",
|
||||
"shop-variety_store|@category_shopping|@shop": "Bazar",
|
||||
"shop-video|@shop": "Boutique de vidéos|videostore",
|
||||
"shop-video_games|@shop": "Boutique de jeux vidéo",
|
||||
"shop-video_games|@shop": "Boutique de jeux vidéos",
|
||||
"tourism-wilderness_hut|@category_hotel": "Refuge non gardé|Refuge-bivouac",
|
||||
"tourism-gallery|@category_tourism": "3Galerie d'art|musée d'art",
|
||||
"tourism-theme_park|@category_tourism|@category_children": "Parc d'attractions|Parc de loisirs",
|
||||
"tourism-gallery|@category_tourism": "3Galerie d'art|musée d'art|galerie de peinture",
|
||||
"tourism-theme_park|@category_tourism|@category_children": "Parc d'attractions|Parc de loisirs|parc à thèmes",
|
||||
"boundary-national_park|@category_tourism": "Parc national",
|
||||
"leisure-nature_reserve|@category_tourism": "Réserve naturelle",
|
||||
"natural-cape": "Cap",
|
||||
@@ -447,7 +447,7 @@
|
||||
"shop-medical_supply|@shop": "Materiel médical",
|
||||
"shop-nutrition_supplements|@shop": "Suppléments nutritionnels",
|
||||
"shop-paint|@shop": "Magasin de peinture",
|
||||
"shop-perfumery|@category_shopping|@shop": "Parfumerie",
|
||||
"shop-perfumery|@category_shopping|@shop": "Parfumerie|boutique de parfum",
|
||||
"shop-sewing|@shop": "Mercerie|Couture",
|
||||
"shop-storage_rental": "Location de stockage",
|
||||
"shop-tobacco|@shop": "Bureau de tabac",
|
||||
@@ -462,19 +462,19 @@
|
||||
"amenity-social_facility": "Établissement de services sociaux",
|
||||
"leisure-sports_hall": "Salle de sport",
|
||||
"amenity-arts_centre|@category_tourism": "Centre artistique",
|
||||
"amenity-prison": "prison",
|
||||
"amenity-prison": "prison|centre pénitentiaire|centre de détention",
|
||||
"amenity-exhibition_centre": "Centre d'exposition",
|
||||
"shop-bathroom_furnishing|@shop": "Mobilier de salle de bain",
|
||||
"shop-bed|@shop": "Magasin de literie",
|
||||
"shop-boutique|@shop": "Boutique",
|
||||
"amenity-food_court": "Aire de restauration",
|
||||
"amenity-food_court": "Aire de restauration|foodcourt",
|
||||
"shop-curtain|@shop": "Magasin de rideaux",
|
||||
"shop-gas|@shop": "Vente de gaz",
|
||||
"shop-gas|@shop": "Vente de gaz|bouteille de gaz",
|
||||
"shop-pet_grooming": "Salon de toilettage",
|
||||
"shop-hifi|@shop": "Matériel Hi-Fi",
|
||||
"amenity-conference_centre": "Centre de conférence",
|
||||
"shop-herbalist|@shop": "Herboristerie",
|
||||
"shop-appliance|@shop": "Magasin d'électroménager",
|
||||
"shop-appliance|@shop": "Magasin d'électroménager|boutique d'électroménager",
|
||||
"shop-agrarian|@shop": "Magasin d'agriculture",
|
||||
"shop-fashion_accessories|@shop": "Boutique d'accessoires de mode",
|
||||
"amenity-waste_transfer_station": "Station de transfert de déchets",
|
||||
@@ -489,7 +489,7 @@
|
||||
"amenity-charging_station-motorcar|amenity-charging_station-motorcar-small|@charging_station": "Chargeur automobile|Chargeur de voiture|Chargeur",
|
||||
"shop-lighting|@shop": "4Lumières|Luminaires|4Lampes",
|
||||
"office-security": "Bureau de sécurité",
|
||||
"building-guardhouse": "Garde",
|
||||
"building-guardhouse": "Garde|poste de sécurité|poste de gardiennage",
|
||||
"leisure-dance|@category_entertainment": "4Danse|École de danse",
|
||||
"shop-money_lender": "Prêteur d'argent",
|
||||
"attraction-amusement_ride|attraction-carousel|attraction-roller_coaster|attraction-maze|attraction-historic|attraction-big_wheel|attraction-bumper_car|@category_children": "Attraction|Labyrinthe",
|
||||
|
||||
@@ -550,7 +550,7 @@
|
||||
"Italy_Emilia-Romagna_Forli-Cesena":"Покрајина Форли-Чезена",
|
||||
"Italy_Emilia-Romagna_Modena":"Покрајина Модена",
|
||||
"Italy_Emilia-Romagna_Parma":"Покрајина Парма",
|
||||
"Italy_Emilia-Romagna_Piacenza":"Покрајина Пјаћенца",
|
||||
"Italy_Emilia-Romagna_Piacenza":"Покрајина Пјаченца",
|
||||
"Italy_Emilia-Romagna_Ravenna":"Покрајина Равена",
|
||||
"Italy_Emilia-Romagna_Reggio Emilia":"Покрајина Ређо Емилија",
|
||||
"Italy_Emilia-Romagna_Rimini":"Покрајина Римини",
|
||||
@@ -1881,7 +1881,7 @@
|
||||
"Italy_Veneto_Treviso Description":"Тревизо, Конелијано, Кастелфранко Венето",
|
||||
"Italy_Veneto_Venezia Description":"Венеција, Местре, Кјоџа",
|
||||
"Italy_Veneto_Verona Description":"Верона, Вилафранка ди Верона, Лењаго",
|
||||
"Italy_Veneto_Vicenza Description":"Вићенца, Басано дел Грапа, Скио",
|
||||
"Italy_Veneto_Vicenza Description":"Виченца, Басано дел Грапа, Скио",
|
||||
"Jamaica Description":"Кингстон, Монтего Беј, Спениш Таун",
|
||||
"Japan_Chubu Region_Aichi_Nagoya Description":"Нагоја, Цушима, Кијосу",
|
||||
"Japan_Chubu Region_Aichi_Toyohashi Description":"Тахара, Гамагори, Нишио",
|
||||
|
||||
4620
data/countries.txt
4620
data/countries.txt
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@
|
||||
"take_exit_number":"Nehmen Sie die Ausfahrt auf",
|
||||
"take_exit_number_street_verb":"NULL",
|
||||
"route_recalculating":"Neuberechnung der Route",
|
||||
"destination":"Werden Sie ankommen.",
|
||||
"destination":"erreichen Sie ihr Ziel.",
|
||||
"you_have_reached_the_destination":"Sie haben Ihr Ziel erreicht.",
|
||||
"in_50_meters":"In fünfzig Metern",
|
||||
"in_100_meters":"In einhundert Metern",
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
{
|
||||
"make_a_slight_right_turn":"Rechts aanhouden.",
|
||||
"make_a_slight_right_turn_street":"flauwe bocht naar rechts",
|
||||
"make_a_slight_right_turn_street":"een flauwe bocht naar rechts",
|
||||
"make_a_right_turn":"Sla rechtsaf.",
|
||||
"make_a_right_turn_street":"Sla rechtsaf",
|
||||
"make_a_sharp_right_turn":"Scherp rechtsaf.",
|
||||
"make_a_sharp_right_turn_street":"scherp naar rechts afslaan",
|
||||
"enter_the_roundabout":"Rij de rotonde op.",
|
||||
"enter_the_roundabout_street":"de rotonde",
|
||||
"enter_the_roundabout_street_verb":"Rijd",
|
||||
"enter_the_roundabout_street":"de rotonde op",
|
||||
"enter_the_roundabout_street_verb":"Rij",
|
||||
"leave_the_roundabout":"Verlaat de rotonde.",
|
||||
"leave_the_roundabout_street":"de rotonde",
|
||||
"leave_the_roundabout_street_verb":"Verlaat",
|
||||
"make_a_slight_left_turn":"Links aanhouden.",
|
||||
"make_a_slight_left_turn_street":"de flauwe bocht naar links",
|
||||
"make_a_slight_left_turn_street":"een flauwe bocht naar links",
|
||||
"make_a_slight_left_turn_street_verb":"Neem",
|
||||
"make_a_left_turn":"Sla linksaf.",
|
||||
"make_a_left_turn_street":"naar links afslaan",
|
||||
"make_a_left_turn_street":"Sla linksaf",
|
||||
"make_a_sharp_left_turn":"Scherp linksaf.",
|
||||
"make_a_sharp_left_turn_street":"scherp naar links afslaan",
|
||||
"make_a_u_turn":"Keer om.",
|
||||
"make_a_u_turn_street":"NULL",
|
||||
"make_a_u_turn_street_verb":"NULL",
|
||||
"make_a_u_turn_street":"om",
|
||||
"make_a_u_turn_street_verb":"Keer",
|
||||
"go_straight":"Rij rechtdoor.",
|
||||
"exit":"Verlaat.",
|
||||
"onto":"naar",
|
||||
"take_exit_number":"Verlaat naar",
|
||||
"take_exit_number_street_verb":"Neem",
|
||||
"route_recalculating":"De route herberekenen",
|
||||
"route_recalculating":"Route herberekenen",
|
||||
"destination":"Arriveert u.",
|
||||
"you_have_reached_the_destination":"Bestemming bereikt.",
|
||||
"in_50_meters":"Over vijftig meter",
|
||||
@@ -104,5 +104,5 @@
|
||||
"in_1_5_miles":"Over anderhalve mijl",
|
||||
"in_2_miles":"Over twee mijl",
|
||||
"unknown_camera":"Camera in zicht",
|
||||
"make_a_slight_right_turn_street_verb":"NULL"
|
||||
"make_a_slight_right_turn_street_verb":"Neem"
|
||||
}
|
||||
|
||||
17
data/test_data/traff/DE-A10-Werder-GrossKreutz.xml
Normal file
17
data/test_data/traff/DE-A10-Werder-GrossKreutz.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<!-- From DE-RealWorldLargeFeed. -->
|
||||
<!--
|
||||
The route starts at a large junction, goes down the wrong carriageway of the motorway,
|
||||
changes direction at the next junction, then back.
|
||||
-->
|
||||
<feed>
|
||||
<message expiration_time="2025-10-09T21:37:08+03:00" id="tmc:d.1.7:d.1.10209.n.1" receive_time="2025-10-09T21:17:08+03:00" update_time="2025-10-09T21:17:08+03:00">
|
||||
<location directionality="ONE_DIRECTION" fuzziness="LOW_RES" road_class="MOTORWAY" road_name="Westlicher Berliner Ring" road_ref="A10">
|
||||
<from junction_name="Werder" junction_ref="21">+52.334801 +12.814650</from>
|
||||
<to junction_name="Groß Kreutz" junction_ref="22">+52.393700 +12.835000</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONGESTION" type="CONGESTION_STATIONARY_TRAFFIC">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
17
data/test_data/traff/DE-A115-PotsdamDrewitz-Nuthetal.xml
Normal file
17
data/test_data/traff/DE-A115-PotsdamDrewitz-Nuthetal.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<!-- From DE-RealWorldLargeFeed. -->
|
||||
<!--
|
||||
The route ends at a large junction, proceeds past the reference point, then
|
||||
goes back down the wrong carriageway of the motorway.
|
||||
-->
|
||||
<feed>
|
||||
<message expiration_time="2025-10-09T21:37:08+03:00" id="tmc:d.1.7:d.1.10292.p.1" receive_time="2025-10-09T21:17:08+03:00" update_time="2025-10-09T21:17:08+03:00">
|
||||
<location directionality="ONE_DIRECTION" fuzziness="LOW_RES" road_class="MOTORWAY" road_name="Autobahnzubringer Magdeburg" road_ref="A115">
|
||||
<from junction_name="Potsdam-Drewitz" junction_ref="5a">+52.352650 +13.140700</from>
|
||||
<to junction_name="Nuthetal" junction_ref="7">+52.300201 +13.083500</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONGESTION" type="CONGESTION_STATIONARY_TRAFFIC">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
@@ -0,0 +1,16 @@
|
||||
<!--
|
||||
From DE-realworld5.
|
||||
Test case for turn penalty (eastern end).
|
||||
-->
|
||||
<feed>
|
||||
<message expiration_time="2025-10-09T21:37:08+03:00" id="tmc:d.1.15:d.1.29829.n.1" receive_time="2025-10-09T21:17:08+03:00" update_time="2025-10-09T21:17:08+03:00">
|
||||
<location directionality="ONE_DIRECTION" fuzziness="LOW_RES" road_name="Mittlerer Ring" road_ref="B2R">
|
||||
<from junction_name="Lerchenauer Straße">+48.176102 +11.558100</from>
|
||||
<to junction_name="Petueltunnel">+48.178001 +11.572800</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONGESTION" type="CONGESTION_QUEUE">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
19
data/test_data/traff/DE-B2R-SendlingSued-Passauerstrasse.xml
Normal file
19
data/test_data/traff/DE-B2R-SendlingSued-Passauerstrasse.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- From DE-realworld5. -->
|
||||
<!--
|
||||
A combination of reference points on the opposite carriageway, high offroad cost,
|
||||
allowing any road to be used and a low penalty results in a completely incorrect
|
||||
location (through a residential area rather than along the opposite carriageway).
|
||||
Test case for turn penalty (eastern end) if the above is resolved.
|
||||
-->
|
||||
<feed>
|
||||
<message expiration_time="2025-10-09T21:37:08+03:00" id="tmc:d.1.15:d.1.22689.p.1" receive_time="2025-10-09T21:17:08+03:00" update_time="2025-10-09T21:17:08+03:00">
|
||||
<location directionality="ONE_DIRECTION" fuzziness="LOW_RES" road_name="Mittlerer Ring" road_ref="B2R">
|
||||
<from junction_name="München-Sendling-Süd">+48.110901 +11.518500</from>
|
||||
<to junction_name="Passauerstraße">+48.110649 +11.534150</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONGESTION" type="CONGESTION_QUEUE">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
22
data/test_data/traff/DE-GM4-UrbanDualCarriagewayEndpoint.xml
Normal file
22
data/test_data/traff/DE-GM4-UrbanDualCarriagewayEndpoint.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
Subset of realworld5.
|
||||
Test case for turn penalty (both ends).
|
||||
Junction names are the names of the crossing roads.
|
||||
No segments of the crossing roads should be among the matched segments.
|
||||
-->
|
||||
<feed>
|
||||
<message expiration_time="2025-10-09T21:37:08+03:00" id="tmc:d.1.15:d.1.46572.p.1,14" receive_time="2025-10-09T21:17:08+03:00" update_time="2025-10-09T21:17:08+03:00">
|
||||
<location directionality="ONE_DIRECTION" fuzziness="LOW_RES" road_name="Leopoldstraße" road_ref="GM4">
|
||||
<from junction_name="Potsdamer Straße">+48.167301 +11.586200</from>
|
||||
<to junction_name="Ungererstraße">+48.164200 +11.586500</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="INCIDENT" type="INCIDENT_ACCIDENT">
|
||||
</event>
|
||||
<event class="CONGESTION" type="CONGESTION_STATIONARY_TRAFFIC">
|
||||
</event>
|
||||
<event class="HAZARD" type="HAZARD_PASSABLE_WITH_CARE_BELOW_ELEVATION">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
58
data/test_data/traff/DE-RoundaboutEndpoint.xml
Executable file
58
data/test_data/traff/DE-RoundaboutEndpoint.xml
Executable file
@@ -0,0 +1,58 @@
|
||||
<!--
|
||||
Test cases for reference points inside a roundabout.
|
||||
If the roundabout itself is included in the decoded location, the message would
|
||||
affect all roads which connect to it, resulting in incorrect routing, especially
|
||||
in the case of closure events. For this reason, we must truncate roundabouts if
|
||||
they occur at the start or end of the decoded location.
|
||||
-->
|
||||
<feed>
|
||||
<message id="tmc:d.1.12:d.1.13962.p.5,11" receive_time="2018-07-27T10:22:22+02:00" update_time="2018-07-27T08:43:15Z" expiration_time="2018-07-27T09:43:15Z" urgency="URGENT">
|
||||
<location fuzziness="LOW_RES" directionality="BOTH_DIRECTIONS" road_class="SECONDARY" road_ref="L87">
|
||||
<from junction_name="Rheinau-Freistett/B36">+48.661098 +7.936800</from>
|
||||
<to junction_name="Gambsheim (F)">+48.683701 +7.916600</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONSTRUCTION" type="CONSTRUCTION_CONSTRUCTION_WORK">
|
||||
</event>
|
||||
<event class="RESTRICTION" type="RESTRICTION_CLOSED">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
<message id="tmc:d.1.12:d.1.26212.p.5,11" receive_time="2018-07-27T10:21:49+02:00" update_time="2018-07-27T08:42:41Z" expiration_time="2018-07-27T09:42:41Z" urgency="URGENT">
|
||||
<location fuzziness="LOW_RES" directionality="BOTH_DIRECTIONS" road_class="PRIMARY" road_ref="B428">
|
||||
<from junction_name="Hackenheim">+49.822948 +7.906900</from>
|
||||
<to junction_name="Frei-Laubersheim">+49.803650 +7.901450</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONSTRUCTION" type="CONSTRUCTION_LONGTERM_ROADWORKS">
|
||||
</event>
|
||||
<event class="RESTRICTION" type="RESTRICTION_CLOSED">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
<message id="tmc:d.1.12:d.1.48638.n.9,11" receive_time="2018-07-27T10:11:06+02:00" update_time="2018-07-27T08:31:43Z" expiration_time="2018-07-27T09:31:43Z" urgency="URGENT">
|
||||
<location fuzziness="LOW_RES" directionality="BOTH_DIRECTIONS" road_class="PRIMARY" road_ref="B272">
|
||||
<from junction_name="Hochstadt">+49.239750 +8.222300</from>
|
||||
<to junction_name="Weingarten">+49.253448 +8.268100</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONSTRUCTION" type="CONSTRUCTION_ROADWORKS">
|
||||
</event>
|
||||
<event class="RESTRICTION" type="RESTRICTION_CLOSED_AHEAD">
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
<message id="tmc:d.1.12:d.1.56576.n.9,11" receive_time="2018-07-27T10:22:53+02:00" update_time="2018-07-27T08:43:45Z" expiration_time="2018-07-27T09:43:45Z" urgency="URGENT">
|
||||
<location fuzziness="LOW_RES" directionality="ONE_DIRECTION" road_class="PRIMARY" road_ref="B417">
|
||||
<from junction_name="Diez">+50.372398 +8.038500</from>
|
||||
<to junction_name="Diez">+50.370850 +8.004050</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="CONSTRUCTION" type="CONSTRUCTION_RESURFACING_WORK">
|
||||
</event>
|
||||
<event class="RESTRICTION" type="RESTRICTION_CLOSED">
|
||||
<supplementary_info class="VEHICLE" type="S_VEHICLE_THROUGH_TRAFFIC"/>
|
||||
</event>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
23
data/test_data/traff/LT-A5-Kaunas-Eastbound.xml
Normal file
23
data/test_data/traff/LT-A5-Kaunas-Eastbound.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<!--
|
||||
This is a 140 m location. Reference points are almost exactly on the opposite
|
||||
carriageway; since this is inside a junction, there is a wider gap between
|
||||
the two carriageways than there would be on a normal stretch of expressway.
|
||||
Without truncation, the decoded location starts approximately in the right
|
||||
spot but overshoots the end point, going to the nearest junction, then back
|
||||
in the opposite direction and to the end point on the opposite carriageway,
|
||||
ending within 5 m of the end point.
|
||||
-->
|
||||
<feed>
|
||||
<message id="lt.eismoinfo.restrictions:4249b6510b73750684ca94de5fe8cf32,eastbound" receive_time="2025-01-21T12:33:06Z" update_time="2025-01-21T12:33:06Z" expiration_time="2025-12-31T21:00:00Z" cancellation="false" forecast="false" urgency="NORMAL">
|
||||
<merge/>
|
||||
<location country="LT" origin="Suvalkai*" directionality="ONE_DIRECTION" destination="Kaunas" road_class="TRUNK" road_ref="A5">
|
||||
<from distance="0.14">54.939945 23.879789</from>
|
||||
<to distance="0.0" junction_name="Kaunas">54.940094 23.881950</to>
|
||||
</location>
|
||||
<events>
|
||||
<event class="RESTRICTION" type="RESTRICTION_MAX_WIDTH" q_dimension="3.5"/>
|
||||
<event class="CONSTRUCTION" type="CONSTRUCTION_ROADWORKS"/>
|
||||
<event class="RESTRICTION" type="RESTRICTION_SPEED_LIMIT" speed="50"/>
|
||||
</events>
|
||||
</message>
|
||||
</feed>
|
||||
@@ -108,8 +108,6 @@ auto constexpr TMP_OFFSETS_EXT = OFFSET_EXT EXTENSION_TMP;
|
||||
#define CROSS_MWM_OSM_WAYS_DIR "cross_mwm_osm_ways"
|
||||
#define TEMP_ADDR_EXTENSION ".tempaddr"
|
||||
|
||||
#define TRAFFIC_FILE_EXTENSION ".traffic"
|
||||
|
||||
#define SKIPPED_ELEMENTS_FILE "skipped_elements.json"
|
||||
|
||||
#define MAPCSS_MAPPING_FILE "mapcss-mapping.csv"
|
||||
|
||||
@@ -207,8 +207,6 @@ set(SRC
|
||||
tesselator.hpp
|
||||
towns_dumper.cpp
|
||||
towns_dumper.hpp
|
||||
traffic_generator.cpp
|
||||
traffic_generator.hpp
|
||||
transit_generator.cpp
|
||||
transit_generator.hpp
|
||||
transit_generator_experimental.cpp
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user