From c54d8d47e8b3ac2ff124e8fa969db018fa154590 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 7 Jan 2015 21:38:09 +0100 Subject: [PATCH 01/14] use HTTPS URL for sharing location In order to maintain privacy when sharing location, this changes the shared location link to use HTTPS, thereby hiding the location info from anyone who might be snooping on the WiFi, ISP, internet, etc. Unfortunately, http://osm.org does not yet work with HTTPS, but the standard OSM URLs are short enough to fit into a text message. They are planning on supporting https://osm.org in the future: https://github.com/openstreetmap/operations/issues/2 --- OsmAnd-java/src/net/osmand/util/MapUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OsmAnd-java/src/net/osmand/util/MapUtils.java b/OsmAnd-java/src/net/osmand/util/MapUtils.java index d31519be60..a6619b16c0 100644 --- a/OsmAnd-java/src/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/net/osmand/util/MapUtils.java @@ -20,7 +20,9 @@ import net.osmand.data.QuadPoint; */ public class MapUtils { - private static final String BASE_SHORT_OSM_URL = "http://osm.org/go/"; + // TODO change the hostname back to osm.org once HTTPS works for it + // https://github.com/openstreetmap/operations/issues/2 + private static final String BASE_SHORT_OSM_URL = "https://openstreetmap.org/go/"; /** * This array is a lookup table that translates 6-bit positive integer From 597f4b0a89e5c982c1c53b694c6752559fa2014d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 8 Jan 2015 10:19:56 +0100 Subject: [PATCH 02/14] also match OSM short hostnames: osm.org and openstreetmap.org osm.org is the official short URL for OpenStreetMap, with proper HTTPS coming soon. openstreetmap.org is the temporary short URL since it already supports HTTPS. --- OsmAnd/AndroidManifest.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 93460e56de..7d15affb63 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -195,6 +195,10 @@ + + + + From 01bb7d091f00bd94c71389922175f36f0fe01ad0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 7 Jan 2015 22:08:04 +0100 Subject: [PATCH 03/14] split geo: URL creation to MapUtils.buildGeoUrl(lat, lon, z) This follow the pattern set by MapUtils.buildShortOsmUrl(). --- OsmAnd-java/src/net/osmand/util/MapUtils.java | 3 +++ .../plus/activities/actions/ShareLocation.java | 18 ++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/MapUtils.java b/OsmAnd-java/src/net/osmand/util/MapUtils.java index a6619b16c0..464833cae4 100644 --- a/OsmAnd-java/src/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/net/osmand/util/MapUtils.java @@ -277,6 +277,9 @@ public class MapUtils { }); } + public static String buildGeoUrl(double latitude, double longitude, int zoom) { + return "geo:" + ((float) latitude) + "," + ((float)longitude) + "?z=" + zoom; + } // Examples // System.out.println(buildShortOsmUrl(51.51829d, 0.07347d, 16)); // http://osm.org/go/0EEQsyfu diff --git a/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java b/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java index 27732c5056..a242970001 100644 --- a/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java +++ b/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java @@ -44,16 +44,16 @@ public class ShareLocation extends OsmAndAction { final int zoom = args.getInt(MapActivityActions.KEY_ZOOM); try { final String shortOsmUrl = MapUtils.buildShortOsmUrl(latitude, longitude, zoom); - final String appLink = "http://download.osmand.net/go?lat=" + ((float) latitude) + "&lon=" + ((float) longitude) + "&z=" + zoom; - String sms = mapActivity.getString(R.string.send_location_sms_pattern, shortOsmUrl, appLink); + final String geoUrl = MapUtils.buildGeoUrl(latitude, longitude, zoom); + String sms = mapActivity.getString(R.string.send_location_sms_pattern, geoUrl, shortOsmUrl); if (which == 0) { - sendEmail(shortOsmUrl, appLink); + sendEmail(shortOsmUrl, geoUrl); } else if (which == 1) { sendSms(sms); } else if (which == 2) { sendToClipboard(sms); } else if (which == 3) { - sendGeoActivity(latitude, longitude, zoom); + sendGeoActivity(geoUrl); } else if (which == 4) { sendQRCode(latitude, longitude); } @@ -69,8 +69,8 @@ public class ShareLocation extends OsmAndAction { - private void sendEmail(final String shortOsmUrl, final String appLink) { - String email = mapActivity.getString(R.string.send_location_email_pattern, shortOsmUrl, appLink); + private void sendEmail(final String shortOsmUrl, final String geoUrl) { + String email = mapActivity.getString(R.string.send_location_email_pattern, shortOsmUrl, geoUrl); ShareDialog.sendEmail(mapActivity, email, getString(R.string.send_location)); } @@ -83,10 +83,8 @@ public class ShareLocation extends OsmAndAction { } - private void sendGeoActivity(final double latitude, final double longitude, final int zoom) { - final String simpleGeo = "geo:"+((float) latitude)+","+((float)longitude) +"?z="+zoom; - Uri location = Uri.parse(simpleGeo); - Intent mapIntent = new Intent(Intent.ACTION_VIEW, location); + private void sendGeoActivity(final String geoUrl) { + Intent mapIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(geoUrl)); mapActivity.startActivity(mapIntent); } From 56eee3216f4e9a683b126498e8c73dffa6f19eb1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 19 Jan 2015 20:55:11 +0100 Subject: [PATCH 04/14] use http://osmand.net/go URL as HTTP url for sharing For the record, I do not think it is a good idea to share location using HTTP, it should always be HTTPS. There are too many privacy concerns. @vshcherb says he plans on adding HTTPS to osmand.net, so that will be good once it happens. --- OsmAnd/AndroidManifest.xml | 6 +++++- .../osmand/plus/activities/actions/ShareLocation.java | 11 ++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 7d15affb63..67011aaf19 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -79,7 +79,11 @@ - + + + + + diff --git a/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java b/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java index a242970001..303d589eb7 100644 --- a/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java +++ b/OsmAnd/src/net/osmand/plus/activities/actions/ShareLocation.java @@ -43,11 +43,12 @@ public class ShareLocation extends OsmAndAction { final double longitude = args.getDouble(MapActivityActions.KEY_LONGITUDE); final int zoom = args.getInt(MapActivityActions.KEY_ZOOM); try { - final String shortOsmUrl = MapUtils.buildShortOsmUrl(latitude, longitude, zoom); final String geoUrl = MapUtils.buildGeoUrl(latitude, longitude, zoom); - String sms = mapActivity.getString(R.string.send_location_sms_pattern, geoUrl, shortOsmUrl); + // TODO change this to HTTPS once it is setup! + final String httpUrl = "http://osmand.net/go?lat=" + ((float) latitude) + "&lon=" + ((float) longitude) + "&z=" + zoom; + String sms = mapActivity.getString(R.string.send_location_sms_pattern, geoUrl, httpUrl); if (which == 0) { - sendEmail(shortOsmUrl, geoUrl); + sendEmail(httpUrl, geoUrl); } else if (which == 1) { sendSms(sms); } else if (which == 2) { @@ -69,8 +70,8 @@ public class ShareLocation extends OsmAndAction { - private void sendEmail(final String shortOsmUrl, final String geoUrl) { - String email = mapActivity.getString(R.string.send_location_email_pattern, shortOsmUrl, geoUrl); + private void sendEmail(final String httpUrl, final String geoUrl) { + String email = mapActivity.getString(R.string.send_location_email_pattern, httpUrl, geoUrl); ShareDialog.sendEmail(mapActivity, email, getString(R.string.send_location)); } From ba156465344af90482fac11dcda86c17b84169e3 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 7 Jan 2015 23:22:42 +0100 Subject: [PATCH 05/14] old-ndk-build.sh: support standard ANDROID_HOME env var Google has defined the ANDROID_HOME env var as the standard env var to point to the Android SDK install. It is not so well documented, but it is documented here and there: https://developer.android.com/tools/testing/testing_ui.html#builddeploy http://books.sonatype.com/mvnref-book/reference/android-dev-sect-config-build.html --- OsmAnd/old-ndk-build.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/OsmAnd/old-ndk-build.sh b/OsmAnd/old-ndk-build.sh index 8056be82fa..5d1b067aba 100755 --- a/OsmAnd/old-ndk-build.sh +++ b/OsmAnd/old-ndk-build.sh @@ -4,15 +4,23 @@ SCRIPT_LOC="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" NAME=$(basename $(dirname "${BASH_SOURCE[0]}") ) -if [ ! -d "$ANDROID_SDK" ]; then - echo "ANDROID_SDK is not set" - exit +if [ -d "$ANDROID_HOME" ]; then + # for backwards compatbility + export ANDROID_SDK=$ANDROID_HOME +else + echo "ANDROID_HOME is not set, trying ANDROID_SDK:" + if [ -d "$ANDROID_SDK" ]; then + export ANDROID_HOME=$ANDROID_SDK + else + echo "ANDROID_SDK is also not set" + exit + fi fi if [ ! -d "$ANDROID_NDK" ]; then echo "ANDROID_NDK is not set" exit fi -export ANDROID_SDK_ROOT=$ANDROID_SDK +export ANDROID_SDK_ROOT=$ANDROID_HOME export ANDROID_NDK_ROOT=$ANDROID_NDK export ANDROID_NDK_TOOLCHAIN_VERSION=4.7 From 7729aa7350cbae133ea2af489f4fb1e30d21c3f2 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 9 Jan 2015 21:09:09 +0100 Subject: [PATCH 06/14] remove scheme arg from GeoPointParserUtil.parse(), java.net.URI provides it Since the first step in parse() is to create a URI instance, the scheme should come from URI.getScheme() instead of an arg. --- .../net/osmand/util/GeoPointParserUtil.java | 107 +++++++++--------- .../activities/search/GeoIntentActivity.java | 8 +- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index 29172cc0db..46daf95ae1 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -3,6 +3,7 @@ package net.osmand.util; import java.net.URI; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -18,68 +19,68 @@ public class GeoPointParserUtil { // geo:34,-106 url = "geo:" + ilat + "," + ilon; System.out.println("url: " + url); - GeoParsedPoint actual = GeoPointParserUtil.parse("geo", url); + GeoParsedPoint actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon)); // geo:34.99,-106.61 url = "geo:" + dlat + "," + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon)); // geo:34.99,-106.61?z=11 z = 11; url = "geo:" + dlat + "," + dlon + "?z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // geo:34.99,-106.61 (Treasure Island) url = "geo:" + dlat + "," + dlon + " (" + name + ")"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, name)); // geo:34.99,-106.61?z=11 (Treasure Island) z = 11; url = "geo:" + dlat + "," + dlon + "?z=" + z + " (" + name + ")"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); // geo:34.99,-106.61?q=34.99%2C-106.61 (Treasure Island) z = GeoParsedPoint.NO_ZOOM; url = "geo:" + dlat + "," + dlon + "?q=" + dlat + "%2C" + dlon + " (" + name + ")"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); // 0,0?q=34,-106(Treasure Island) z = GeoParsedPoint.NO_ZOOM; url = "geo:0,0?q=" + ilat + "," + ilon + " (" + name + ")"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z, name)); // 0,0?q=34.99,-106.61(Treasure Island) z = GeoParsedPoint.NO_ZOOM; url = "geo:0,0?q=" + dlat + "," + dlon + " (" + name + ")"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); // geo:0,0?z=11&q=34.99,-106.61(Treasure Island) z = 11; url = "geo:0,0?z=" + z + "&q=" + dlat + "," + dlon + " (" + name + ")"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); // geo:0,0?z=11&q=34.99,-106.61 z = 11; url = "geo:0,0?z=" + z + "&q=" + dlat + "," + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // google calendar @@ -87,14 +88,14 @@ public class GeoPointParserUtil { String qstr = "760 West Genesee Street Syracuse NY 13204"; url = "geo:0,0?q=" + qstr; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qstr)); // geo:0,0?z=11&q=1600+Amphitheatre+Parkway,+CA qstr = "1600 Amphitheatre Parkway, CA"; url = "geo:0,0?z=11&q=" + URLEncoder.encode(qstr); System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qstr)); // geo:50.451300,30.569900?z=15&q=50.451300,30.569900 (Kiev) @@ -105,85 +106,85 @@ public class GeoPointParserUtil { url = "geo:50.451300,30.569900?z=15&q=50.451300,30.569900 (Kiev)"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("geo", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qlat, qlon, z, qname)); // http://download.osmand.net/go?lat=34&lon=-106&z=11 url = "http://download.osmand.net/go?lat=" + ilat + "&lon=" + ilon + "&z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://download.osmand.net/go?lat=34.99&lon=-106.61&z=11 url = "http://download.osmand.net/go?lat=" + dlat + "&lon=" + dlon + "&z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://openstreetmap.org/map=11/34/-106 url = "http://openstreetmap.org/map=" + z + "/" + ilat + "/" + ilon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://openstreetmap.org/map=11/34.99/-106.61 url = "http://openstreetmap.org/map=" + z + "/" + dlat + "/" + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://openstreetmap.de/zoom=11&lat=34&lon=-106 url = "http://openstreetmap.de/zoom=" + z + "&lat=" + ilat + "&lon=" + ilon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://openstreetmap.de/zoom=11&lat=34.99&lon=-106.61 url = "http://openstreetmap.de/zoom=" + z + "&lat=" + dlat + "&lon=" + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://openstreetmap.de/lat=34.99&lon=-106.61&zoom=11 url = "http://openstreetmap.de/lat=" + dlat + "&lon=" + dlon + "&zoom=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://maps.google.com/maps/@34,-106,11z url = "http://maps.google.com/maps/@" + ilat + "," + ilon + "," + z + "z"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://maps.google.com/maps/@34.99,-106.61,11z url = "http://maps.google.com/maps/@" + dlat + "," + dlon + "," + z + "z"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://maps.google.com/maps/ll=34,-106,z=11 url = "http://maps.google.com/maps/ll=" + ilat + "," + ilon + ",z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://maps.google.com/maps/ll=34.99,-106.61,z=11 url = "http://maps.google.com/maps/ll=" + dlat + "," + dlon + ",z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://maps.google.com/maps/q=loc:34,-106&z=11 url = "http://maps.google.com/maps/q=loc:" + ilat + "," + ilon + "&z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://maps.google.com/maps/q=loc:34.99,-106.61&z=11 url = "http://maps.google.com/maps/q=loc:" + dlat + "," + dlon + "&z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // whatsapp @@ -191,7 +192,7 @@ public class GeoPointParserUtil { z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com/maps/q=loc:" + ilat + "," + ilon + " (You)"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // whatsapp @@ -199,103 +200,103 @@ public class GeoPointParserUtil { z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com/maps/q=loc:" + dlat + "," + dlon + " (You)"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://www.google.com/maps/search/food/34,-106,14z url = "http://www.google.com/maps/search/food/" + ilat + "," + ilon + "," + z + "z"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://www.google.com/maps/search/food/34.99,-106.61,14z url = "http://www.google.com/maps/search/food/" + dlat + "," + dlon + "," + z + "z"; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://maps.google.com?saddr=Current+Location&daddr=34,-106 z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com?saddr=Current+Location&daddr=" + ilat + "," + ilon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://maps.google.com?saddr=Current+Location&daddr=34.99,-106.61 z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com?saddr=Current+Location&daddr=" + dlat + "," + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://www.google.com/maps/dir/Current+Location/34,-106 z = GeoParsedPoint.NO_ZOOM; url = "http://www.google.com/maps/dir/Current+Location/" + ilat + "," + ilon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://www.google.com/maps/dir/Current+Location/34.99,-106.61 z = GeoParsedPoint.NO_ZOOM; url = "http://www.google.com/maps/dir/Current+Location/" + dlat + "," + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://maps.google.com/maps?q=34,-106 z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com/maps?q=" + ilat + "," + ilon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://maps.google.com/maps?q=34.99,-106.61 z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com/maps?q=" + dlat + "," + dlon; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://www.google.com/maps/place/760+West+Genesee+Street+Syracuse+NY+13204 qstr = "760+West+Genesee+Street+Syracuse+NY+13204"; url = "http://www.google.com/maps/place/" + qstr; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qstr)); // http://maps.google.com/maps?q=760+West+Genesee+Street+Syracuse+NY+13204 qstr = "760+West+Genesee+Street+Syracuse+NY+13204"; url = "http://www.google.com/maps?q=" + qstr; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qstr)); // http://maps.google.com/maps?daddr=760+West+Genesee+Street+Syracuse+NY+13204 qstr = "760+West+Genesee+Street+Syracuse+NY+13204"; url = "http://www.google.com/maps?daddr=" + qstr; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qstr)); // http://www.google.com/maps/dir/Current+Location/760+West+Genesee+Street+Syracuse+NY+13204 qstr = "760+West+Genesee+Street+Syracuse+NY+13204"; url = "http://www.google.com/maps/dir/Current+Location/" + qstr; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(qstr)); // http://maps.yandex.ru/?ll=34,-106&z=11 z = 11; url = "http://maps.yandex.ru/?ll=" + ilat + "," + ilon + "&z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // http://maps.yandex.ru/?ll=34.99,-106.61&z=11 z = 11; url = "http://maps.yandex.ru/?ll=" + dlat + "," + dlon + "&z=" + z; System.out.println("url: " + url); - actual = GeoPointParserUtil.parse("http", url); + actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); } @@ -326,8 +327,8 @@ public class GeoPointParserUtil { System.out.println("Passed!"); } - private static String getQueryParameter(final String param, URI data) { - final String query = data.getQuery(); + private static String getQueryParameter(final String param, URI uri) { + final String query = uri.getQuery(); String value = null; if (query != null && query.contains(param)) { String[] params = query.split("&"); @@ -344,17 +345,21 @@ public class GeoPointParserUtil { /** * Parses geo and map intents: * - * @param scheme - * The intent scheme * @param uri * The URI object * @return {@link GeoParsedPoint} */ - public static GeoParsedPoint parse(final String scheme, final String uri) { - final URI data = URI.create(uri.replaceAll("\\s+", "+").replaceAll("%20", "+").replaceAll("%2C", ",")); + public static GeoParsedPoint parse(final String uriString) { + final URI uri = URI.create(uriString.replaceAll("\\s+", "+").replaceAll("%20", "+").replaceAll("%2C", ",")); + + String scheme = uri.getScheme(); + if (scheme == null) + return null; + else + scheme = scheme.toLowerCase(Locale.US); if ("http".equals(scheme) || "https".equals(scheme)) { - final String schemeSpecific = data.getSchemeSpecificPart(); + final String schemeSpecific = uri.getSchemeSpecificPart(); if (schemeSpecific == null) { return null; @@ -403,7 +408,7 @@ public class GeoPointParserUtil { String subString = schemeSpecific.substring(sites[s][si].length()); if (subString.equals("")) { - subString = data.getFragment(); + subString = uri.getFragment(); } final Matcher matcher = Pattern.compile(patterns[s][p]).matcher(subString); @@ -463,7 +468,7 @@ public class GeoPointParserUtil { return null; } if ("geo".equals(scheme) || "osmand.geo".equals(scheme)) { - String schemeSpecific = data.getSchemeSpecificPart(); + String schemeSpecific = uri.getSchemeSpecificPart(); if (schemeSpecific == null) { return null; } diff --git a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java index c1928af9dc..a16e4739c8 100644 --- a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java @@ -101,7 +101,7 @@ public class GeoIntentActivity extends OsmandListActivity { while (getMyApplication().isApplicationInitializing()) { Thread.sleep(200); } - return extract(intent.getScheme(), intent.getData()).execute(); + return extract(intent.getData()).execute(); } catch (Exception e) { return null; } @@ -202,14 +202,12 @@ public class GeoIntentActivity extends OsmandListActivity { * geo:0,0?q=34.99,-106.61(Treasure)
* geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA
* - * @param scheme - * The intent scheme * @param data * The intent uri * @return */ - private MyService extract(final String scheme, final Uri data) { - GeoPointParserUtil.GeoParsedPoint p = GeoPointParserUtil.parse(scheme, data.toString()); + private MyService extract(final Uri uri) { + GeoPointParserUtil.GeoParsedPoint p = GeoPointParserUtil.parse(uri.toString()); if (p.isGeoPoint()) { if (p.getName() != null) { return new GeoPointSearch(p.getLat(), p.getLon(), p.getName(), p.getZoom()); From 32f7cccd0f47cfe2e2df6c230ebf6160f00b3679 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 12 Jan 2015 21:06:14 +0100 Subject: [PATCH 07/14] rework OpenStreetMap URL parsing to handle current formats It seems this code is quite out of date, because none of the URL formats listed in the tests seem to work. This commit updates the URL formats in the tests, then makes all of them parse properly. It also changes the parsing technique, leveraging java.net.URL's built-in parsing abilities to assist. Also, I plan on adding a lot more URL formats, so the current code structure made it very difficult to add to. So each service will be split out into its own section, starting here. --- .../net/osmand/util/GeoPointParserUtil.java | 135 +++++++++++++++--- 1 file changed, 118 insertions(+), 17 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index 46daf95ae1..3163982bd2 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -12,6 +12,7 @@ public class GeoPointParserUtil { public static void main(String[] args) { final int ilat = 34, ilon = -106; final double dlat = 34.99, dlon = -106.61; + final double longLat = 34.993933029174805, longLon = -106.615680694580078; final String name = "Treasure Island"; int z = GeoParsedPoint.NO_ZOOM; String url; @@ -121,18 +122,37 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); - // http://openstreetmap.org/map=11/34/-106 - url = "http://openstreetmap.org/map=" + z + "/" + ilat + "/" + ilon; + // http://openstreetmap.org/#map=11/34/-106 + url = "http://openstreetmap.org/#map=" + z + "/" + ilat + "/" + ilon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://openstreetmap.org/map=11/34.99/-106.61 - url = "http://openstreetmap.org/map=" + z + "/" + dlat + "/" + dlon; + // http://openstreetmap.org/#map=11/34.99/-106.61 + url = "http://openstreetmap.org/#map=" + z + "/" + dlat + "/" + dlon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + // http://openstreetmap.org/#11/34.99/-106.61 + url = "http://openstreetmap.org/#" + z + "/" + dlat + "/" + dlon; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + + // https://www.openstreetmap.org/#map=11/49.563/17.291 + url = "https://www.openstreetmap.org/#map=" + z + "/" + dlat + "/" + dlon; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + + // https://www.openstreetmap.org/?mlat=49.56275939941406&mlon=17.291107177734375#map=11/49.563/17.291 + url = "https://www.openstreetmap.org/?mlat=" + longLat + "&mlon=" + longLon + + "#map=" + z + "/" + dlat + "/" + dlon; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertGeoPoint(actual, new GeoParsedPoint(longLat, longLon, z)); + // http://openstreetmap.de/zoom=11&lat=34&lon=-106 url = "http://openstreetmap.de/zoom=" + z + "&lat=" + ilat + "&lon=" + ilon; System.out.println("url: " + url); @@ -298,6 +318,25 @@ public class GeoPointParserUtil { System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + + + /* URLs straight from various services, instead of generated here */ + + String urls[] = { + "https://www.openstreetmap.org/#map=0/0/0", + "https://www.openstreetmap.org/#map=0/180/180", + "https://www.openstreetmap.org/#map=0/-180/-180", + "https://www.openstreetmap.org/#map=0/180.0/180.0", + "https://www.openstreetmap.org/#map=6/33.907/34.662", + "https://www.openstreetmap.org/?mlat=49.56275939941406&mlon=17.291107177734375#map=8/49.563/17.291", + }; + + for (String u : urls) { + System.out.println("url: " + u); + actual = GeoPointParserUtil.parse(u); + assert(actual != null); + System.out.println("Passed!"); + } } private static void assertGeoPoint(GeoParsedPoint actual, GeoParsedPoint expected) { @@ -357,22 +396,22 @@ public class GeoPointParserUtil { return null; else scheme = scheme.toLowerCase(Locale.US); + if ("http".equals(scheme) || "https".equals(scheme)) { + String host = uri.getHost(); + if (host == null) + return null; + else + host = host.toLowerCase(Locale.US); final String schemeSpecific = uri.getSchemeSpecificPart(); - - if (schemeSpecific == null) { + if (schemeSpecific == null) return null; - } final String[] osmandNetSite = { "//download.osmand.net/go?" }; final String[] osmandNetPattern = { "lat=([+-]?\\d+(?:\\.\\d+)?)&lon=([+-]?\\d+(?:\\.\\d+)?)&?(z=\\d{1,2})" }; - final String[] openstreetmapOrgSite = { "//openstreetmap.org/", "//www.openstreetmap.org/" }; - - final String[] openstreetmapOrgPattern = { "(?:.*)(?:map=)(\\d{1,2})/([+-]?\\d+(?:\\.\\d+)?)/([+-]?\\d+(?:\\.\\d+)?)(?:.*)" }; - final String[] openstreetmapDeSite = { "//openstreetmap.de/", "//www.openstreetmap.de/" }; final String[] openstreetmapDePattern = { @@ -395,11 +434,56 @@ public class GeoPointParserUtil { final String[] yandexRuPattern = { "(?:.*)ll=([+-]?\\d+(?:\\.\\d+)?),([+-]?\\d+(?:\\.\\d+)?)(?:.+)(z=\\d{1,2})(?:.*)" }; - final String sites[][] = { osmandNetSite, openstreetmapOrgSite, openstreetmapDeSite, googleComSite, - yandexRuSite }; + final String sites[][] = { osmandNetSite, openstreetmapDeSite, + googleComSite, yandexRuSite }; + + final String patterns[][] = { osmandNetPattern, + openstreetmapDePattern, googleComPattern, yandexRuPattern }; + + try { + if (host.equals("osm.org") || host.endsWith("openstreetmap.org")) { + Pattern p; + Matcher matcher; + String path = uri.getPath(); + if ("go".equals(path)) { // short URL form + // TODO decode OSM short URL and delete this: + p = Pattern.compile("(?:.*)(?:map=)(\\d{1,2})/([+-]?\\d+(?:\\.\\d+)?)/([+-]?\\d+(?:\\.\\d+)?)(?:.*)"); + matcher = p.matcher(schemeSpecific); + } else { // data in the query and/or feature strings + String lat = "0"; + String lon = "0"; + String zoom = String.valueOf(GeoParsedPoint.NO_ZOOM); + String fragment = uri.getFragment(); + if (fragment != null) { + p = Pattern.compile("(?:map=)?(\\d{1,2})/([+-]?\\d+(?:\\.\\d+)?)/([+-]?\\d+(?:\\.\\d+)?)(?:.*)"); + matcher = p.matcher(fragment); + if (matcher.matches()) { + zoom = matcher.group(1); + lat = matcher.group(2); + lon = matcher.group(3); + } + } + String query = uri.getQuery(); + if (query != null) { + // the query string sometimes has higher resolution values + p = Pattern.compile("(?:.*)mlat=([+-]?\\d+(?:\\.\\d+)?)(?:.*)&mlon=([+-]?\\d+(?:\\.\\d+)?)(?:.*)?"); + matcher = p.matcher(query); + if (matcher.matches()) { + lat = matcher.group(1); + lon = matcher.group(2); + } + } + return new GeoParsedPoint(lat, lon, zoom); + } + } + } catch (IllegalStateException e) { + e.printStackTrace(); + return null; + } catch (NumberFormatException e) { + e.printStackTrace(); + return null; + } - final String patterns[][] = { osmandNetPattern, openstreetmapOrgPattern, openstreetmapDePattern, - googleComPattern, yandexRuPattern }; // search by geo coordinates for (int s = 0; s < sites.length; s++) { for (int si = 0; si < sites[s].length; si++) { @@ -466,8 +550,7 @@ public class GeoPointParserUtil { } } return null; - } - if ("geo".equals(scheme) || "osmand.geo".equals(scheme)) { + } else if ("geo".equals(scheme) || "osmand.geo".equals(scheme)) { String schemeSpecific = uri.getSchemeSpecificPart(); if (schemeSpecific == null) { return null; @@ -545,6 +628,14 @@ public class GeoPointParserUtil { return null; } + private static int parseZoom(String zoom) { + try { + return Integer.valueOf(zoom); + } catch (NumberFormatException e) { + return GeoParsedPoint.NO_ZOOM; + } + } + public static class GeoParsedPoint { private static final int NO_ZOOM = -1; @@ -579,6 +670,16 @@ public class GeoPointParserUtil { this.zoom = zoom; } + public GeoParsedPoint(String latString, String lonString, String zoomString) throws NumberFormatException { + this(Double.valueOf(latString), Double.valueOf(lonString)); + this.zoom = parseZoom(zoomString); + } + + public GeoParsedPoint(String latString, String lonString) throws NumberFormatException { + this(Double.valueOf(latString), Double.valueOf(lonString)); + this.zoom = NO_ZOOM; + } + public GeoParsedPoint(String query) { super(); this.query = query; From baf25cbb14a4087294892534976155bea33ea283 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 12 Jan 2015 21:08:32 +0100 Subject: [PATCH 08/14] include test lat/lon to 5 decimal places since that's the common format This makes the test more realistic, since most services are using at least this much accuracy. --- .../net/osmand/util/GeoPointParserUtil.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index 3163982bd2..eff976476d 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -11,7 +11,7 @@ public class GeoPointParserUtil { public static void main(String[] args) { final int ilat = 34, ilon = -106; - final double dlat = 34.99, dlon = -106.61; + final double dlat = 34.99393, dlon = -106.61568; final double longLat = 34.993933029174805, longLon = -106.615680694580078; final String name = "Treasure Island"; int z = GeoParsedPoint.NO_ZOOM; @@ -23,33 +23,33 @@ public class GeoPointParserUtil { GeoParsedPoint actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon)); - // geo:34.99,-106.61 + // geo:34.99393,-106.61568 url = "geo:" + dlat + "," + dlon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon)); - // geo:34.99,-106.61?z=11 + // geo:34.99393,-106.61568?z=11 z = 11; url = "geo:" + dlat + "," + dlon + "?z=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); - // geo:34.99,-106.61 (Treasure Island) + // geo:34.99393,-106.61568 (Treasure Island) url = "geo:" + dlat + "," + dlon + " (" + name + ")"; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, name)); - // geo:34.99,-106.61?z=11 (Treasure Island) + // geo:34.99393,-106.61568?z=11 (Treasure Island) z = 11; url = "geo:" + dlat + "," + dlon + "?z=" + z + " (" + name + ")"; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); - // geo:34.99,-106.61?q=34.99%2C-106.61 (Treasure Island) + // geo:34.99393,-106.61568?q=34.99393%2C-106.61568 (Treasure Island) z = GeoParsedPoint.NO_ZOOM; url = "geo:" + dlat + "," + dlon + "?q=" + dlat + "%2C" + dlon + " (" + name + ")"; System.out.println("url: " + url); @@ -63,21 +63,21 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z, name)); - // 0,0?q=34.99,-106.61(Treasure Island) + // 0,0?q=34.99393,-106.61568(Treasure Island) z = GeoParsedPoint.NO_ZOOM; url = "geo:0,0?q=" + dlat + "," + dlon + " (" + name + ")"; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); - // geo:0,0?z=11&q=34.99,-106.61(Treasure Island) + // geo:0,0?z=11&q=34.99393,-106.61568(Treasure Island) z = 11; url = "geo:0,0?z=" + z + "&q=" + dlat + "," + dlon + " (" + name + ")"; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z, name)); - // geo:0,0?z=11&q=34.99,-106.61 + // geo:0,0?z=11&q=34.99393,-106.61568 z = 11; url = "geo:0,0?z=" + z + "&q=" + dlat + "," + dlon; System.out.println("url: " + url); @@ -116,7 +116,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://download.osmand.net/go?lat=34.99&lon=-106.61&z=11 + // http://download.osmand.net/go?lat=34.99393&lon=-106.61568&z=11 url = "http://download.osmand.net/go?lat=" + dlat + "&lon=" + dlon + "&z=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -128,13 +128,13 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://openstreetmap.org/#map=11/34.99/-106.61 + // http://openstreetmap.org/#map=11/34.99393/-106.61568 url = "http://openstreetmap.org/#map=" + z + "/" + dlat + "/" + dlon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); - // http://openstreetmap.org/#11/34.99/-106.61 + // http://openstreetmap.org/#11/34.99393/-106.61568 url = "http://openstreetmap.org/#" + z + "/" + dlat + "/" + dlon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -159,13 +159,13 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://openstreetmap.de/zoom=11&lat=34.99&lon=-106.61 + // http://openstreetmap.de/zoom=11&lat=34.99393&lon=-106.61568 url = "http://openstreetmap.de/zoom=" + z + "&lat=" + dlat + "&lon=" + dlon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); - // http://openstreetmap.de/lat=34.99&lon=-106.61&zoom=11 + // http://openstreetmap.de/lat=34.99393&lon=-106.61568&zoom=11 url = "http://openstreetmap.de/lat=" + dlat + "&lon=" + dlon + "&zoom=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -177,7 +177,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://maps.google.com/maps/@34.99,-106.61,11z + // http://maps.google.com/maps/@34.99393,-106.61568,11z url = "http://maps.google.com/maps/@" + dlat + "," + dlon + "," + z + "z"; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -189,7 +189,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://maps.google.com/maps/ll=34.99,-106.61,z=11 + // http://maps.google.com/maps/ll=34.99393,-106.61568,z=11 url = "http://maps.google.com/maps/ll=" + dlat + "," + dlon + ",z=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -201,7 +201,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://maps.google.com/maps/q=loc:34.99,-106.61&z=11 + // http://maps.google.com/maps/q=loc:34.99393,-106.61568&z=11 url = "http://maps.google.com/maps/q=loc:" + dlat + "," + dlon + "&z=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -216,7 +216,7 @@ public class GeoPointParserUtil { assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); // whatsapp - // http://maps.google.com/maps/q=loc:34.99,-106.61 (You) + // http://maps.google.com/maps/q=loc:34.99393,-106.61568 (You) z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com/maps/q=loc:" + dlat + "," + dlon + " (You)"; System.out.println("url: " + url); @@ -229,7 +229,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://www.google.com/maps/search/food/34.99,-106.61,14z + // http://www.google.com/maps/search/food/34.99393,-106.61568,14z url = "http://www.google.com/maps/search/food/" + dlat + "," + dlon + "," + z + "z"; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -242,7 +242,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://maps.google.com?saddr=Current+Location&daddr=34.99,-106.61 + // http://maps.google.com?saddr=Current+Location&daddr=34.99393,-106.61568 z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com?saddr=Current+Location&daddr=" + dlat + "," + dlon; System.out.println("url: " + url); @@ -256,7 +256,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://www.google.com/maps/dir/Current+Location/34.99,-106.61 + // http://www.google.com/maps/dir/Current+Location/34.99393,-106.61568 z = GeoParsedPoint.NO_ZOOM; url = "http://www.google.com/maps/dir/Current+Location/" + dlat + "," + dlon; System.out.println("url: " + url); @@ -270,7 +270,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://maps.google.com/maps?q=34.99,-106.61 + // http://maps.google.com/maps?q=34.99393,-106.61568 z = GeoParsedPoint.NO_ZOOM; url = "http://maps.google.com/maps?q=" + dlat + "," + dlon; System.out.println("url: " + url); @@ -312,7 +312,7 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // http://maps.yandex.ru/?ll=34.99,-106.61&z=11 + // http://maps.yandex.ru/?ll=34.99393,-106.61568&z=11 z = 11; url = "http://maps.yandex.ru/?ll=" + dlat + "," + dlon + "&z=" + z; System.out.println("url: " + url); From 147f2adf05a5e2663b86c4786c5a23f370769f61 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 12 Jan 2015 21:50:27 +0100 Subject: [PATCH 09/14] add BaiduMap as a URL pattern (http://map.baidu.com) This is a mapping service that is popular in China. --- .../net/osmand/util/GeoPointParserUtil.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index eff976476d..2452ac65b7 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -319,6 +319,14 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + // http://map.baidu.com/?l=13&tn=B_NORMAL_MAP&c=13748138,4889173&s=gibberish + z = 7; + int latint = ((int)(dlat * 100000)); + int lonint = ((int)(dlon * 100000)); + url = "http://map.baidu.com/?l=" + z + "&tn=B_NORMAL_MAP&c=" + latint + "," + lonint + "&s=gibberish"; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); /* URLs straight from various services, instead of generated here */ @@ -475,6 +483,17 @@ public class GeoPointParserUtil { } return new GeoParsedPoint(lat, lon, zoom); } + } else if (schemeSpecific.startsWith("//map.baidu.")) { // .com and .cn both work + /* Baidu Map uses a custom format for lat/lon., it is basically standard lat/lon + * multiplied by 100,000, then rounded to an integer */ + Pattern p = Pattern.compile(".*[/?&]l=(\\d{1,2}).*&c=([+-]?\\d+),([+-]?\\d+).*"); + Matcher matcher = p.matcher(schemeSpecific); + if (matcher.matches()) { + double lat = Integer.valueOf(matcher.group(2)) / 100000.; + double lon = Integer.valueOf(matcher.group(3)) / 100000.; + int zoom = parseZoom(matcher.group(1)); + return new GeoParsedPoint(lat, lon, zoom); + } } } catch (IllegalStateException e) { e.printStackTrace(); From 50abbb0d57c80cbcc6271e2a56db23afa78ed7cf Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 13 Jan 2015 12:02:02 +0100 Subject: [PATCH 10/14] consolidate IntentFilter for matching HTTP map URIs with no specific path This puts them all into a single to improve readability and reduce the number of IntentFilters used. This also adds some new domains: * maps.yandex.com * map.baidu.cn * map.baidu.com * wb.amap.com * www.amap.com --- OsmAnd/AndroidManifest.xml | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 67011aaf19..b9e6420487 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -181,10 +181,16 @@ - - - - + + + + + + + + + + @@ -196,17 +202,6 @@ - - - - - - - - - - - From 2537d92a6ae569330aeca5feb582917db762705d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 13 Jan 2015 19:32:57 +0100 Subject: [PATCH 11/14] update MapUtils.decodeShortLinkString() to also parse zoom This method is used to parse the custom OpenStreetMap shortlink algorithm that encodes lat, lon, and zoom. The previous version, MapUtils.decodeShortLocString(), only parsed lat, lon from the shortlink. --- .../net/osmand/util/GeoPointParserUtil.java | 6 +- OsmAnd-java/src/net/osmand/util/MapUtils.java | 61 +++++++++---------- .../activities/search/GeoIntentActivity.java | 4 +- .../audionotes/AudioVideoNotesPlugin.java | 10 +-- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index 2452ac65b7..effb770cbf 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -352,7 +352,7 @@ public class GeoPointParserUtil { if (!expected.getQuery().equals(actual.getQuery())) throw new RuntimeException("Query param not equal"); } else { - double aLat = actual.getLat(), eLat = expected.getLat(), aLon = actual.getLon(), eLon = expected.getLon(); + double aLat = actual.getLatitude(), eLat = expected.getLatitude(), aLon = actual.getLongitude(), eLon = expected.getLongitude(); int aZoom = actual.getZoom(), eZoom = expected.getZoom(); String aName = actual.getName(), eName = expected.getName(); if (eName != null) { @@ -705,11 +705,11 @@ public class GeoPointParserUtil { this.geoAddress = true; } - public double getLat() { + public double getLatitude() { return lat; } - public double getLon() { + public double getLongitude() { return lon; } diff --git a/OsmAnd-java/src/net/osmand/util/MapUtils.java b/OsmAnd-java/src/net/osmand/util/MapUtils.java index 464833cae4..38d2f179eb 100644 --- a/OsmAnd-java/src/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/net/osmand/util/MapUtils.java @@ -8,6 +8,7 @@ import java.util.List; import net.osmand.data.LatLon; import net.osmand.data.MapObject; import net.osmand.data.QuadPoint; +import net.osmand.util.GeoPointParserUtil.GeoParsedPoint; /** @@ -286,10 +287,10 @@ public class MapUtils { // System.out.println(buildShortOsmUrl(52.30103d, 4.862927d, 18)); // http://osm.org/go/0E4_JiVhs // System.out.println(buildShortOsmUrl(40.59d, -115.213d, 9)); // http://osm.org/go/TelHTB-- public static String buildShortOsmUrl(double latitude, double longitude, int zoom){ - return BASE_SHORT_OSM_URL + createShortLocString(latitude, longitude, zoom) + "?m"; + return BASE_SHORT_OSM_URL + createShortLinkString(latitude, longitude, zoom) + "?m"; } - public static String createShortLocString(double latitude, double longitude, int zoom) { + public static String createShortLinkString(double latitude, double longitude, int zoom) { long lat = (long) (((latitude + 90d)/180d)*(1L << 32)); long lon = (long) (((longitude + 180d)/360d)*(1L << 32)); long code = interleaveBits(lon, lat); @@ -306,44 +307,42 @@ public class MapUtils { return str; } - @SuppressWarnings("unused") - public static LatLon decodeShortLocString(String s) { + public static GeoParsedPoint decodeShortLinkString(String s) { + int i = 0; long x = 0; long y = 0; - int z = 0; - int z_offset = 0; + int z = -8; - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) == '-') { - z_offset--; - continue; - } + for (i = 0; i < s.length(); i++) { + int digit = -1; char c = s.charAt(i); - for (int j = 0; j < intToBase64.length; j++) { + for (int j = 0; j < intToBase64.length; j++) if (c == intToBase64[j]) { - for (int k = 0; k < 3; k++) { - x <<= 1; - if ((j & 32) != 0) { - x = x | 1; - } - j <<= 1; - y <<= 1; - if ((j & 32) != 0) { - y = y | 1; - } - j <<= 1; - } - z += 3; + digit = j; break; } + if (digit < 0) + break; + if (digit < 0) + break; + // distribute 6 bits into x and y + x <<= 3; + y <<= 3; + for (int j = 2; j >= 0; j--) { + x |= ((digit & (1 << (j+j+1))) == 0 ? 0 : (1 << j)); + y |= ((digit & (1 << (j+j))) == 0 ? 0 : (1 << j)); } + z += 3; } - x <<= (32 - z); - y <<= (32 - z); -// int zoom = z - 8 - ((3 + z_offset) % 3); - double dlat = (180d * (y) / ((double)(1L << 32))) - 90d; - double dlon = (360d * (x)/ ((double)(1L << 32))) - 180d; - return new LatLon(dlat, dlon); + double lon = x * Math.pow(2, 2 - 3 * i) * 90. - 180; + double lat = y * Math.pow(2, 2 - 3 * i) * 45. - 90; + // adjust z + if(i < s.length() && s.charAt(i) == '-') { + z -= 2; + if(i + 1 < s.length() && s.charAt(i + 1) == '-') + z++; + } + return new GeoParsedPoint(lat, lon, z); } /** diff --git a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java index a16e4739c8..e798d19123 100644 --- a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java @@ -210,9 +210,9 @@ public class GeoIntentActivity extends OsmandListActivity { GeoPointParserUtil.GeoParsedPoint p = GeoPointParserUtil.parse(uri.toString()); if (p.isGeoPoint()) { if (p.getName() != null) { - return new GeoPointSearch(p.getLat(), p.getLon(), p.getName(), p.getZoom()); + return new GeoPointSearch(p.getLatitude(), p.getLongitude(), p.getName(), p.getZoom()); } - return new GeoPointSearch(p.getLat(), p.getLon(), p.getZoom()); + return new GeoPointSearch(p.getLatitude(), p.getLongitude(), p.getZoom()); } else { return new GeoAddressSearch(p.getQuery()); } diff --git a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java index d514931d7b..4885161e8c 100644 --- a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java +++ b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java @@ -23,7 +23,6 @@ import net.osmand.PlatformUtil; import net.osmand.access.AccessibleAlertBuilder; import net.osmand.access.AccessibleToast; import net.osmand.data.DataTileManager; -import net.osmand.data.LatLon; import net.osmand.plus.ApplicationMode; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick; @@ -46,6 +45,7 @@ import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.mapwidgets.StackWidgetView; import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.util.Algorithms; +import net.osmand.util.GeoPointParserUtil.GeoParsedPoint; import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; @@ -553,7 +553,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { } private File getBaseFileName(double lat, double lon, OsmandApplication app, String ext) { - String basename = MapUtils.createShortLocString(lat, lon, 15); + String basename = MapUtils.createShortLinkString(lat, lon, 15); int k = 1; File f = app.getAppPath(IndexConstants.AV_INDEX_DIR); f.mkdirs(); @@ -941,9 +941,9 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { encodeName = encodeName.substring(0, i); } r.file = f; - LatLon l = MapUtils.decodeShortLocString(encodeName); - r.lat = l.getLatitude(); - r.lon = l.getLongitude(); + GeoParsedPoint geo = MapUtils.decodeShortLinkString(encodeName); + r.lat = geo.getLatitude(); + r.lon = geo.getLongitude(); Float heading = app.getLocationProvider().getHeading(); Location loc = app.getLocationProvider().getLastKnownLocation(); if (lastTakingPhoto != null && lastTakingPhoto.getName().equals(f.getName()) && heading != null) { From 8d927de6ac3f886d9f5276a7618db6834cbfc149 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 14 Jan 2015 20:49:36 +0100 Subject: [PATCH 12/14] if incoming URL was properly parsed, remove GeoIntentActivity from backstack When a user clicks on a URL that OsmAnd claims, they will first go to the GeoIntentActivity, which will show them the processing, and any errors, then it'll take them to the map. Since the map will stay in the same task as the original Activity where the user clicked it, the user is very likely to be clicking on the back button. Calling finish() here gives them one less thing to click back on, since GeoIntentActivity will be removed. closes #1037 https://github.com/osmandapp/Osmand/pull/1037 --- .../src/net/osmand/plus/activities/search/GeoIntentActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java index e798d19123..f9dd96b7f5 100644 --- a/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/search/GeoIntentActivity.java @@ -126,6 +126,7 @@ public class GeoIntentActivity extends OsmandListActivity { .getItemId(0)); } } + finish(); } else { AccessibleToast.makeText(GeoIntentActivity.this, getString(R.string.search_offline_geo_error, intent.getData()), Toast.LENGTH_LONG).show(); From 50eed920159aa1dd3f24fa624613d89c455c0f0a Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 13 Jan 2015 19:36:58 +0100 Subject: [PATCH 13/14] parse lat/lon/zoom from OpenStreetMap shortlinks This is a nice format of shortlink since it uses a public, offline algorithm to generate them. So Osmand can get what it needs from the shortlink without going online. https://wiki.openstreetmap.org/wiki/Shortlink --- .../net/osmand/util/GeoPointParserUtil.java | 80 +++++++++++++++++-- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index effb770cbf..c170c8c4f6 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -123,6 +123,7 @@ public class GeoPointParserUtil { assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://openstreetmap.org/#map=11/34/-106 + z = 11; url = "http://openstreetmap.org/#map=" + z + "/" + ilat + "/" + ilon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -146,14 +147,33 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); - // https://www.openstreetmap.org/?mlat=49.56275939941406&mlon=17.291107177734375#map=11/49.563/17.291 + // https://www.openstreetmap.org/?mlat=34.993933029174805&mlon=-106.61568069458008#map=11/34.99393/-106.61568 url = "https://www.openstreetmap.org/?mlat=" + longLat + "&mlon=" + longLon + "#map=" + z + "/" + dlat + "/" + dlon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); - assertGeoPoint(actual, new GeoParsedPoint(longLat, longLon, z)); + assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + + // https://wiki.openstreetmap.org/wiki/Shortlink + + // http://osm.org/go/TyFSutZ-?m= + // https://www.openstreetmap.org/?mlat=34.993933029174805&mlon=-106.61568069458008#map=15/34.99393/-106.61568 + z = 15; + url = "http://osm.org/go/TyFYuF6P--?m="; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertApproximateGeoPoint(actual, new GeoParsedPoint(longLat, longLon, z)); + + // http://osm.org/go/TyFS-- + // http://www.openstreetmap.org/#map=3/34.99/-106.70 + z = 3; + url = "http://osm.org/go/TyFS--"; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertApproximateGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); // http://openstreetmap.de/zoom=11&lat=34&lon=-106 + z = 11; url = "http://openstreetmap.de/zoom=" + z + "&lat=" + ilat + "&lon=" + ilon; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); @@ -331,6 +351,10 @@ public class GeoPointParserUtil { /* URLs straight from various services, instead of generated here */ String urls[] = { + "https://openstreetmap.org/go/0LQ127-?m", + "http://osm.org/go/0LQ127-?m", + "http://osm.org/go/0EEQjE==", + "http://osm.org/go/0EEQjEEb", "https://www.openstreetmap.org/#map=0/0/0", "https://www.openstreetmap.org/#map=0/180/180", "https://www.openstreetmap.org/#map=0/-180/-180", @@ -347,6 +371,17 @@ public class GeoPointParserUtil { } } + private static boolean areCloseEnough(int a, int b) { + return a == b; + } + + private static boolean areCloseEnough(double a, double b, long howClose) { + long aRounded = (long) Math.round(a * Math.pow(10, howClose)); + long bRounded = (long) Math.round(b * Math.pow(10, howClose)); + System.out.println("areCloseEnough: " + aRounded + ", " + bRounded); + return aRounded == bRounded; + } + private static void assertGeoPoint(GeoParsedPoint actual, GeoParsedPoint expected) { if (expected.getQuery() != null) { if (!expected.getQuery().equals(actual.getQuery())) @@ -361,10 +396,37 @@ public class GeoPointParserUtil { + eName); } } - if (eLat != aLat) { + if (!areCloseEnough(eLat, aLat, 5)) { throw new RuntimeException("Latitude is not equal; actual=" + aLat + ", expected=" + eLat); } - if (eLon != aLon) { + if (!areCloseEnough(eLon, aLon, 5)) { + throw new RuntimeException("Longitude is not equal; actual=" + aLon + ", expected=" + eLon); + } + if (eZoom != aZoom) { + throw new RuntimeException("Zoom is not equal; actual=" + aZoom + ", expected=" + eZoom); + } + } + System.out.println("Passed!"); + } + + private static void assertApproximateGeoPoint(GeoParsedPoint actual, GeoParsedPoint expected) { + if (expected.getQuery() != null) { + if (!expected.getQuery().equals(actual.getQuery())) + throw new RuntimeException("Query param not equal"); + } else { + double aLat = actual.getLatitude(), eLat = expected.getLatitude(), aLon = actual.getLongitude(), eLon = expected.getLongitude(); + int aZoom = actual.getZoom(), eZoom = expected.getZoom(); + String aName = actual.getName(), eName = expected.getName(); + if (eName != null) { + if (!aName.equals(eName)) { + throw new RuntimeException("Point name\\capture is not equal; actual=" + aName + ", expected=" + + eName); + } + } + if (((int)eLat) != ((int)aLat)) { + throw new RuntimeException("Latitude is not equal; actual=" + aLat + ", expected=" + eLat); + } + if (((int)eLon) != ((int)aLon)) { throw new RuntimeException("Longitude is not equal; actual=" + aLon + ", expected=" + eLon); } if (eZoom != aZoom) { @@ -453,10 +515,12 @@ public class GeoPointParserUtil { Pattern p; Matcher matcher; String path = uri.getPath(); - if ("go".equals(path)) { // short URL form - // TODO decode OSM short URL and delete this: - p = Pattern.compile("(?:.*)(?:map=)(\\d{1,2})/([+-]?\\d+(?:\\.\\d+)?)/([+-]?\\d+(?:\\.\\d+)?)(?:.*)"); - matcher = p.matcher(schemeSpecific); + if (path != null && path.startsWith("/go/")) { // short URL form + p = Pattern.compile("^/go/([A-Za-z0-9_@~]+-*)(?:.*)"); + matcher = p.matcher(uri.getPath()); + if (matcher.matches()) { + return MapUtils.decodeShortLinkString(matcher.group(1)); + } } else { // data in the query and/or feature strings String lat = "0"; String lon = "0"; From 9bb03894a57cc80c2f9ad935ba007d2c406abd2c Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 13 Jan 2015 12:09:14 +0100 Subject: [PATCH 14/14] generate OpenStreetMap shortlinks using current char set (~ instead of @) OpenStreetMap has changed the shortlink charset to use ~ instead of @ to be support services like Twitter where @ has meaning. OpenStreetMap still will parse the old format, but only generates new shortlinks using "~". This commit changes OsmAnd to have the same behavior. References: https://wiki.openstreetmap.org/wiki/Shortlink#Code_for_encoding_.26_decoding https://github.com/openstreetmap/openstreetmap-website/blob/e84b2bd22f7c92fb7a128a91c999f86e350bf04d/app/assets/javascripts/application.js#L188 ---------------- OsmAnd-java/src/net/osmand/util/MapUtils.java ---------------- --- .../net/osmand/util/GeoPointParserUtil.java | 20 +++++++++++++++++++ OsmAnd-java/src/net/osmand/util/MapUtils.java | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java index c170c8c4f6..322cf18932 100644 --- a/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/net/osmand/util/GeoPointParserUtil.java @@ -172,6 +172,22 @@ public class GeoPointParserUtil { actual = GeoPointParserUtil.parse(url); assertApproximateGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); + // http://osm.org/go/TyFYuF6P~~-?m // current shortlink format with "~" + // https://www.openstreetmap.org/?mlat=34.993933029174805&mlon=-106.61568069458008#map=15/34.99393/-106.61568 + z = 20; + url = "http://osm.org/go/TyFYuF6P~~-?m"; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertApproximateGeoPoint(actual, new GeoParsedPoint(longLat, longLon, z)); + + // http://osm.org/go/TyFYuF6P@@--?m= // old, deprecated shortlink format with "@" + // https://www.openstreetmap.org/?mlat=34.993933029174805&mlon=-106.61568069458008#map=15/34.99393/-106.61568 + z = 21; + url = "http://osm.org/go/TyFYuF6P@@--?m="; + System.out.println("url: " + url); + actual = GeoPointParserUtil.parse(url); + assertApproximateGeoPoint(actual, new GeoParsedPoint(longLat, longLon, z)); + // http://openstreetmap.de/zoom=11&lat=34&lon=-106 z = 11; url = "http://openstreetmap.de/zoom=" + z + "&lat=" + ilat + "&lon=" + ilon; @@ -355,6 +371,10 @@ public class GeoPointParserUtil { "http://osm.org/go/0LQ127-?m", "http://osm.org/go/0EEQjE==", "http://osm.org/go/0EEQjEEb", + "http://osm.org/go/0EE~jEEb", + "http://osm.org/go/0EE@jEEb", + "http://osm.org/go/~~~~", + "http://osm.org/go/@@@@", "https://www.openstreetmap.org/#map=0/0/0", "https://www.openstreetmap.org/#map=0/180/180", "https://www.openstreetmap.org/#map=0/-180/-180", diff --git a/OsmAnd-java/src/net/osmand/util/MapUtils.java b/OsmAnd-java/src/net/osmand/util/MapUtils.java index 38d2f179eb..f9855eebd3 100644 --- a/OsmAnd-java/src/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/net/osmand/util/MapUtils.java @@ -35,7 +35,7 @@ public class MapUtils { 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '@' + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '~' }; public static double getDistance(LatLon l, double latitude, double longitude){ @@ -308,6 +308,8 @@ public class MapUtils { } public static GeoParsedPoint decodeShortLinkString(String s) { + // convert old shortlink format to current one + s = s.replaceAll("@", "~"); int i = 0; long x = 0; long y = 0;