Fix geo intent search
This commit is contained in:
parent
3777a1ed4e
commit
58c3e89efb
2 changed files with 46 additions and 340 deletions
|
@ -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;
|
||||
|
|
|
@ -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<Void, Void, ExecutionResult> {
|
||||
private class GeoIntentTask extends AsyncTask<Void, Void, GeoParsedPoint> {
|
||||
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<br/>
|
||||
* geo:47.6,-122.3?z=11<br/>
|
||||
* geo:0,0?q=34.99,-106.61(Treasure)<br/>
|
||||
* geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA<br/>
|
||||
*
|
||||
* @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<MapObject> places = new ArrayList<MapObject>(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<MapObject> {
|
||||
|
||||
public MapObjectAdapter(List<MapObject> 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<br/>
|
||||
* geo:47.6,-122.3?z=11<br/>
|
||||
* geo:0,0?q=34.99,-106.61(Treasure)<br/>
|
||||
* geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA<br/>
|
||||
*
|
||||
* @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<String> 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<String>();
|
||||
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<String> q = new ArrayList<String>(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<RegionAddressRepository> countriesToSearch = limitSearchToCountries(q);
|
||||
// search cities for found countries
|
||||
final List<Street> allStreets = new ArrayList<Street>();
|
||||
final TLongObjectHashMap<City> cityIds = new TLongObjectHashMap<City>();
|
||||
for (RegionAddressRepository rar : countriesToSearch) {
|
||||
for (String element : q) {
|
||||
if (element != null && element.length() > 2) {
|
||||
rar.searchMapObjectsByName(element, new ResultMatcher<MapObject>() {
|
||||
@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<MapObject> connectedStreets = new ArrayList<MapObject>();
|
||||
Iterator<Street> 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<MapObject> all = new ArrayList<MapObject>();
|
||||
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<RegionAddressRepository> limitSearchToCountries(List<String> q) {
|
||||
ResourceManager resourceManager = getMyApplication().getResourceManager();
|
||||
List<RegionAddressRepository> foundCountries = new ArrayList<RegionAddressRepository>();
|
||||
RegionAddressRepository country;
|
||||
Iterator<String> it = q.iterator();
|
||||
while (it.hasNext()) {
|
||||
String maybeCountry = it.next();
|
||||
country = resourceManager.getRegionRepository(maybeCountry);
|
||||
if (country != null) {
|
||||
foundCountries.add(country);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
Collection<RegionAddressRepository> 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<MapObject>(), NO_ZOOM);
|
||||
|
||||
private final Collection<? extends MapObject> mapObjects;
|
||||
private final int zoom;
|
||||
|
||||
public ExecutionResult(final Collection<? extends MapObject> mapObjects) {
|
||||
this(mapObjects, NO_ZOOM);
|
||||
}
|
||||
|
||||
public ExecutionResult(final Collection<? extends MapObject> 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<? extends MapObject> 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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue