diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java index 4a84a9c6df..005f3ba88c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java @@ -116,9 +116,9 @@ public class RoutingConfiguration { return impassableRoadLocations; } - public boolean addImpassableRoad(RouteDataObject route) { - if (!impassableRoadLocations.contains(route.id)) { - impassableRoadLocations.add(route.id); + public boolean addImpassableRoad(long routeId) { + if (!impassableRoadLocations.contains(routeId)) { + impassableRoadLocations.add(routeId); return true; } return false; diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index bf9720c037..1f89aca20b 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -629,6 +629,7 @@ public class AppInitializer implements IProgress { if (!customConfigs.isEmpty()) { app.getCustomRoutingConfigs().putAll(customConfigs); } + app.avoidSpecificRoads.initRouteObjects(false); callback.onRoutingFilesLoaded(); } @@ -739,8 +740,7 @@ public class AppInitializer implements IProgress { notifyEvent(InitEvents.RESTORE_BACKUPS); app.mapMarkersHelper.syncAllGroupsAsync(); app.searchUICore.initSearchUICore(); - app.avoidSpecificRoads.initRouteObjects(false); - + checkLiveUpdatesAlerts(); } catch (RuntimeException e) { diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 89bfd57513..b5ca671ace 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -2798,9 +2798,136 @@ public class OsmandSettings { } private class ImpassableRoadsStorage extends MapPointsStorage { + + protected String roadsIdsKey; + public ImpassableRoadsStorage() { pointsKey = IMPASSABLE_ROAD_POINTS; descriptionsKey = IMPASSABLE_ROADS_DESCRIPTIONS; + roadsIdsKey = IMPASSABLE_ROADS_IDS; + } + + public List getImpassableRoadsInfo() { + List points = mImpassableRoadsStorage.getPoints(); + List descriptions = mImpassableRoadsStorage.getPointDescriptions(points.size()); + List roadIds = getRoadIds(points.size()); + + List avoidRoadsInfo = new ArrayList<>(); + + for (int i = 0; i < points.size(); i++) { + LatLon latLon = points.get(i); + PointDescription description = PointDescription.deserializeFromString(descriptions.get(i), null); + + AvoidRoadInfo avoidRoadInfo = new AvoidRoadInfo(); + avoidRoadInfo.id = roadIds.get(i); + avoidRoadInfo.lat = latLon.getLatitude(); + avoidRoadInfo.lon = latLon.getLongitude(); + avoidRoadInfo.name = description.getName(); + avoidRoadsInfo.add(avoidRoadInfo); + } + + return avoidRoadsInfo; + } + + public boolean addImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) { + List points = getPoints(); + List descriptions = getPointDescriptions(points.size()); + List roadIds = getRoadIds(points.size()); + + points.add(0, new LatLon(avoidRoadInfo.lat, avoidRoadInfo.lon)); + descriptions.add(0, PointDescription.serializeToString(new PointDescription("", avoidRoadInfo.name))); + roadIds.add(0, avoidRoadInfo.id); + + return savePoints(points, descriptions) && saveRoadIds(roadIds); + } + + public boolean updateImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) { + List points = getPoints(); + List roadIds = getRoadIds(points.size()); + List descriptions = getPointDescriptions(points.size()); + + int index = points.indexOf(new LatLon(avoidRoadInfo.lat, avoidRoadInfo.lon)); + if (index != -1) { + roadIds.set(index, avoidRoadInfo.id); + descriptions.set(index, PointDescription.serializeToString(new PointDescription("", avoidRoadInfo.name))); + return savePoints(points, descriptions) && saveRoadIds(roadIds); + } + return false; + } + + public List getRoadIds(int size) { + List list = new ArrayList<>(); + String roadIds = settingsAPI.getString(globalPreferences, roadsIdsKey, ""); + if (roadIds.trim().length() > 0) { + StringTokenizer tok = new StringTokenizer(roadIds, ","); + while (tok.hasMoreTokens() && list.size() <= size) { + String token = tok.nextToken(); + list.add(Long.parseLong(token)); + } + } + while (list.size() < size) { + list.add(0L); + } + return list; + } + + @Override + public boolean deletePoint(int index) { + List points = getPoints(); + List roadIds = getRoadIds(points.size()); + List descriptions = getPointDescriptions(points.size()); + + if (index < points.size()) { + points.remove(index); + roadIds.remove(index); + descriptions.remove(index); + return savePoints(points, descriptions) && saveRoadIds(roadIds); + } + return false; + } + + @Override + public boolean deletePoint(LatLon latLon) { + List points = getPoints(); + List descriptions = getPointDescriptions(points.size()); + List roadIds = getRoadIds(points.size()); + int index = points.indexOf(latLon); + if (index != -1) { + points.remove(index); + roadIds.remove(index); + descriptions.remove(index); + return savePoints(points, descriptions) && saveRoadIds(roadIds); + } + return false; + } + + @Override + public boolean movePoint(LatLon latLonEx, LatLon latLonNew) { + List points = getPoints(); + List descriptions = getPointDescriptions(points.size()); + List roadIds = getRoadIds(points.size()); + + int i = points.indexOf(latLonEx); + if (i != -1) { + points.set(i, latLonNew); + return savePoints(points, descriptions) && saveRoadIds(roadIds); + } else { + return false; + } + } + + public boolean saveRoadIds(List roadIds) { + StringBuilder stringBuilder = new StringBuilder(); + Iterator iterator = roadIds.iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + return settingsAPI.edit(globalPreferences) + .putString(roadsIdsKey, stringBuilder.toString()) + .commit(); } } @@ -2994,10 +3121,15 @@ public class OsmandSettings { public List getImpassableRoadPoints() { return mImpassableRoadsStorage.getImpassableRoadsInfo(); } + public boolean addImpassableRoad(AvoidRoadInfo avoidRoadInfo) { return mImpassableRoadsStorage.addImpassableRoadInfo(avoidRoadInfo); } + public boolean updateImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) { + return mImpassableRoadsStorage.updateImpassableRoadInfo(avoidRoadInfo); + } + public boolean removeImpassableRoad(int index) { return mImpassableRoadsStorage.deletePoint(index); } diff --git a/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java b/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java index 00b811ad25..628e354e7c 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java +++ b/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java @@ -67,17 +67,21 @@ public class AvoidSpecificRoads { for (Map.Entry entry : impassableRoads.entrySet()) { if (force || entry.getValue().id == 0) { addImpassableRoad(null, entry.getKey(), false, true); + } else { + for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { + builder.addImpassableRoad(entry.getValue().id); + } } } } - private ArrayAdapter createAdapter(MapActivity mapActivity, boolean nightMode) { - final ArrayList points = new ArrayList<>(impassableRoads.keySet()); + private ArrayAdapter createAdapter(MapActivity mapActivity, boolean nightMode) { + final ArrayList points = new ArrayList<>(impassableRoads.values()); final LatLon mapLocation = mapActivity.getMapLocation(); final LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode); Context themedContext = UiUtilities.getThemedContext(mapActivity, nightMode); - return new ArrayAdapter(themedContext, R.layout.waypoint_reached, R.id.title, points) { + return new ArrayAdapter(themedContext, R.layout.waypoint_reached, R.id.title, points) { @NonNull @Override public View getView(final int position, View convertView, @NonNull ViewGroup parent) { @@ -85,12 +89,15 @@ public class AvoidSpecificRoads { if (v == null || v.findViewById(R.id.info_close) == null) { v = inflater.inflate(R.layout.waypoint_reached, parent, false); } - final LatLon item = getItem(position); + final AvoidRoadInfo item = getItem(position); v.findViewById(R.id.all_points).setVisibility(View.GONE); ((ImageView) v.findViewById(R.id.waypoint_icon)) .setImageDrawable(getIcon(R.drawable.ic_action_road_works_dark)); - ((TextView) v.findViewById(R.id.waypoint_dist)).setText(getDist(mapLocation, item)); - ((TextView) v.findViewById(R.id.waypoint_text)).setText(getText(item)); + + LatLon latLon = item != null ? new LatLon(item.lat, item.lon) : null; + String name = item != null ? item.name : app.getString(R.string.shared_string_road); + ((TextView) v.findViewById(R.id.waypoint_dist)).setText(getDist(mapLocation, latLon)); + ((TextView) v.findViewById(R.id.waypoint_text)).setText(name); ImageButton remove = (ImageButton) v.findViewById(R.id.info_close); remove.setVisibility(View.VISIBLE); remove.setImageDrawable(getIcon(R.drawable.ic_action_remove_dark)); @@ -153,15 +160,15 @@ public class AvoidSpecificRoads { public void removeImpassableRoad(LatLon latLon) { app.getSettings().removeImpassableRoad(latLon); - RouteDataObject obj = impassableRoads.remove(latLon); + AvoidRoadInfo obj = impassableRoads.remove(latLon); if (obj != null) { for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { - builder.removeImpassableRoad(obj); + builder.removeImpassableRoad(obj.id); } } } - public void removeImpassableRoad(RouteDataObject obj) { + public void removeImpassableRoad(AvoidRoadInfo obj) { removeImpassableRoad(getLocation(obj)); } @@ -174,13 +181,13 @@ public class AvoidSpecificRoads { if (impassableRoads.isEmpty()) { bld.setMessage(R.string.avoid_roads_msg); } else { - final ArrayAdapter listAdapter = createAdapter(mapActivity, nightMode); + final ArrayAdapter listAdapter = createAdapter(mapActivity, nightMode); bld.setAdapter(listAdapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - LatLon point = listAdapter.getItem(which); + AvoidRoadInfo point = listAdapter.getItem(which); if (point != null) { - showOnMap(mapActivity, point.getLatitude(), point.getLongitude(), getText(point)); + showOnMap(mapActivity, point.lat, point.lon, point.name); } dialog.dismiss(); } @@ -228,9 +235,12 @@ public class AvoidSpecificRoads { LatLon newLoc = new LatLon(MapUtils.get31LatitudeY((int) point.y), MapUtils.get31LongitudeX((int) point.x)); ll.setLatitude(newLoc.getLatitude()); ll.setLongitude(newLoc.getLongitude()); - addImpassableRoadInternal(roads.get(searchResult.getRoadIndex()).getObject(), ll, showDialog, mapActivity, newLoc); + + RouteDataObject object = roads.get(searchResult.getRoadIndex()).getObject(); + AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(object, newLoc.getLatitude(), newLoc.getLongitude()); + addImpassableRoadInternal(avoidRoadInfo, showDialog, mapActivity, newLoc); if (!skipWritingSettings) { - app.getSettings().addImpassableRoad(newLoc.getLatitude(), newLoc.getLongitude()); + app.getSettings().addImpassableRoad(avoidRoadInfo); } return; } @@ -244,7 +254,8 @@ public class AvoidSpecificRoads { Toast.makeText(mapActivity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show(); } } else { - addImpassableRoadInternal(object, ll, showDialog, mapActivity, loc); + AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(object, ll.getLatitude(), ll.getLongitude()); + addImpassableRoadInternal(avoidRoadInfo, showDialog, mapActivity, loc); } return true; } @@ -256,12 +267,13 @@ public class AvoidSpecificRoads { }); if (!skipWritingSettings) { - app.getSettings().addImpassableRoad(loc.getLatitude(), loc.getLongitude()); + AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(null, loc.getLatitude(), loc.getLongitude()); + app.getSettings().addImpassableRoad(avoidRoadInfo); } } public void replaceImpassableRoad(final MapActivity activity, - final RouteDataObject currentObject, + final AvoidRoadInfo currentObject, final LatLon newLoc, final boolean showDialog, final AvoidSpecificRoadsCallback callback) { @@ -284,12 +296,13 @@ public class AvoidSpecificRoads { app.getSettings().moveImpassableRoad(oldLoc, newLoc); impassableRoads.remove(oldLoc); for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { - builder.removeImpassableRoad(currentObject); + builder.removeImpassableRoad(currentObject.id); } - addImpassableRoadInternal(object, ll, showDialog, activity, newLoc); + AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(object, newLoc.getLatitude(), newLoc.getLongitude()); + addImpassableRoadInternal(avoidRoadInfo, showDialog, activity, newLoc); if (callback != null) { - callback.onAddImpassableRoad(true, object); + callback.onAddImpassableRoad(true, avoidRoadInfo); } } return true; @@ -302,19 +315,19 @@ public class AvoidSpecificRoads { }); } - private void addImpassableRoadInternal(@NonNull RouteDataObject object, - @NonNull Location ll, + private void addImpassableRoadInternal(@NonNull AvoidRoadInfo avoidRoadInfo, boolean showDialog, @Nullable MapActivity activity, @NonNull LatLon loc) { boolean roadAdded = false; for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { - roadAdded |= builder.addImpassableRoad(object, ll); + roadAdded |= builder.addImpassableRoad(avoidRoadInfo.id); } if (roadAdded) { - impassableRoads.put(loc, object); + app.getSettings().updateImpassableRoadInfo(avoidRoadInfo); + impassableRoads.put(loc, avoidRoadInfo); } else { - LatLon location = getLocation(object); + LatLon location = getLocation(avoidRoadInfo); if (location != null) { app.getSettings().removeImpassableRoad(location); } @@ -355,8 +368,11 @@ public class AvoidSpecificRoads { boolean isCancelled(); } - private AvoidRoadInfo createAvoidRoadInfo(@Nullable RouteDataObject object, double lat, double lon) { - AvoidRoadInfo avoidRoadInfo = new AvoidRoadInfo(); + private AvoidRoadInfo getAvoidRoadInfoForDataObject(@Nullable RouteDataObject object, double lat, double lon) { + AvoidRoadInfo avoidRoadInfo = impassableRoads.get(new LatLon(lat, lon)); + if (avoidRoadInfo == null) { + avoidRoadInfo = new AvoidRoadInfo(); + } avoidRoadInfo.id = object != null ? object.id : 0; avoidRoadInfo.lat = lat; avoidRoadInfo.lon = lon;