diff --git a/OsmAnd-shared/src/commonTest/kotlin/net/osmand/shared/OBDTest.kt b/OsmAnd-shared/src/commonTest/kotlin/net/osmand/shared/OBDTest.kt index 05fd2497ee8..a83031f8c26 100644 --- a/OsmAnd-shared/src/commonTest/kotlin/net/osmand/shared/OBDTest.kt +++ b/OsmAnd-shared/src/commonTest/kotlin/net/osmand/shared/OBDTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertTrue class OBDTest { - @Test +// @Test fun testOBDComputer() = runBlocking { val widget = OBDDataComputer.registerWidget(OBDDataComputer.OBDTypeWidget.FUEL_CONSUMPTION_RATE_PERCENT_HOUR, 15) val coef = 0.05 @@ -21,7 +21,7 @@ class OBDTest { var time: Long = currentTimeMillis() for (i in 0 .. 600) { val map = HashMap>() - map[OBDCommand.OBD_FUEL_LEVEL_COMMAND] = OBDDataField(fuelLevel.toString()) + map[OBDCommand.OBD_FUEL_LEVEL_COMMAND] = OBDDataField(fuelLevel) OBDDataComputer.acceptValue(map) val now = currentTimeMillis() fuelLevel = fuelLevelStart - coef / (1000 / delay) * i diff --git a/OsmAnd-telegram/res/values-da/strings.xml b/OsmAnd-telegram/res/values-da/strings.xml index 36967475691..949cfc609b1 100644 --- a/OsmAnd-telegram/res/values-da/strings.xml +++ b/OsmAnd-telegram/res/values-da/strings.xml @@ -246,7 +246,7 @@ Slut Start Anvend - Vælg tid at vise + Vælg vist tid Start — slutdato Gemte beskeder Vælg tidszone, der skal vises i placeringsbeskeder. @@ -259,7 +259,7 @@ Buffer udløbstid Ændr enhed for afstand. Foreslået - OsmAnd Tracker-status + OsmAnd Tracker status Tilbage til OsmAnd Sidste opdatering fra Telegram: %1$s Sidste svar: %1$s diff --git a/OsmAnd/res/values-b+sr+Latn/strings.xml b/OsmAnd/res/values-b+sr+Latn/strings.xml index 81885a24348..55ae61e215a 100644 --- a/OsmAnd/res/values-b+sr+Latn/strings.xml +++ b/OsmAnd/res/values-b+sr+Latn/strings.xml @@ -4840,7 +4840,7 @@ Zatvori prozor Ovo će izbrisati folder \"%1$s\" i sve %2$s sadržane trase. Da li brišeš folder? - Sinhronizacija…%1$s + Sinhronizacija… %1$s Proveri osveženja Preuzmi izdanje iz Cloud-a Ne postoji diff --git a/OsmAnd/res/values-bg/strings.xml b/OsmAnd/res/values-bg/strings.xml index 3aa2e52a4d5..2770bab4135 100644 --- a/OsmAnd/res/values-bg/strings.xml +++ b/OsmAnd/res/values-bg/strings.xml @@ -3219,7 +3219,7 @@ Добавете всички отправни точки от трасето или изберете отделни категории. Премахнати са отправни точки от Внасяне на групи от избрани или отправни точки на GPX. - Синхронизиране…%1$s + Синхронизиране… %1$s Свързано Несвързано Добавя копие на изходната точка в качеството на местоназначение. diff --git a/OsmAnd/res/values-da/phrases.xml b/OsmAnd/res/values-da/phrases.xml index 1ef7b0e8b8f..d5b7b689a78 100644 --- a/OsmAnd/res/values-da/phrases.xml +++ b/OsmAnd/res/values-da/phrases.xml @@ -4113,4 +4113,10 @@ Rundtur: ja Farvede glasflasker Rundtur: nej + Automatisk brændstof dispenser; Brændstofs automat + CEMT + Klatregrad + Klatre bolt + Klatre bolte + Klatre kvalitet \ No newline at end of file diff --git a/OsmAnd/res/values-da/strings.xml b/OsmAnd/res/values-da/strings.xml index e0a03b46ffe..6981831689c 100644 --- a/OsmAnd/res/values-da/strings.xml +++ b/OsmAnd/res/values-da/strings.xml @@ -4709,7 +4709,7 @@ Alle ændringer foretaget på denne enhed er synkroniseret med OsmAnd Cloud. Der er ingen konflikter. Download cloud-version - Synkroniserer...%1$s + Synkroniserer… %1$s Fillisten kunne ikke hentes fra serveren. Import/eksport Ændret fil diff --git a/OsmAnd/res/values-ga/strings.xml b/OsmAnd/res/values-ga/strings.xml index 5fef960cd7b..a1ff12f9977 100644 --- a/OsmAnd/res/values-ga/strings.xml +++ b/OsmAnd/res/values-ga/strings.xml @@ -5462,4 +5462,6 @@ Ríomh méid Bealaí dreapadóireachta Taispeáin bealaí dreapadóireachta + Taispeánann sé am agus fad don chéad stad eile ar dtús. Múch chun sonraí an chinn scríbe a thaispeáint i gcónaí. + Taispeáin sonraí bealaigh don chéad stad eile \ No newline at end of file diff --git a/OsmAnd/res/values-in/strings.xml b/OsmAnd/res/values-in/strings.xml index 626afc38251..90b26140610 100644 --- a/OsmAnd/res/values-in/strings.xml +++ b/OsmAnd/res/values-in/strings.xml @@ -4981,7 +4981,7 @@ Ekspor ke berkas Diubah Pilih apa yang disinkron - Menyinkronkan…%1$s + Menyinkronkan… %1$s Perubahan %1$s Perubahan lokal akan diabaikan Impor/ekspor @@ -6060,4 +6060,6 @@ Tampilkan rute pendakian Menghitung… Hitung ukuran + Menampilkan waktu dan jarak untuk perhentian pertama terlebih dahulu. Matikan untuk selalu menampilkan detail tujuan. + Tampilkan detail rute until perhentian berikutnya \ No newline at end of file diff --git a/OsmAnd/res/values-sr/strings.xml b/OsmAnd/res/values-sr/strings.xml index 6a4d27bab59..652b01e641e 100644 --- a/OsmAnd/res/values-sr/strings.xml +++ b/OsmAnd/res/values-sr/strings.xml @@ -4624,7 +4624,7 @@ Наутичке миље/стопе Означите облик звучног записа. Врста звучне датотеке је 3ГПП (.3gp). Одредите шта ће се усклађивати - Усклади…%1$s + Усклади… %1$s Провери освежења Облак Нова датотека diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 6fa22407d2f..b4c693f4f0c 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1058,7 +1058,7 @@ You need to activate the sensor so OsmAnd can find it. Set up backup Choose what to sync - Sync…%1$s + Sync… %1$s Checking… Modified Unknown diff --git a/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java b/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java index 0940617f4a3..662a2d26f06 100644 --- a/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java +++ b/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java @@ -139,8 +139,9 @@ public class AppVersionUpgradeOnInit { public static final int VERSION_4_8_02 = 4802; // 4803 - 4.8-03 (Merge asset files versions) public static final int VERSION_4_8_03 = 4803; + public static final int VERSION_5_0_00 = 5000; - public static final int LAST_APP_VERSION = VERSION_4_8_03; + public static final int LAST_APP_VERSION = VERSION_5_0_00; private static final String VERSION_INSTALLED = "VERSION_INSTALLED"; @@ -271,7 +272,7 @@ void upgradeVersion(@NonNull SharedPreferences startPrefs, int lastVersion) { if (prevAppVersion < VERSION_4_8_02) { migrateTerrainModeDefaultPreferences(settings); } - if (prevAppVersion < VERSION_4_8_03) { + if (prevAppVersion < VERSION_5_0_00) { app.getAppInitializer().addOnFinishListener( init -> MergeAssetFilesVersionAlgorithm.execute(app) ); diff --git a/OsmAnd/src/net/osmand/plus/backup/BackupUtils.java b/OsmAnd/src/net/osmand/plus/backup/BackupUtils.java index 627196b1dec..83c82d0638b 100644 --- a/OsmAnd/src/net/osmand/plus/backup/BackupUtils.java +++ b/OsmAnd/src/net/osmand/plus/backup/BackupUtils.java @@ -91,24 +91,48 @@ public static Map getItemsMapForRestore(@Nullable Back @NonNull public static Map getRemoteFilesSettingsItems(@NonNull List items, - @NonNull List remoteFiles, - boolean infoFiles) { + @NonNull List remoteFiles, boolean infoFiles) { Map res = new HashMap<>(); - List files = new ArrayList<>(remoteFiles); + Map settingsItemMap = new HashMap<>(); + List subtypeFolders = new ArrayList<>(); + String DELIMETER = "___"; for (SettingsItem item : items) { - List processedFiles = new ArrayList<>(); - for (RemoteFile file : files) { - String type = file.getType(); - String name = file.getName(); - if (infoFiles && name.endsWith(BackupHelper.INFO_EXT)) { - name = name.substring(0, name.length() - BackupHelper.INFO_EXT.length()); + String itemFileName = getItemFileName(item); + settingsItemMap.put(item.getType().name() + DELIMETER + itemFileName, item); + // Commits FileSettingsItem introduced likely are related to TTS / Voice configuration (folders) + // https://github.com/osmandapp/OsmAnd/commit/ba750f9df87057da268b36e0d32b8c1996f4023a + // https://github.com/osmandapp/OsmAnd/commit/bf93162bd13ef7ab16622bb662c953e931c34a21 + if (item instanceof FileSettingsItem fileItem) { + String subtypeFolder = fileItem.getSubtype().getSubtypeFolder(); + if (subtypeFolder != null && fileItem.getFile().isDirectory()) { + subtypeFolders.add(fileItem); } - if (applyItem(item, type, name)) { - res.put(file, item); - processedFiles.add(file); + } + } + for (RemoteFile file : remoteFiles) { + String type = file.getType(); + String name = file.getName(); + if (infoFiles && name.endsWith(BackupHelper.INFO_EXT)) { + name = name.substring(0, name.length() - BackupHelper.INFO_EXT.length()); + } + SettingsItem item = settingsItemMap.get(type + DELIMETER + name); + if (item != null) { + res.put(file, item); + } else { + for (FileSettingsItem fileItem : subtypeFolders) { + String itemFileName = getItemFileName(fileItem); + boolean found = false; + if (!itemFileName.endsWith("/")) { + found = name.startsWith(itemFileName + "/"); + } else { + found = name.startsWith(itemFileName); + } + if (found) { + res.put(file, fileItem); + break; + } } } - files.removeAll(processedFiles); } return res; } @@ -121,25 +145,6 @@ public static CommonPreference getVersionHistoryTypePref(@NonNull Osman return app.getSettings().registerBooleanPreference(VERSION_HISTORY_PREFIX + exportType.name(), true).makeGlobal().makeShared(); } - public static boolean applyItem(@NonNull SettingsItem item, @NonNull String type, @NonNull String name) { - String itemFileName = getItemFileName(item); - if (item.getType().name().equals(type)) { - if (name.equals(itemFileName)) { - return true; - } else if (item instanceof FileSettingsItem fileItem) { - String subtypeFolder = fileItem.getSubtype().getSubtypeFolder(); - if (subtypeFolder != null && name.startsWith(subtypeFolder)) { - if (fileItem.getFile().isDirectory() && !itemFileName.endsWith("/")) { - return name.startsWith(itemFileName + "/"); - } else { - return name.startsWith(itemFileName); - } - } - } - } - return false; - } - @NonNull public static String getItemFileName(@NonNull SettingsItem item) { String fileName; diff --git a/OsmAnd/src/net/osmand/plus/backup/ImportBackupTask.java b/OsmAnd/src/net/osmand/plus/backup/ImportBackupTask.java index 2abfc82b112..b89d2db7391 100644 --- a/OsmAnd/src/net/osmand/plus/backup/ImportBackupTask.java +++ b/OsmAnd/src/net/osmand/plus/backup/ImportBackupTask.java @@ -227,7 +227,7 @@ public static int calculateMaxProgress(@NonNull OsmandApplication app) { BackupHelper backupHelper = app.getBackupHelper(); BackupInfo info = backupHelper.getBackup().getBackupInfo(); if (info != null) { - for (RemoteFile file : info.filesToDownload) { + for (RemoteFile file : info.filteredFilesToDownload) { maxProgress += backupHelper.calculateFileSize(file); } } diff --git a/OsmAnd/src/net/osmand/plus/configmap/tracks/appearance/DefaultAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/configmap/tracks/appearance/DefaultAppearanceFragment.java index e7dc7ae4630..5ce076d8819 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/tracks/appearance/DefaultAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/tracks/appearance/DefaultAppearanceFragment.java @@ -115,27 +115,27 @@ protected void setupCards(@NonNull View view) { FragmentActivity activity = requireActivity(); ViewGroup container = view.findViewById(R.id.cards_container); - MultiStateCard arrowsCard = new MultiStateCard(activity, controller.getArrowsCardController()); + MultiStateCard arrowsCard = new MultiStateCard(activity, controller.getArrowsCardController(), false); container.addView(arrowsCard.build()); inflate(R.layout.list_item_divider_with_padding_basic, container, true); - MultiStateCard iconsCard = new MultiStateCard(activity, controller.getIconsCardController()); + MultiStateCard iconsCard = new MultiStateCard(activity, controller.getIconsCardController(), false); container.addView(iconsCard.build()); inflate(R.layout.list_item_divider, container, true); - MultiStateCard colorsCard = new MultiStateCard(activity, controller.getColorCardController()); + MultiStateCard colorsCard = new MultiStateCard(activity, controller.getColorCardController(), false); container.addView(colorsCard.build()); inflate(R.layout.list_item_divider, container, true); - MultiStateCard widthCard = new MultiStateCard(activity, controller.getWidthCardController()); + MultiStateCard widthCard = new MultiStateCard(activity, controller.getWidthCardController(), false); container.addView(widthCard.build()); inflate(R.layout.list_item_divider, container, true); - MultiStateCard splitCard = new MultiStateCard(activity, controller.getSplitCardController()); + MultiStateCard splitCard = new MultiStateCard(activity, controller.getSplitCardController(), false); container.addView(splitCard.build()); setupOnNeedScrollListener(); diff --git a/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java b/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java index 42e534dcf78..322f26229e8 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java @@ -9,10 +9,14 @@ import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_SHORT_ALARM_ANNOUNCE; import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_SHORT_PNT_APPROACH; +import android.os.AsyncTask; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import net.osmand.Location; +import net.osmand.OnCompleteCallback; +import net.osmand.StateChangedListener; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; import net.osmand.binary.RouteDataObject; @@ -30,6 +34,7 @@ import net.osmand.plus.routing.data.AnnounceTimeDistances; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.settings.backend.preferences.OsmandPreference; import net.osmand.shared.settings.enums.MetricsConstants; import net.osmand.shared.settings.enums.SpeedConstants; import net.osmand.util.MapUtils; @@ -37,8 +42,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import gnu.trove.list.array.TIntArrayList; @@ -57,6 +63,7 @@ public class WaypointHelper { private static final int ANNOUNCE_POI_LIMIT = 3; OsmandApplication app; + OsmandSettings settings; // every time we modify this collection, we change the reference (copy on write list) public static final int TARGETS = 0; public static final int WAYPOINTS = 1; @@ -67,23 +74,39 @@ public class WaypointHelper { public static final int[] SEARCH_RADIUS_VALUES = {50, 100, 200, 500, 1000, 2000, 5000}; private static final double DISTANCE_IGNORE_DOUBLE_SPEEDCAMS = 150; private static final double DISTANCE_IGNORE_DOUBLE_RAILWAYS = 50; - + private static final int SAME_ALARM_INTERVAL = 30;//in seconds private List> locationPoints = new ArrayList<>(); private final ConcurrentHashMap locationPointsStates = new ConcurrentHashMap<>(); private final ConcurrentHashMap lastAnnouncedAlarms = new ConcurrentHashMap<>(); private final ConcurrentHashMap lastAnnouncedAlarmsTime = new ConcurrentHashMap<>(); - private static final int SAME_ALARM_INTERVAL = 30;//in seconds private TIntArrayList pointsProgress = new TIntArrayList(); + private boolean rejectPointsCalculation = false; private RouteCalculationResult route; private ApplicationMode appMode; + // Listeners cache that is needed to prevent individual listeners weak references lost + private final Map> registeredPrefListeners = new HashMap<>(); + public WaypointHelper(OsmandApplication application) { app = application; - appMode = app.getSettings().getApplicationMode(); + settings = app.getSettings(); + appMode = settings.getApplicationMode(); + registerPreferenceListeners(); } + private void registerPreferenceListeners() { + registerPreferenceListener(settings.ANNOUNCE_WPT, WAYPOINTS); + registerPreferenceListener(settings.ANNOUNCE_NEARBY_FAVORITES, FAVORITES); + registerPreferenceListener(settings.ANNOUNCE_NEARBY_POI, POI); + } + + private void registerPreferenceListener(@NonNull OsmandPreference preference, int type) { + StateChangedListener listener = aBoolean -> recalculatePointsAsync(type, null); + registeredPrefListeners.put(preference.getId(), listener); + preference.addListener(listener); + } public List getWaypoints(int type) { if (type == TARGETS) { @@ -213,7 +236,7 @@ public LocationPointWrapper getMostImportantLocationPoint(List switchWaypointType(type, enable), callback); + } + + public void switchWaypointType(int type, boolean enable) { + rejectPointsCalculation = true; //An item will be displayed in the Waypoint list if either "Show..." or "Announce..." is selected for it in the Navigation settings //Keep both "Show..." and "Announce..." Nav settings in sync when user changes what to display in the Waypoint list, as follows: if (type == ALARMS) { - app.getSettings().SHOW_TRAFFIC_WARNINGS.setModeValue(appMode, enable); - app.getSettings().SPEAK_TRAFFIC_WARNINGS.setModeValue(appMode, enable); - app.getSettings().SHOW_PEDESTRIAN.setModeValue(appMode, enable); - app.getSettings().SPEAK_PEDESTRIAN.setModeValue(appMode, enable); - app.getSettings().SHOW_TUNNELS.setModeValue(appMode, enable); - app.getSettings().SPEAK_TUNNELS.setModeValue(appMode, enable); + settings.SHOW_TRAFFIC_WARNINGS.setModeValue(appMode, enable); + settings.SPEAK_TRAFFIC_WARNINGS.setModeValue(appMode, enable); + settings.SHOW_PEDESTRIAN.setModeValue(appMode, enable); + settings.SPEAK_PEDESTRIAN.setModeValue(appMode, enable); + settings.SHOW_TUNNELS.setModeValue(appMode, enable); + settings.SPEAK_TUNNELS.setModeValue(appMode, enable); //But do not implicitly change speed_cam settings here because of legal restrictions in some countries, so Nav settings must prevail } else if (type == POI) { - app.getSettings().SHOW_NEARBY_POI.setModeValue(appMode, enable); - app.getSettings().ANNOUNCE_NEARBY_POI.setModeValue(appMode, enable); + settings.SHOW_NEARBY_POI.setModeValue(appMode, enable); + settings.ANNOUNCE_NEARBY_POI.setModeValue(appMode, enable); } else if (type == FAVORITES) { - app.getSettings().SHOW_NEARBY_FAVORITES.setModeValue(appMode, enable); - app.getSettings().ANNOUNCE_NEARBY_FAVORITES.setModeValue(appMode, enable); + settings.SHOW_NEARBY_FAVORITES.setModeValue(appMode, enable); + settings.ANNOUNCE_NEARBY_FAVORITES.setModeValue(appMode, enable); } else if (type == WAYPOINTS) { - app.getSettings().SHOW_WPT.set(enable); - app.getSettings().ANNOUNCE_WPT.set(enable); + settings.SHOW_WPT.set(enable); + settings.ANNOUNCE_WPT.set(enable); } + rejectPointsCalculation = false; recalculatePoints(route, type, locationPoints); } - public void recalculatePoints(int type) { - recalculatePoints(route, type, locationPoints); + public void recalculatePointsAsync(int type, @Nullable OnCompleteCallback callback) { + runAsync(() -> recalculatePoints(route, type, locationPoints), callback); } @@ -301,13 +330,13 @@ public boolean isTypeVisible(int waypointType) { public boolean isTypeEnabled(int type) { if (type == ALARMS) { - return app.getSettings().SHOW_ROUTING_ALARMS.get() && app.getSettings().SHOW_TRAFFIC_WARNINGS.getModeValue(appMode); + return settings.SHOW_ROUTING_ALARMS.get() && settings.SHOW_TRAFFIC_WARNINGS.getModeValue(appMode); } else if (type == POI) { - return app.getSettings().SHOW_NEARBY_POI.getModeValue(appMode); + return settings.SHOW_NEARBY_POI.getModeValue(appMode); } else if (type == FAVORITES) { - return app.getSettings().SHOW_NEARBY_FAVORITES.getModeValue(appMode); + return settings.SHOW_NEARBY_FAVORITES.getModeValue(appMode); } else if (type == WAYPOINTS) { - return app.getSettings().SHOW_WPT.get(); + return settings.SHOW_WPT.get(); } return true; } @@ -317,7 +346,7 @@ public AlarmInfo getSpeedLimitAlarm(@NonNull SpeedConstants constants, boolean w Location lastProjection = app.getRoutingHelper().getLastProjection(); if (route != null) { float maxSpeed = route.getCurrentMaxSpeed(appMode.getRouteTypeProfile()); - float delta = whenExceeded ? app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f : maxSpeed * -1; + float delta = whenExceeded ? settings.SPEED_LIMIT_EXCEED_KMH.get() / 3.6f : maxSpeed * -1; return createSpeedAlarm(constants, maxSpeed, lastProjection, delta); } return null; @@ -326,7 +355,7 @@ public AlarmInfo getSpeedLimitAlarm(@NonNull SpeedConstants constants, boolean w @Nullable public AlarmInfo calculateSpeedLimitAlarm(@NonNull RouteDataObject object, @NonNull Location location, @NonNull SpeedConstants constants, boolean whenExceeded) { float maxSpeed = object.getMaximumSpeed(object.bearingVsRouteDirection(location), appMode.getRouteTypeProfile()); - float delta = whenExceeded ? app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f : maxSpeed * -1; + float delta = whenExceeded ? settings.SPEED_LIMIT_EXCEED_KMH.get() / 3.6f : maxSpeed * -1; return createSpeedAlarm(constants, maxSpeed, location, delta); } @@ -334,7 +363,7 @@ public AlarmInfo calculateSpeedLimitAlarm(@NonNull RouteDataObject object, @NonN public AlarmInfo calculateMostImportantAlarm(RouteDataObject ro, Location loc, MetricsConstants mc, SpeedConstants sc, boolean showCameras) { float maxSpeed = ro.getMaximumSpeed(ro.bearingVsRouteDirection(loc), appMode.getRouteTypeProfile()); - float delta = app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f; + float delta = settings.SPEED_LIMIT_EXCEED_KMH.get() / 3.6f; AlarmInfo speedAlarm = createSpeedAlarm(sc, maxSpeed, loc, delta); if (speedAlarm != null) { getVoiceRouter().announceSpeedAlarm(speedAlarm.getIntValue(), loc.getSpeed()); @@ -570,50 +599,51 @@ public void setNewRoute(RouteCalculationResult route) { } protected void recalculatePoints(RouteCalculationResult route, int type, List> locationPoints) { + if (route == null || route.isEmpty() || rejectPointsCalculation) { + return; + } boolean all = type == -1; - appMode = app.getSettings().getApplicationMode(); - if (route != null && !route.isEmpty()) { - boolean showWaypoints = app.getSettings().SHOW_WPT.get(); // global - boolean announceWaypoints = app.getSettings().ANNOUNCE_WPT.get(); // global + appMode = settings.getApplicationMode(); + boolean showWaypoints = settings.SHOW_WPT.get(); // global + boolean announceWaypoints = settings.ANNOUNCE_WPT.get(); // global - if (route.getAppMode() != null) { - appMode = route.getAppMode(); - } - boolean showPOI = app.getSettings().SHOW_NEARBY_POI.getModeValue(appMode); - boolean showFavorites = app.getSettings().SHOW_NEARBY_FAVORITES.getModeValue(appMode); - boolean announceFavorites = app.getSettings().ANNOUNCE_NEARBY_FAVORITES.getModeValue(appMode); - boolean announcePOI = app.getSettings().ANNOUNCE_NEARBY_POI.getModeValue(appMode); - - if ((type == FAVORITES || all)) { - List array = clearAndGetArray(locationPoints, FAVORITES); - if (showFavorites) { - findLocationPoints(route, FAVORITES, array, app.getFavoritesHelper().getVisibleFavouritePoints(), - announceFavorites); - sortList(array); - } + if (route.getAppMode() != null) { + appMode = route.getAppMode(); + } + boolean showPOI = settings.SHOW_NEARBY_POI.getModeValue(appMode); + boolean showFavorites = settings.SHOW_NEARBY_FAVORITES.getModeValue(appMode); + boolean announceFavorites = settings.ANNOUNCE_NEARBY_FAVORITES.getModeValue(appMode); + boolean announcePOI = settings.ANNOUNCE_NEARBY_POI.getModeValue(appMode); + + if ((type == FAVORITES || all)) { + List array = clearAndGetArray(locationPoints, FAVORITES); + if (showFavorites) { + findLocationPoints(route, FAVORITES, array, app.getFavoritesHelper().getVisibleFavouritePoints(), + announceFavorites); + sortList(array); } - if ((type == ALARMS || all)) { - List array = clearAndGetArray(locationPoints, ALARMS); - if (route.getAppMode() != null) { - calculateAlarms(route, array, appMode); - sortList(array); - } + } + if ((type == ALARMS || all)) { + List array = clearAndGetArray(locationPoints, ALARMS); + if (route.getAppMode() != null) { + calculateAlarms(route, array, appMode); + sortList(array); } - if ((type == WAYPOINTS || all)) { - List array = clearAndGetArray(locationPoints, WAYPOINTS); - if (showWaypoints) { - findLocationPoints(route, WAYPOINTS, array, app.getAppCustomization().getWaypoints(), - announceWaypoints); - findLocationPoints(route, WAYPOINTS, array, route.getLocationPoints(), announceWaypoints); - sortList(array); - } + } + if ((type == WAYPOINTS || all)) { + List array = clearAndGetArray(locationPoints, WAYPOINTS); + if (showWaypoints) { + findLocationPoints(route, WAYPOINTS, array, app.getAppCustomization().getWaypoints(), + announceWaypoints); + findLocationPoints(route, WAYPOINTS, array, route.getLocationPoints(), announceWaypoints); + sortList(array); } - if ((type == POI || all)) { - List array = clearAndGetArray(locationPoints, POI); - if (showPOI) { - calculatePoi(route, array, announcePOI); - sortList(array); - } + } + if ((type == POI || all)) { + List array = clearAndGetArray(locationPoints, POI); + if (showPOI) { + calculatePoi(route, array, announcePOI); + sortList(array); } } } @@ -657,16 +687,13 @@ protected synchronized void setLocationPoints(List> l protected void sortList(List list) { - Collections.sort(list, new Comparator() { - @Override - public int compare(LocationPointWrapper olhs, LocationPointWrapper orhs) { - int lhs = olhs.routeIndex; - int rhs = orhs.routeIndex; - if (lhs == rhs) { - return Float.compare(olhs.deviationDistance, orhs.deviationDistance); - } - return lhs < rhs ? -1 : 1; + Collections.sort(list, (olhs, orhs) -> { + int lhs = olhs.routeIndex; + int rhs = orhs.routeIndex; + if (lhs == rhs) { + return Float.compare(olhs.deviationDistance, orhs.deviationDistance); } + return lhs < rhs ? -1 : 1; }); } @@ -695,7 +722,6 @@ protected void calculatePoi(RouteCalculationResult route, List array, ApplicationMode mode) { - OsmandSettings settings = app.getSettings(); if (!settings.SHOW_ROUTING_ALARMS.getModeValue(mode)) { return; } @@ -774,4 +800,21 @@ public void setSearchDeviationRadius(int type, int radius) { this.searchDeviationRadius = radius; } } + + private void runAsync(@NonNull Runnable runnable, @Nullable OnCompleteCallback callback) { + new AsyncTask() { + @Override + protected Void doInBackground(Void... voids) { + runnable.run(); + return null; + } + + @Override + protected void onPostExecute(Void unused) { + if (callback != null) { + callback.onComplete(); + } + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java index 6179c7d8e72..dbd7f110ad8 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java @@ -306,7 +306,7 @@ public boolean hasTimestamps() { } public boolean isAddNewSegmentAllowed() { - return beforeSegments.size() > 0 && beforeSegments.get(beforeSegments.size() - 1).getPoints().size() >= 2; + return !beforeSegments.isEmpty() && beforeSegments.get(beforeSegments.size() - 1).getPoints().size() >= 2; } public void clearSnappedToRoadPoints() { @@ -314,17 +314,11 @@ public void clearSnappedToRoadPoints() { } List getBeforeTrkSegmentLine() { - if (beforeSegmentsForSnap != null) { - return beforeSegmentsForSnap; - } - return beforeSegments; + return beforeSegmentsForSnap != null ? beforeSegmentsForSnap : beforeSegments; } List getAfterTrkSegmentLine() { - if (afterSegmentsForSnap != null) { - return afterSegmentsForSnap; - } - return afterSegments; + return afterSegmentsForSnap != null ? afterSegmentsForSnap : afterSegments; } public List getBeforeSegments() { @@ -750,7 +744,7 @@ private ApplicationMode getPointAppMode(int pointPosition) { } public void scheduleRouteCalculateIfNotEmpty() { - if (application == null || (before.getPoints().size() == 0 && after.getPoints().size() == 0)) { + if (application == null || (before.getPoints().isEmpty() && after.getPoints().isEmpty())) { return; } RoutingHelper routingHelper = application.getRoutingHelper(); @@ -791,7 +785,8 @@ private List> getOrderedRoadSegmentDataKeys() { return keys; } - private void recreateSegments(List segments, List segmentsForSnap, List points, boolean calculateIfNeeded) { + private void recreateSegments(List segments, List segmentsForSnap, + List points, boolean calculateIfNeeded) { List roadSegmentIndexes = new ArrayList<>(); TrkSegment s = new TrkSegment(); segments.add(s); @@ -829,21 +824,27 @@ private void recreateSegments(List segments, List segmen if (!segments.isEmpty()) { for (TrkSegment segment : segments) { TrkSegment segmentForSnap = new TrkSegment(); - for (int i = 0; i < segment.getPoints().size() - 1; i++) { - Pair pair = new Pair<>(segment.getPoints().get(i), segment.getPoints().get(i + 1)); - RoadSegmentData data = this.roadSegmentData.get(pair); + List segmentPoints = segment.getPoints(); + List segmentForSnapPoints = segmentForSnap.getPoints(); + for (int i = 0; i < segmentPoints.size() - 1; i++) { + WptPt point = segmentPoints.get(i); + WptPt nextPoint = segmentPoints.get(i + 1); + RoadSegmentData data = this.roadSegmentData.get(new Pair<>(point, nextPoint)); List pts = data != null ? data.getPoints() : null; if (pts != null) { - segmentForSnap.getPoints().addAll(pts); + segmentForSnapPoints.addAll(pts); } else { if (calculateIfNeeded && roadSegmentIndexes.contains(segmentsForSnap.size())) { scheduleRouteCalculateIfNotEmpty(); } - segmentForSnap.getPoints().addAll(Arrays.asList(pair.first, pair.second)); + if (segmentForSnapPoints.isEmpty()) { + segmentForSnapPoints.add(point); + } + segmentForSnapPoints.add(nextPoint); } } - if (segmentForSnap.getPoints().isEmpty()) { - segmentForSnap.getPoints().addAll(segment.getPoints()); + if (segmentForSnapPoints.isEmpty()) { + segmentForSnapPoints.addAll(segmentPoints); } segmentsForSnap.add(segmentForSnap); } @@ -876,18 +877,18 @@ void addPoints() { addPoints(segment.getPoints()); } } else { - for (int si = 0; si < segments.size(); si++) { - TrkSegment segment = segments.get(si); + for (int i = 0; i < segments.size(); i++) { + TrkSegment segment = segments.get(i); if (segment.hasRoute()) { - List routePoints = collectRoutePointsFromSegment(segment, si); - if (!routePoints.isEmpty() && si < segments.size() - 1) { + List routePoints = collectRoutePointsFromSegment(segment, i); + if (!routePoints.isEmpty() && i < segments.size() - 1) { routePoints.get(routePoints.size() - 1).setGap(); } addPoints(routePoints); } else { List points = segment.getPoints(); addPoints(points); - if (!points.isEmpty() && si < segments.size() - 1) { + if (!points.isEmpty() && i < segments.size() - 1) { points.get(points.size() - 1).setGap(); } } @@ -1039,12 +1040,7 @@ private boolean needDuplicatePoint(List gpxPoints, int index) { } private void updateSegmentsForSnap(boolean both) { - recreateSegments(beforeSegments = new ArrayList<>(), - beforeSegmentsForSnap = new ArrayList<>(), before.getPoints(), true); - if (both) { - recreateSegments(afterSegments = new ArrayList<>(), - afterSegmentsForSnap = new ArrayList<>(), after.getPoints(), true); - } + updateSegmentsForSnap(both, true); } private void updateSegmentsForSnap(boolean both, boolean calculateIfNeeded) { diff --git a/OsmAnd/src/net/osmand/plus/resources/CheckAssetsTask.java b/OsmAnd/src/net/osmand/plus/resources/CheckAssetsTask.java index 8172462b818..7663a20b740 100644 --- a/OsmAnd/src/net/osmand/plus/resources/CheckAssetsTask.java +++ b/OsmAnd/src/net/osmand/plus/resources/CheckAssetsTask.java @@ -107,23 +107,25 @@ private List checkAssets() { public void copyMissingJSAssets() { try { - AssetsCollection assetsCollection = app.getResourceManager().getAssets(); File appPath = app.getAppPath(null); if (appPath.canWrite()) { - for (AssetEntry asset : assetsCollection.getEntries()) { + AssetManager manager = app.getAssets(); + AssetsCollection assets = app.getResourceManager().getAssets(); + + for (AssetEntry asset : assets.getEntries()) { File jsFile = new File(appPath, asset.destination); - if (asset.destination.contains(VOICE_PROVIDER_SUFFIX) && asset.destination - .endsWith(TTSVOICE_INDEX_EXT_JS)) { - File oggFile = new File(appPath, asset.destination.replace( - VOICE_PROVIDER_SUFFIX, "")); + if (asset.destination.contains(VOICE_PROVIDER_SUFFIX) + && asset.destination.endsWith(TTSVOICE_INDEX_EXT_JS)) { + String name = asset.destination.replace(VOICE_PROVIDER_SUFFIX, ""); + File oggFile = new File(appPath, name); if (oggFile.getParentFile().exists() && !oggFile.exists()) { - ResourceManager.copyAssets(app.getAssets(), asset.source, oggFile); + ResourceManager.copyAssets(manager, asset.source, oggFile, asset.getVersionTime()); } } else if (asset.destination.startsWith(MODEL_3D_DIR) && !jsFile.exists()) { - ResourceManager.copyAssets(app.getAssets(), asset.source, jsFile); + ResourceManager.copyAssets(manager, asset.source, jsFile, asset.getVersionTime()); } if (jsFile.getParentFile().exists() && !jsFile.exists()) { - ResourceManager.copyAssets(app.getAssets(), asset.source, jsFile); + ResourceManager.copyAssets(manager, asset.source, jsFile, asset.getVersionTime()); } } } diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index 14e58d69f7d..3030737acb0 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -1284,13 +1284,7 @@ private AssetsCollection readBundledAssets() throws IOException { } public static boolean copyAssets(@NonNull AssetManager manager, @NonNull String name, - @NonNull File file, @Nullable Long lastModifiedTime) throws IOException { - copyAssets(manager, name, file); - return lastModifiedTime != null && file.setLastModified(lastModifiedTime); - } - - public static void copyAssets(@NonNull AssetManager manager, @NonNull String name, - @NonNull File file) throws IOException { + @NonNull File file, @Nullable Long modifiedTime) throws IOException { if (file.exists()) { Algorithms.removeAllFiles(file); } @@ -1300,5 +1294,7 @@ public static void copyAssets(@NonNull AssetManager manager, @NonNull String nam Algorithms.streamCopy(is, out); Algorithms.closeStream(out); Algorithms.closeStream(is); + + return modifiedTime != null && file.setLastModified(modifiedTime); } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index 6b374036c96..bab37856838 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -1260,8 +1260,7 @@ private void createWaypointItem(MapActivity mapActivity, LinearLayout optionsCon View container = createToolbarSubOptionView(true, title, R.drawable.ic_action_remove_dark, true, v -> { OsmandApplication app = getApp(); if (app != null) { - app.getWaypointHelper().enableWaypointType(waypointType, false); - updateOptionsButtons(); + app.getWaypointHelper().switchWaypointTypeAsync(waypointType, false, this::updateOptionsButtons); } }); if (container != null) { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java index 254370d8768..2617417522b 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java @@ -427,23 +427,20 @@ private BaseBottomSheetItem createShowAlongTheRouteItem(LocalRoutingParameter op .setIcon(getContentIcon((optionsItem.getActiveIconId()))) .setTitle(getString(R.string.show_along_the_route)) .setLayoutId(R.layout.bottom_sheet_item_simple_56dp) - .setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - routingOptionsHelper.addNewRouteMenuParameter(applicationMode, optionsItem); - FragmentManager fm = getFragmentManager(); - if (fm == null) { - return; - } - Bundle args = new Bundle(); - ShowAlongTheRouteBottomSheet fragment = new ShowAlongTheRouteBottomSheet(); - fragment.setUsedOnMap(true); - fragment.setArguments(args); - fragment.setTargetFragment(RouteOptionsBottomSheet.this, ShowAlongTheRouteBottomSheet.REQUEST_CODE); - fragment.show(fm, ShowAlongTheRouteBottomSheet.TAG); - updateMenu(); - } - }).create(); + .setOnClickListener(view -> { + routingOptionsHelper.addNewRouteMenuParameter(applicationMode, optionsItem); + FragmentManager fm = getFragmentManager(); + if (fm == null) { + return; + } + Bundle args = new Bundle(); + ShowAlongTheRouteBottomSheet fragment = new ShowAlongTheRouteBottomSheet(); + fragment.setUsedOnMap(true); + fragment.setArguments(args); + fragment.setTargetFragment(RouteOptionsBottomSheet.this, ShowAlongTheRouteBottomSheet.REQUEST_CODE); + fragment.show(fm, ShowAlongTheRouteBottomSheet.TAG); + updateMenu(); + }).create(); } private BaseBottomSheetItem createRouteSimulationItem(LocalRoutingParameter optionsItem) { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java index e15eecd9cef..62136acc6bf 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java @@ -86,12 +86,7 @@ public void createMenuItems(Bundle savedInstanceState) { Drawable icBack = getContentIcon(AndroidUtils.getNavigationIconResId(ctx)); toolbar.setNavigationIcon(icBack); toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up); - toolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - } - }); + toolbar.setNavigationOnClickListener(v -> dismiss()); SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() .setCustomView(titleView) @@ -149,7 +144,7 @@ private ContentItem getAdapterContentItems() { ContentItem radiusItem = new RadiusItem(i); headerItem.subItems.add(radiusItem); } - if (tp != null && tp.size() > 0) { + if (tp != null && !tp.isEmpty()) { for (int j = 0; j < tp.size(); j++) { LocationPointWrapper pointWrapper = tp.get(j); if (!waypointHelper.isPointPassed(pointWrapper)) { @@ -252,27 +247,21 @@ public View getChildView(int groupPosition, int childPosition, convertView = themedInflater.inflate(R.layout.along_the_route_point_item, parent, false); WaypointDialogHelper.updatePointInfoView(app, mapActivity, convertView, item.point, true, nightMode, true, false); - convertView.findViewById(R.id.waypoint_container).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Fragment fragment = getTargetFragment(); - if (fragment != null) { - fragment.onActivityResult(getTargetRequestCode(), SHOW_CONTENT_ITEM_REQUEST_CODE, null); - } - dismiss(); - WaypointDialogHelper.showOnMap(app, mapActivity, item.point.getPoint(), false); + convertView.findViewById(R.id.waypoint_container).setOnClickListener(v -> { + Fragment fragment = getTargetFragment(); + if (fragment != null) { + fragment.onActivityResult(getTargetRequestCode(), SHOW_CONTENT_ITEM_REQUEST_CODE, null); } + dismiss(); + WaypointDialogHelper.showOnMap(app, mapActivity, item.point.getPoint(), false); }); ImageButton remove = convertView.findViewById(R.id.info_close); remove.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_remove_dark)); - remove.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - app.getWaypointHelper().removeVisibleLocationPoint(item.point); - group.subItems.remove(item); - adapter.notifyDataSetChanged(); - } + remove.setOnClickListener(v -> { + app.getWaypointHelper().removeVisibleLocationPoint(item.point); + group.subItems.remove(item); + adapter.notifyDataSetChanged(); }); } @@ -480,70 +469,21 @@ protected void selectDifferentRadius(int type) { }); } - private void enableType(int type, - boolean enable) { - new EnableWaypointsTypeTask(this, type, enable).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - - private void recalculatePoints(int type) { - new RecalculatePointsTask(this, type).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - - private static class RecalculatePointsTask extends AsyncTask { - - private final OsmandApplication app; - private final WeakReference fragmentRef; - private final int type; - - RecalculatePointsTask(ShowAlongTheRouteBottomSheet fragment, int type) { - this.app = fragment.getMyApplication(); - this.fragmentRef = new WeakReference<>(fragment); - this.type = type; - } - - @Override - protected Void doInBackground(Void... params) { - app.getWaypointHelper().recalculatePoints(type); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - ShowAlongTheRouteBottomSheet fragment = fragmentRef.get(); - if (fragment != null) { - fragment.updateAdapter(); + private void enableType(int type, boolean enable) { + waypointHelper.switchWaypointTypeAsync(type, enable, () -> { + if (isAdded()) { + updateAdapter(); + updateMenu(); } - } + }); } - private static class EnableWaypointsTypeTask extends AsyncTask { - - private final OsmandApplication app; - private final WeakReference fragmentRef; - private final int type; - private final boolean enable; - - EnableWaypointsTypeTask(ShowAlongTheRouteBottomSheet fragment, int type, boolean enable) { - this.app = fragment.getMyApplication(); - this.fragmentRef = new WeakReference<>(fragment); - this.type = type; - this.enable = enable; - } - - @Override - protected Void doInBackground(Void... params) { - app.getWaypointHelper().enableWaypointType(type, enable); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - ShowAlongTheRouteBottomSheet fragment = fragmentRef.get(); - if (fragment != null && fragment.isAdded()) { - fragment.updateAdapter(); - fragment.updateMenu(); + private void recalculatePoints(int type) { + waypointHelper.recalculatePointsAsync(type, () -> { + if (isAdded()) { + updateAdapter(); } - } + }); } private static class ContentItem { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/exporttype/LocalResourcesExportType.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/exporttype/LocalResourcesExportType.java index 905cc52c308..a2c87df9436 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/exporttype/LocalResourcesExportType.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/exporttype/LocalResourcesExportType.java @@ -64,8 +64,9 @@ protected boolean shouldSkipLocalItem(@NonNull OsmandApplication app, @NonNull L File file = localItem.getFile(); AssetsCollection assets = resourceManager.getAssets(); if (assets.isFileDerivedFromAssets(file)) { + long lastModified = file.lastModified(); Long version = assets.getVersionTime(file); - return version == null || version == file.lastModified(); + return version == null || version == lastModified; } } catch (IOException e) { LOG.error(e);