diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 17d4d16..2d707c7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,29 +1,29 @@
+ android:versionName="1.1.0"
+ android:versionCode="1100"
+ package="org.microg.nlp.backend.nominatim">
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/org/microg/nlp/backend/nominatim/BackendService.java b/src/org/microg/nlp/backend/nominatim/BackendService.java
index 5f85cd2..0a4ec07 100644
--- a/src/org/microg/nlp/backend/nominatim/BackendService.java
+++ b/src/org/microg/nlp/backend/nominatim/BackendService.java
@@ -1,10 +1,13 @@
package org.microg.nlp.backend.nominatim;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
+import android.net.Uri;
import android.os.Build;
import android.util.Log;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.microg.nlp.api.GeocoderBackendService;
@@ -18,13 +21,19 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.atomic.AtomicBoolean;
public class BackendService extends GeocoderBackendService {
- private static final String TAG = BackendService.class.getName();
+ private static final String TAG = "NominatimGeocoderBackend";
private static final String SERVICE_URL_MAPQUEST = "http://open.mapquestapi.com/nominatim/v1/";
private static final String SERVICE_URL_OSM = " http://nominatim.openstreetmap.org/";
private static final String REVERSE_GEOCODE_URL =
"%sreverse?format=json&accept-language=%s&lat=%f&lon=%f";
+ private static final String SEARCH_GEOCODE_URL =
+ "%ssearch?format=json&accept-language=%s&addressdetails=1&bounded=1&q=%s&limit=%d";
+ private static final String SEARCH_GEOCODE_WITH_BOX_URL =
+ "%ssearch?format=json&accept-language=%s&addressdetails=1&bounded=1&q=%s&limit=%d" +
+ "&viewbox=%f,%f,%f,%f";
private static final String WIRE_LATITUDE = "lat";
private static final String WIRE_LONGITUDE = "lon";
private static final String WIRE_ADDRESS = "address";
@@ -45,51 +54,20 @@ protected List
getFromLocation(double latitude, double longitude, int m
String url = String.format(Locale.US, REVERSE_GEOCODE_URL, SERVICE_URL_MAPQUEST,
locale.split("_")[0], latitude, longitude);
try {
- HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
- setUserAgentOnConnection(connection);
- connection.setDoInput(true);
- InputStream inputStream = connection.getInputStream();
- JSONObject result = new JSONObject(new String(readStreamToEnd(inputStream)));
+ JSONObject result = new JSONObject(new AsyncGetRequest(this,
+ url).asyncStart().retrieveString());
Address address = parseResponse(localeFromLocaleString(locale), result);
if (address != null) {
- List addresses = new ArrayList();
+ List addresses = new ArrayList<>();
addresses.add(address);
return addresses;
}
- } catch (IOException | JSONException e) {
+ } catch (Exception e) {
Log.w(TAG, e);
}
return null;
}
- public static byte[] readStreamToEnd(InputStream is) throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- if (is != null) {
- byte[] buff = new byte[1024];
- while (true) {
- int nb = is.read(buff);
- if (nb < 0) {
- break;
- }
- bos.write(buff, 0, nb);
- }
- is.close();
- }
- return bos.toByteArray();
- }
-
- public void setUserAgentOnConnection(URLConnection connection) {
- try {
- connection.setRequestProperty("User-Agent",
- String.format("UnifiedNlp/%s (Linux; Android %s)",
- getPackageManager().getPackageInfo(getPackageName(), 0).versionName,
- Build.VERSION.RELEASE));
- } catch (PackageManager.NameNotFoundException e) {
- connection.setRequestProperty("User-Agent",
- String.format("UnifiedNlp (Linux; Android %s)", Build.VERSION.RELEASE));
- }
- }
-
private static Locale localeFromLocaleString(String localeString) {
String[] split = localeString.split("_");
if (split.length == 1) {
@@ -106,6 +84,31 @@ private static Locale localeFromLocaleString(String localeString) {
protected List getFromLocationName(String locationName, int maxResults,
double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude,
double upperRightLongitude, String locale) {
+ String query = Uri.encode(locationName);
+ String url;
+ if (lowerLeftLatitude == 0 && lowerLeftLongitude == 0 && upperRightLatitude == 0 &&
+ upperRightLongitude == 0) {
+ url = String.format(Locale.US, SEARCH_GEOCODE_URL, SERVICE_URL_MAPQUEST,
+ locale.split("_")[0], query, maxResults);
+ } else {
+ url = String.format(Locale.US, SEARCH_GEOCODE_WITH_BOX_URL, SERVICE_URL_MAPQUEST,
+ locale.split("_")[0], query, maxResults, lowerLeftLongitude,
+ upperRightLatitude, upperRightLongitude, lowerLeftLatitude);
+ }
+ try {
+ JSONArray result = new JSONArray(new AsyncGetRequest(this,
+ url).asyncStart().retrieveString());
+ List addresses = new ArrayList<>();
+ for (int i = 0; i < result.length(); i++) {
+ Address address = parseResponse(localeFromLocaleString(locale),
+ result.getJSONObject(i));
+ if (address != null)
+ addresses.add(address);
+ }
+ if (!addresses.isEmpty()) return addresses;
+ } catch (Exception e) {
+ Log.w(TAG, e);
+ }
return null;
}
@@ -160,4 +163,88 @@ private Address parseResponse(Locale locale, JSONObject result) throws JSONExcep
return address;
}
+
+ private class AsyncGetRequest extends Thread {
+ public static final String USER_AGENT = "User-Agent";
+ public static final String USER_AGENT_TEMPLATE = "UnifiedNlp/%s (Linux; Android %s)";
+ private final AtomicBoolean done = new AtomicBoolean(false);
+ private final Context context;
+ private final String url;
+ private byte[] result;
+
+ private AsyncGetRequest(Context context, String url) {
+ this.context = context;
+ this.url = url;
+ }
+
+ @Override
+ public void run() {
+ synchronized (done) {
+ try {
+ Log.d(TAG, "Requesting " + url);
+ HttpURLConnection connection = (HttpURLConnection) new URL(url)
+ .openConnection();
+ setUserAgentOnConnection(connection);
+ connection.setDoInput(true);
+ InputStream inputStream = connection.getInputStream();
+ result = readStreamToEnd(inputStream);
+ } catch (Exception e) {
+ Log.w(TAG, e);
+ }
+ done.set(true);
+ done.notifyAll();
+ }
+ }
+
+ public AsyncGetRequest asyncStart() {
+ start();
+ return this;
+ }
+
+ public byte[] retrieveAllBytes() {
+ if (!done.get()) {
+ synchronized (done) {
+ while (!done.get()) {
+ try {
+ done.wait();
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public String retrieveString() {
+ return new String(retrieveAllBytes());
+ }
+
+ private void setUserAgentOnConnection(URLConnection connection) {
+ try {
+ connection.setRequestProperty(USER_AGENT, String.format(USER_AGENT_TEMPLATE,
+ context.getPackageManager().getPackageInfo(context.getPackageName(),
+ 0).versionName, Build.VERSION.RELEASE));
+ } catch (PackageManager.NameNotFoundException e) {
+ connection.setRequestProperty(USER_AGENT, String.format(USER_AGENT_TEMPLATE, 0,
+ Build.VERSION.RELEASE));
+ }
+ }
+
+ private byte[] readStreamToEnd(InputStream is) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ if (is != null) {
+ byte[] buff = new byte[1024];
+ while (true) {
+ int nb = is.read(buff);
+ if (nb < 0) {
+ break;
+ }
+ bos.write(buff, 0, nb);
+ }
+ is.close();
+ }
+ return bos.toByteArray();
+ }
+ }
}