avoid roads export import

This commit is contained in:
veliymolfar 2020-02-20 18:34:27 +02:00
parent 89df698065
commit a0ce3b60fe
8 changed files with 258 additions and 4 deletions

View file

@ -14,6 +14,7 @@ import com.google.gson.reflect.TypeToken;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager;
import net.osmand.osm.MapPoiTypes;
@ -21,6 +22,8 @@ import net.osmand.osm.PoiCategory;
import net.osmand.plus.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.ApplicationMode.ApplicationModeBuilder;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.quickaction.QuickActionRegistry;
@ -147,6 +150,7 @@ public class SettingsHelper {
QUICK_ACTION,
POI_UI_FILTERS,
MAP_SOURCES,
AVOID_ROADS
}
public abstract static class SettingsItem {
@ -1435,6 +1439,191 @@ public class SettingsHelper {
}
}
public static class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidRoadInfo> {
private OsmandApplication app;
private OsmandSettings settings;
private AvoidSpecificRoads specificRoads;
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull List<AvoidRoadInfo> items) {
super(SettingsItemType.AVOID_ROADS, items);
this.app = app;
settings = app.getSettings();
specificRoads = app.getAvoidSpecificRoads();
existingItems = new ArrayList<>(specificRoads.getImpassableRoads().values());
}
AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
super(SettingsItemType.AVOID_ROADS, json);
this.app = app;
settings = app.getSettings();
specificRoads = app.getAvoidSpecificRoads();
existingItems = new ArrayList<>(specificRoads.getImpassableRoads().values());
}
@NonNull
@Override
public String getName() {
return "avoid_roads";
}
@NonNull
@Override
public String getPublicName(@NonNull Context ctx) {
return "avoid_roads";
}
@NonNull
@Override
public String getFileName() {
return getName() + ".json";
}
@Override
public void apply() {
for (AvoidRoadInfo duplicate : duplicateItems) {
if (shouldReplace) {
LatLon latLon = new LatLon(duplicate.latitude, duplicate.longitude);
if (settings.removeImpassableRoad(latLon)) {
settings.addImpassableRoad(duplicate);
}
} else {
settings.addImpassableRoad(duplicate);
}
}
for (AvoidRoadInfo avoidRoad : items) {
settings.addImpassableRoad(avoidRoad);
}
specificRoads.loadImpassableRoads();
specificRoads.initRouteObjects(true);
}
@NonNull
@Override
public List<AvoidRoadInfo> excludeDuplicateItems() {
duplicateItems = new ArrayList<>();
for (AvoidRoadInfo item : items) {
if (isDuplicate(item)) {
duplicateItems.add(item);
}
}
items.removeAll(duplicateItems);
return duplicateItems;
}
@Override
public boolean isDuplicate(AvoidRoadInfo item) {
for (AvoidRoadInfo existingItem : existingItems) {
if (item.latitude == existingItem.latitude && item.longitude == existingItem.longitude) {
return true;
}
}
return false;
}
@Override
public boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public AvoidRoadInfo renameItem(AvoidRoadInfo item) {
int number = 0;
while (true) {
number++;
AvoidRoadInfo renamedItem = item;
renamedItem.name = renamedItem.name + "_" + number;
if (!isDuplicate(renamedItem)) {
return renamedItem;
}
}
}
@NonNull
@Override
SettingsItemReader getReader() {
return new SettingsItemReader(this) {
@Override
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
StringBuilder buf = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
} catch (IOException e) {
throw new IOException("Cannot read json body", e);
}
String jsonStr = buf.toString();
if (Algorithms.isEmpty(jsonStr)) {
throw new IllegalArgumentException("Cannot find json body");
}
final JSONObject json;
try {
items = new ArrayList<>();
json = new JSONObject(jsonStr);
JSONArray jsonArray = json.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
double latitude = object.optDouble("latitude");
double longitude = object.optDouble("longitude");
String name = object.optString("name");
String appModeKey = object.optString("appModeKey");
AvoidRoadInfo roadInfo = new AvoidRoadInfo();
roadInfo.id = 0;
roadInfo.latitude = latitude;
roadInfo.longitude = longitude;
roadInfo.name = name;
roadInfo.appModeKey = appModeKey;
items.add(roadInfo);
}
} catch (JSONException e) {
throw new IllegalArgumentException("Json parse error", e);
}
}
};
}
@NonNull
@Override
SettingsItemWriter getWriter() {
return new SettingsItemWriter(this) {
@Override
public boolean writeToStream(@NonNull OutputStream outputStream) throws IOException {
JSONObject json = new JSONObject();
JSONArray jsonArray = new JSONArray();
if (!items.isEmpty()) {
try {
for (AvoidRoadInfo avoidRoad : items) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("latitude", avoidRoad.latitude);
jsonObject.put("longitude", avoidRoad.longitude);
jsonObject.put("name", avoidRoad.name);
jsonObject.put("appModeKey", avoidRoad.appModeKey);
jsonArray.put(jsonObject);
}
json.put("items", jsonArray);
} catch (JSONException e) {
LOG.error("Failed write to json", e);
}
}
if (json.length() > 0) {
try {
String s = json.toString(2);
outputStream.write(s.getBytes("UTF-8"));
} catch (JSONException e) {
LOG.error("Failed to write json to stream", e);
}
return true;
}
return false;
}
};
}
}
private static class SettingsItemsFactory {
private OsmandApplication app;
@ -1500,6 +1689,9 @@ public class SettingsHelper {
case MAP_SOURCES:
item = new MapSourcesSettingsItem(app, json);
break;
case AVOID_ROADS:
item = new AvoidRoadsSettingsItem(app, json);
break;
}
return item;
}

View file

@ -54,6 +54,10 @@ public class AvoidSpecificRoads {
public AvoidSpecificRoads(final OsmandApplication app) {
this.app = app;
loadImpassableRoads();
}
public void loadImpassableRoads(){
for (AvoidRoadInfo avoidRoadInfo : app.getSettings().getImpassableRoadPoints()) {
impassableRoads.put(new LatLon(avoidRoadInfo.latitude, avoidRoadInfo.longitude), avoidRoadInfo);
}

View file

@ -31,6 +31,7 @@ public class AdditionalDataWrapper {
POI_TYPES,
MAP_SOURCES,
CUSTOM_RENDER_STYLE,
CUSTOM_ROUTING
CUSTOM_ROUTING,
AVOID_ROADS
}
}

View file

@ -15,6 +15,7 @@ import net.osmand.plus.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.ProfileIconColors;
import net.osmand.plus.quickaction.QuickAction;
@ -118,6 +119,11 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter<RecyclerView
itemHolder.icon.setVisibility(View.INVISIBLE);
}
itemHolder.subTitle.setVisibility(View.GONE);
} else if (currentItem instanceof AvoidRoadInfo) {
itemHolder.title.setText(((AvoidRoadInfo) currentItem).name);
itemHolder.icon.setImageResource(R.drawable.map_pin_avoid_road);
itemHolder.subTitle.setVisibility(View.GONE);
itemHolder.icon.setVisibility(View.VISIBLE);
}
itemHolder.divider.setVisibility(shouldShowDivider(position) ? View.VISIBLE : View.GONE);
}

View file

@ -17,6 +17,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.AdditionalDataWrapper;
import net.osmand.plus.profiles.ProfileIconColors;
@ -213,6 +214,13 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter {
icon.setVisibility(View.VISIBLE);
subText.setVisibility(View.GONE);
break;
case AVOID_ROADS:
AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) currentItem;
title.setText(avoidRoadInfo.name);
icon.setImageResource(R.drawable.map_pin_avoid_road);
icon.setVisibility(View.VISIBLE);
subText.setVisibility(View.GONE);
break;
default:
return child;
}
@ -273,6 +281,8 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter {
return R.string.shared_string_custom_rendering_style;
case CUSTOM_ROUTING:
return R.string.shared_string_routing;
case AVOID_ROADS:
return R.string.avoid_road;
default:
return R.string.access_empty_list;
}

View file

@ -15,12 +15,12 @@ import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Toast;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager;
import net.osmand.plus.ApplicationMode;
@ -33,6 +33,7 @@ import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.AdditionalDataWrapper;
import net.osmand.plus.quickaction.QuickAction;
@ -245,6 +246,13 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
}
}
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
if (!impassableRoads.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.AVOID_ROADS,
new ArrayList<>(impassableRoads.values())
));
}
return dataList;
}
@ -262,6 +270,7 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
for (Object object : adapter.getDataToOperate()) {
if (object instanceof QuickAction) {
quickActions.add((QuickAction) object);
@ -272,6 +281,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) {
settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object));
} else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object);
}
}
if (!quickActions.isEmpty()) {
@ -283,6 +294,9 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates));
}
if (!avoidRoads.isEmpty()) {
settingsItems.add(new SettingsHelper.AvoidRoadsSettingsItem(app, avoidRoads));
}
return settingsItems;
}

View file

@ -19,6 +19,7 @@ import net.osmand.plus.SettingsHelper;
import net.osmand.plus.SettingsHelper.SettingsItem;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.view.ComplexButton;
@ -97,6 +98,7 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement
List<ITileSource> tileSources = new ArrayList<>();
List<File> renderFilesList = new ArrayList<>();
List<File> routingFilesList = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
for (Object object : duplicatesList) {
if (object instanceof ApplicationMode.ApplicationModeBean) {
@ -114,6 +116,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement
} else if (file.getAbsolutePath().contains("files/routing")) {
routingFilesList.add(file);
}
} else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object);
}
}
if (!profiles.isEmpty()) {
@ -140,6 +144,10 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement
duplicates.add(getString(R.string.shared_string_custom_rendering_style));
duplicates.addAll(renderFilesList);
}
if (!avoidRoads.isEmpty()) {
duplicates.add(getString(R.string.avoid_road));
duplicates.addAll(avoidRoads);
}
return duplicates;
}

View file

@ -20,6 +20,7 @@ import net.osmand.plus.SettingsHelper;
import net.osmand.plus.SettingsHelper.SettingsItem;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.AdditionalDataWrapper;
import net.osmand.plus.quickaction.QuickAction;
@ -124,7 +125,6 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
}
}
@SuppressWarnings("unchecked")
private List<Object> getDuplicatesData(List<SettingsItem> items) {
List<Object> duplicateItems = new ArrayList<>();
for (SettingsItem item : items) {
@ -151,6 +151,11 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
if (item.exists()) {
duplicateItems.add(((SettingsHelper.FileSettingsItem) item).getFile());
}
} else if (item instanceof SettingsHelper.AvoidRoadsSettingsItem) {
List<AvoidRoadInfo> avoidRoads = ((SettingsHelper.AvoidRoadsSettingsItem) item).excludeDuplicateItems();
if (!avoidRoads.isEmpty()) {
duplicateItems.addAll(avoidRoads);
}
}
}
return duplicateItems;
@ -165,6 +170,7 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
for (Object object : dataToOperate) {
if (object instanceof ApplicationMode.ApplicationModeBean) {
settingsItems.add(new SettingsHelper.ProfileSettingsItem(app, (ApplicationMode.ApplicationModeBean) object));
@ -178,6 +184,8 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) {
settingsItems.add(new SettingsHelper.FileSettingsItem(getMyApplication(), (File) object));
} else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object);
}
}
if (!quickActions.isEmpty()) {
@ -189,10 +197,12 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(getMyApplication(), tileSourceTemplates));
}
if (!avoidRoads.isEmpty()) {
settingsItems.add(new SettingsHelper.AvoidRoadsSettingsItem(getMyApplication(), avoidRoads));
}
return settingsItems;
}
@SuppressWarnings("unchecked")
private List<AdditionalDataWrapper> getSettingsToOperate() {
List<AdditionalDataWrapper> settingsToOperate = new ArrayList<>();
List<ApplicationMode.ApplicationModeBean> profiles = new ArrayList<>();
@ -201,6 +211,7 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
List<ITileSource> tileSourceTemplates = new ArrayList<>();
List<File> routingFilesList = new ArrayList<>();
List<File> renderFilesList = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
for (SettingsHelper.SettingsItem item : settingsItems) {
if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) {
@ -217,6 +228,8 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
} else if (item.getName().startsWith("/routing/")) {
routingFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile());
}
} else if (item.getType().equals(SettingsHelper.SettingsItemType.AVOID_ROADS)) {
avoidRoads.addAll(((SettingsHelper.AvoidRoadsSettingsItem) item).getItems());
}
}
@ -253,6 +266,12 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment
routingFilesList
));
}
if (!avoidRoads.isEmpty()) {
settingsToOperate.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.AVOID_ROADS,
avoidRoads
));
}
return settingsToOperate;
}