From 3a15e487505579a0da691e81128f4f4088556077 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Tue, 18 Apr 2017 11:50:21 +0300 Subject: [PATCH] Fix geo intent search --- .../net/osmand/util/GeoPointParserUtil.java | 2 +- .../activities/search/GeoIntentActivity.java | 384 ++---------------- 2 files changed, 46 insertions(+), 340 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index 550cb0d5ad..8f472ce0a0 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -1336,7 +1336,7 @@ public class GeoPointParserUtil { } public static class GeoParsedPoint { - private static final int NO_ZOOM = -1; + public static final int NO_ZOOM = -1; private double lat = 0; private double lon = 0; diff --git a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java index 281ce58bb7..09576dcaa5 100644 --- a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java @@ -15,7 +15,6 @@ import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.TextView; import android.widget.Toast; - import net.osmand.ResultMatcher; import net.osmand.data.Amenity; import net.osmand.data.City; @@ -34,7 +33,9 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.OsmandListActivity; import net.osmand.plus.resources.RegionAddressRepository; import net.osmand.plus.resources.ResourceManager; +import net.osmand.util.Algorithms; import net.osmand.util.GeoPointParserUtil; +import net.osmand.util.GeoPointParserUtil.GeoParsedPoint; import net.osmand.util.MapUtils; import java.util.ArrayList; @@ -87,16 +88,20 @@ public class GeoIntentActivity extends OsmandListActivity { } } - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - MapObject item = ((MapObjectAdapter) getListAdapter()).getItem(position); - OsmandSettings settings = getMyApplication().getSettings(); - settings.setMapLocationToShow(item.getLocation().getLatitude(), item.getLocation().getLongitude(), - settings.getLastKnownMapZoom(), getString(item)); //$NON-NLS-1$ - MapActivity.launchMapActivityMoveToTop(this); + + private PointDescription getString(MapObject o) { + if (o instanceof Amenity) { + OsmandSettings settings = ((OsmandApplication) getApplication()).getSettings(); + return new PointDescription(PointDescription.POINT_TYPE_POI, + OsmAndFormatter.getPoiStringWithoutType((Amenity) o, settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get())); + } + if (o instanceof Street) { + return new PointDescription(PointDescription.POINT_TYPE_ADDRESS, ((Street) o).getCity().getName() + " " + o.getName()); + } + return new PointDescription(PointDescription.POINT_TYPE_ADDRESS, o.toString()); } - private class GeoIntentTask extends AsyncTask { + private class GeoIntentTask extends AsyncTask { private final ProgressDialog progress; private final Intent intent; @@ -109,85 +114,54 @@ public class GeoIntentActivity extends OsmandListActivity { protected void onPreExecute() { } + /** + * Extracts information from geo and map intents: + * + * geo:47.6,-122.3
+ * geo:47.6,-122.3?z=11
+ * geo:0,0?q=34.99,-106.61(Treasure)
+ * geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA
+ * + * @param uri + * The intent uri + * @return + */ @Override - protected ExecutionResult doInBackground(Void... nothing) { + protected GeoParsedPoint doInBackground(Void... nothing) { try { while (getMyApplication().isApplicationInitializing()) { Thread.sleep(200); } - return extract(intent.getData()).execute(); + Uri uri = intent.getData(); + return GeoPointParserUtil.parse(uri.toString()); } catch (Exception e) { return null; } } @Override - protected void onPostExecute(ExecutionResult result) { + protected void onPostExecute(GeoPointParserUtil.GeoParsedPoint p ) { progress.dismiss(); - if (result != null) { - if (result.isEmpty()) { - Toast.makeText(GeoIntentActivity.this, getString(R.string.search_nothing_found), - Toast.LENGTH_LONG).show(); - } else { - if (result.hasZoom()) { - getMyApplication().getSettings().setLastKnownMapZoom(result.getZoom()); - } - - final List places = new ArrayList(result.getMapObjects()); - setListAdapter(new MapObjectAdapter(places)); - if (places.size() == 1) { - onItemClick(getListView(), getListAdapter().getView(0, null, null), 0, getListAdapter() - .getItemId(0)); - } + if (p != null && p.isGeoPoint()) { + OsmandSettings settings = getMyApplication().getSettings(); + PointDescription pd = new PointDescription(p.getLatitude(), p.getLongitude()); + if(!Algorithms.isEmpty(p.getLabel())) { + pd.setName(p.getLabel()); } - finish(); - } else { - Toast.makeText(GeoIntentActivity.this, - getString(R.string.search_offline_geo_error, intent.getData()), Toast.LENGTH_LONG).show(); + settings.setMapLocationToShow(p.getLatitude(), p.getLongitude(), + settings.getLastKnownMapZoom(), pd); //$NON-NLS-1$ + MapActivity.launchMapActivityMoveToTop(GeoIntentActivity.this); } + Uri uri = intent.getData(); + String searchString = p != null && p.isGeoAddress() ? p.getLabel() : uri.toString(); + + // TODO + MapActivity.launchMapActivityMoveToTop(GeoIntentActivity.this); + } } - private class MapObjectAdapter extends ArrayAdapter { - - public MapObjectAdapter(List places) { - super(GeoIntentActivity.this, R.layout.search_address_offline_list_item, places); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - if (row == null) { - LayoutInflater inflater = getLayoutInflater(); - row = inflater.inflate(R.layout.search_address_offline_list_item, parent, false); - } - MapObject model = getItem(position); - TextView label = (TextView) row.findViewById(R.id.label); - TextView distanceLabel = (TextView) row.findViewById(R.id.distance_label); - if (location != null) { - int dist = (int) (MapUtils.getDistance(location, model.getLocation().getLatitude(), model.getLocation() - .getLongitude())); - distanceLabel.setText(OsmAndFormatter.getFormattedDistance(dist, (OsmandApplication) getApplication())); - } else { - distanceLabel.setText(""); //$NON-NLS-1$ - } - label.setText(getString(model).getFullPlainName(getApplication())); - return row; - } - } - - private PointDescription getString(MapObject o) { - if (o instanceof Amenity) { - OsmandSettings settings = ((OsmandApplication) getApplication()).getSettings(); - return new PointDescription(PointDescription.POINT_TYPE_POI, - OsmAndFormatter.getPoiStringWithoutType((Amenity) o, settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get())); - } - if (o instanceof Street) { - return new PointDescription(PointDescription.POINT_TYPE_ADDRESS, ((Street) o).getCity().getName() + " " + o.getName()); - } - return new PointDescription(PointDescription.POINT_TYPE_ADDRESS, o.toString()); - } @Override @@ -202,274 +176,6 @@ public class GeoIntentActivity extends OsmandListActivity { progressDlg = null; } } + - /** - * Extracts information from geo and map intents: - * - * geo:47.6,-122.3
- * geo:47.6,-122.3?z=11
- * geo:0,0?q=34.99,-106.61(Treasure)
- * geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA
- * - * @param uri - * The intent uri - * @return - */ - private MyService extract(final Uri uri) { - Log.v(this.getClass().toString(), "extract(" + "uri=" + uri + ")"); - GeoPointParserUtil.GeoParsedPoint p = GeoPointParserUtil.parse(uri.toString()); - if (p.isGeoPoint()) { - if (p.getLabel() != null) { - return new GeoPointSearch(p.getLatitude(), p.getLongitude(), p.getLabel(), p.getZoom()); - } - return new GeoPointSearch(p.getLatitude(), p.getLongitude(), p.getZoom()); - } else { - return new GeoAddressSearch(p.getQuery()); - } - } - - private final class GeoAddressSearch implements MyService { - private List elements; - - public GeoAddressSearch(String query) { - query = query.replaceAll("%20", ",").replaceAll("%0A", ",").replaceAll("\n", ",").replaceAll("\t", ",") - .replaceAll(" ", ","); - System.out.println(query); - // String is split on each comma - String[] s = query.substring(query.indexOf("q=") + 2).split(","); - - elements = new ArrayList(); - for (int i = 0; i < s.length; i++) { - if (s[i].isEmpty()) { - continue; - } - elements.add(s[i].replace('+', ' ').trim()); - } - } - - public MapObject checkGeoPoint() { - double lat = Double.NaN; - double lon = Double.NaN; - for (String e : elements) { - if (e.startsWith("S") || e.startsWith("N")) { - try { - lat = Double.parseDouble(e.substring(1)); - if (e.startsWith("S")) { - lat = -lat; - } - } catch (NumberFormatException es) { - } - } else if (e.startsWith("E") || e.startsWith("W")) { - try { - lon = Double.parseDouble(e.substring(1)); - if (e.startsWith("W")) { - lon = -lon; - } - } catch (NumberFormatException es) { - } - } else if (e.contains(".")) { - try { - double n = Double.parseDouble(e); - if (Double.isNaN(lat)) { - lat = n; - } else { - lon = n; - } - } catch (NumberFormatException es) { - } - } - - } - if (Double.isNaN(lat) || Double.isNaN(lon)) { - return null; - } - - Amenity point = new Amenity(); - ((Amenity) point).setType(getMyApplication().getPoiTypes().getUserDefinedCategory()); - ((Amenity) point).setSubType(""); - point.setLocation(lat, lon); - point.setName("Lat: " + lat + ", Lon: " + lon); - return point; - } - - @Override - public ExecutionResult execute() { - if (elements.isEmpty()) { - return ExecutionResult.EMPTY; - } - List q = new ArrayList(elements); - MapObject geo = checkGeoPoint(); - if (geo != null) { - return new ExecutionResult(Collections.singleton(geo)); - } - // do not - if(DO_NOT_SEARCH_ADDRESS) { - return ExecutionResult.EMPTY; - } - - // now try to search the City, Street, Etc.. if Street is not found, - // try to search POI - Collection countriesToSearch = limitSearchToCountries(q); - // search cities for found countries - final List allStreets = new ArrayList(); - final TLongObjectHashMap cityIds = new TLongObjectHashMap(); - for (RegionAddressRepository rar : countriesToSearch) { - for (String element : q) { - if (element != null && element.length() > 2) { - rar.searchMapObjectsByName(element, new ResultMatcher() { - @Override - public boolean publish(MapObject object) { - if (object instanceof City && object.getId() != null) { - cityIds.put(object.getId(), (City) object); - } else if (object instanceof Street) { - allStreets.add((Street) object); - } - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - }); - } - } - } - if (cityIds.isEmpty()) { - return new ExecutionResult(allStreets); - } - final List connectedStreets = new ArrayList(); - Iterator p = allStreets.iterator(); - while (p.hasNext()) { - Street s = p.next(); - if (cityIds.contains(s.getCity().getId())) { - connectedStreets.add(s); - } else { - boolean tooFar = true; - for (City c : cityIds.valueCollection()) { - if (MapUtils.getDistance(c.getLocation(), s.getLocation()) < 50000) { - tooFar = false; - break; - } - } - if (tooFar) { - p.remove(); - } - } - } - if (connectedStreets.isEmpty()) { - List all = new ArrayList(); - all.addAll(cityIds.valueCollection()); - all.addAll(allStreets); - return new ExecutionResult(all); - } else { - // add all other results to connected streets - connectedStreets.addAll(cityIds.valueCollection()); - return new ExecutionResult(connectedStreets); - } - } - - private Collection limitSearchToCountries(List q) { - ResourceManager resourceManager = getMyApplication().getResourceManager(); - List foundCountries = new ArrayList(); - RegionAddressRepository country; - Iterator it = q.iterator(); - while (it.hasNext()) { - String maybeCountry = it.next(); - country = resourceManager.getRegionRepository(maybeCountry); - if (country != null) { - foundCountries.add(country); - it.remove(); - } - } - Collection countriesToSearch = foundCountries; - if (foundCountries.isEmpty()) { - // there is no country, we have to search each country - countriesToSearch = resourceManager.getAddressRepositories(); - } - return countriesToSearch; - } - - } - - @SuppressWarnings("unused") - private class GeoPointSearch implements MyService { - private final MapObject point; - private final int zoom; - - public GeoPointSearch(double lat, double lon) { - this(lat, lon, ExecutionResult.NO_ZOOM); - } - - public GeoPointSearch(double lat, double lon, int zoom) { - this(lat, lon, "Lat: " + lat + ", Lon: " + lon, zoom); - } - - public GeoPointSearch(double lat, double lon, String name) { - this(lat, lon, name, ExecutionResult.NO_ZOOM); - } - - public GeoPointSearch(double lat, double lon, String name, int zoom) { - final Amenity amenity = new Amenity(); - amenity.setLocation(lat, lon); - amenity.setName(name); - amenity.setType(getMyApplication().getPoiTypes().getUserDefinedCategory()); - amenity.setSubType(""); - - this.point = amenity; - this.zoom = zoom; - } - - @Override - public ExecutionResult execute() { - if (point != null) { - return new ExecutionResult(Collections.singletonList(point), zoom); - } else { - return ExecutionResult.EMPTY; - } - } - - } - - private static class ExecutionResult { - public static final int NO_ZOOM = -1; - public static final ExecutionResult EMPTY = new ExecutionResult(new ArrayList(), NO_ZOOM); - - private final Collection mapObjects; - private final int zoom; - - public ExecutionResult(final Collection mapObjects) { - this(mapObjects, NO_ZOOM); - } - - public ExecutionResult(final Collection mapObjects, final int zoom) { - this.mapObjects = mapObjects; - this.zoom = zoom; - } - - public boolean isEmpty() { - return mapObjects.isEmpty(); - } - - public boolean hasZoom() { - return zoom != NO_ZOOM; - } - - public Collection getMapObjects() { - return mapObjects; - } - - public int getZoom() { - return zoom; - } - - @Override - public String toString() { - return "ExecutionResult{" + "mapObjects=" + mapObjects + ", zoom=" + zoom + '}'; - } - } - - private static interface MyService { - public ExecutionResult execute(); - } }