Skip to content

Commit c9583d8

Browse files
committed
Add support for getFromLocationName
1 parent 9e620c8 commit c9583d8

File tree

2 files changed

+147
-60
lines changed

2 files changed

+147
-60
lines changed

AndroidManifest.xml

+24-24
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
android:versionName="1.0.0"
4-
android:versionCode="1000"
5-
package="org.microg.nlp.backend.nominatim">
3+
android:versionName="1.1.0"
4+
android:versionCode="1100"
5+
package="org.microg.nlp.backend.nominatim">
66

7-
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
8-
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
9-
<uses-permission android:name="android.permission.INTERNET" />
10-
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
11-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
12-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
8+
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
9+
<uses-permission android:name="android.permission.INTERNET"/>
10+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
11+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
12+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1313

14-
<uses-sdk
15-
android:minSdkVersion="9"
16-
android:targetSdkVersion="19" />
17-
<application
18-
android:allowBackup="false"
19-
android:icon="@drawable/ic_launcher"
20-
android:label="@string/app_name">
21-
<service
22-
android:name=".BackendService"
23-
android:label="MapQuest Nominatim Backend">
24-
<intent-filter>
25-
<action android:name="org.microg.nlp.GEOCODER_BACKEND" />
26-
</intent-filter>
27-
</service>
28-
</application>
14+
<uses-sdk
15+
android:minSdkVersion="9"
16+
android:targetSdkVersion="21"/>
17+
<application
18+
android:allowBackup="false"
19+
android:icon="@drawable/ic_launcher"
20+
android:label="@string/app_name">
21+
<service
22+
android:name=".BackendService"
23+
android:label="Nominatim Backend">
24+
<intent-filter>
25+
<action android:name="org.microg.nlp.GEOCODER_BACKEND"/>
26+
</intent-filter>
27+
</service>
28+
</application>
2929
</manifest>

src/org/microg/nlp/backend/nominatim/BackendService.java

+123-36
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package org.microg.nlp.backend.nominatim;
22

3+
import android.content.Context;
34
import android.content.pm.PackageManager;
45
import android.location.Address;
6+
import android.net.Uri;
57
import android.os.Build;
68
import android.util.Log;
79

10+
import org.json.JSONArray;
811
import org.json.JSONException;
912
import org.json.JSONObject;
1013
import org.microg.nlp.api.GeocoderBackendService;
@@ -18,13 +21,19 @@
1821
import java.util.ArrayList;
1922
import java.util.List;
2023
import java.util.Locale;
24+
import java.util.concurrent.atomic.AtomicBoolean;
2125

2226
public class BackendService extends GeocoderBackendService {
23-
private static final String TAG = BackendService.class.getName();
27+
private static final String TAG = "NominatimGeocoderBackend";
2428
private static final String SERVICE_URL_MAPQUEST = "http://open.mapquestapi.com/nominatim/v1/";
2529
private static final String SERVICE_URL_OSM = " http://nominatim.openstreetmap.org/";
2630
private static final String REVERSE_GEOCODE_URL =
2731
"%sreverse?format=json&accept-language=%s&lat=%f&lon=%f";
32+
private static final String SEARCH_GEOCODE_URL =
33+
"%ssearch?format=json&accept-language=%s&addressdetails=1&bounded=1&q=%s&limit=%d";
34+
private static final String SEARCH_GEOCODE_WITH_BOX_URL =
35+
"%ssearch?format=json&accept-language=%s&addressdetails=1&bounded=1&q=%s&limit=%d" +
36+
"&viewbox=%f,%f,%f,%f";
2837
private static final String WIRE_LATITUDE = "lat";
2938
private static final String WIRE_LONGITUDE = "lon";
3039
private static final String WIRE_ADDRESS = "address";
@@ -45,51 +54,20 @@ protected List<Address> getFromLocation(double latitude, double longitude, int m
4554
String url = String.format(Locale.US, REVERSE_GEOCODE_URL, SERVICE_URL_MAPQUEST,
4655
locale.split("_")[0], latitude, longitude);
4756
try {
48-
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
49-
setUserAgentOnConnection(connection);
50-
connection.setDoInput(true);
51-
InputStream inputStream = connection.getInputStream();
52-
JSONObject result = new JSONObject(new String(readStreamToEnd(inputStream)));
57+
JSONObject result = new JSONObject(new AsyncGetRequest(this,
58+
url).asyncStart().retrieveString());
5359
Address address = parseResponse(localeFromLocaleString(locale), result);
5460
if (address != null) {
55-
List<Address> addresses = new ArrayList<Address>();
61+
List<Address> addresses = new ArrayList<>();
5662
addresses.add(address);
5763
return addresses;
5864
}
59-
} catch (IOException | JSONException e) {
65+
} catch (Exception e) {
6066
Log.w(TAG, e);
6167
}
6268
return null;
6369
}
6470

65-
public static byte[] readStreamToEnd(InputStream is) throws IOException {
66-
ByteArrayOutputStream bos = new ByteArrayOutputStream();
67-
if (is != null) {
68-
byte[] buff = new byte[1024];
69-
while (true) {
70-
int nb = is.read(buff);
71-
if (nb < 0) {
72-
break;
73-
}
74-
bos.write(buff, 0, nb);
75-
}
76-
is.close();
77-
}
78-
return bos.toByteArray();
79-
}
80-
81-
public void setUserAgentOnConnection(URLConnection connection) {
82-
try {
83-
connection.setRequestProperty("User-Agent",
84-
String.format("UnifiedNlp/%s (Linux; Android %s)",
85-
getPackageManager().getPackageInfo(getPackageName(), 0).versionName,
86-
Build.VERSION.RELEASE));
87-
} catch (PackageManager.NameNotFoundException e) {
88-
connection.setRequestProperty("User-Agent",
89-
String.format("UnifiedNlp (Linux; Android %s)", Build.VERSION.RELEASE));
90-
}
91-
}
92-
9371
private static Locale localeFromLocaleString(String localeString) {
9472
String[] split = localeString.split("_");
9573
if (split.length == 1) {
@@ -106,6 +84,31 @@ private static Locale localeFromLocaleString(String localeString) {
10684
protected List<Address> getFromLocationName(String locationName, int maxResults,
10785
double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude,
10886
double upperRightLongitude, String locale) {
87+
String query = Uri.encode(locationName);
88+
String url;
89+
if (lowerLeftLatitude == 0 && lowerLeftLongitude == 0 && upperRightLatitude == 0 &&
90+
upperRightLongitude == 0) {
91+
url = String.format(Locale.US, SEARCH_GEOCODE_URL, SERVICE_URL_MAPQUEST,
92+
locale.split("_")[0], query, maxResults);
93+
} else {
94+
url = String.format(Locale.US, SEARCH_GEOCODE_WITH_BOX_URL, SERVICE_URL_MAPQUEST,
95+
locale.split("_")[0], query, maxResults, lowerLeftLongitude,
96+
upperRightLatitude, upperRightLongitude, lowerLeftLatitude);
97+
}
98+
try {
99+
JSONArray result = new JSONArray(new AsyncGetRequest(this,
100+
url).asyncStart().retrieveString());
101+
List<Address> addresses = new ArrayList<>();
102+
for (int i = 0; i < result.length(); i++) {
103+
Address address = parseResponse(localeFromLocaleString(locale),
104+
result.getJSONObject(i));
105+
if (address != null)
106+
addresses.add(address);
107+
}
108+
if (!addresses.isEmpty()) return addresses;
109+
} catch (Exception e) {
110+
Log.w(TAG, e);
111+
}
109112
return null;
110113
}
111114

@@ -160,4 +163,88 @@ private Address parseResponse(Locale locale, JSONObject result) throws JSONExcep
160163

161164
return address;
162165
}
166+
167+
private class AsyncGetRequest extends Thread {
168+
public static final String USER_AGENT = "User-Agent";
169+
public static final String USER_AGENT_TEMPLATE = "UnifiedNlp/%s (Linux; Android %s)";
170+
private final AtomicBoolean done = new AtomicBoolean(false);
171+
private final Context context;
172+
private final String url;
173+
private byte[] result;
174+
175+
private AsyncGetRequest(Context context, String url) {
176+
this.context = context;
177+
this.url = url;
178+
}
179+
180+
@Override
181+
public void run() {
182+
synchronized (done) {
183+
try {
184+
Log.d(TAG, "Requesting " + url);
185+
HttpURLConnection connection = (HttpURLConnection) new URL(url)
186+
.openConnection();
187+
setUserAgentOnConnection(connection);
188+
connection.setDoInput(true);
189+
InputStream inputStream = connection.getInputStream();
190+
result = readStreamToEnd(inputStream);
191+
} catch (Exception e) {
192+
Log.w(TAG, e);
193+
}
194+
done.set(true);
195+
done.notifyAll();
196+
}
197+
}
198+
199+
public AsyncGetRequest asyncStart() {
200+
start();
201+
return this;
202+
}
203+
204+
public byte[] retrieveAllBytes() {
205+
if (!done.get()) {
206+
synchronized (done) {
207+
while (!done.get()) {
208+
try {
209+
done.wait();
210+
} catch (InterruptedException e) {
211+
break;
212+
}
213+
}
214+
}
215+
}
216+
return result;
217+
}
218+
219+
public String retrieveString() {
220+
return new String(retrieveAllBytes());
221+
}
222+
223+
private void setUserAgentOnConnection(URLConnection connection) {
224+
try {
225+
connection.setRequestProperty(USER_AGENT, String.format(USER_AGENT_TEMPLATE,
226+
context.getPackageManager().getPackageInfo(context.getPackageName(),
227+
0).versionName, Build.VERSION.RELEASE));
228+
} catch (PackageManager.NameNotFoundException e) {
229+
connection.setRequestProperty(USER_AGENT, String.format(USER_AGENT_TEMPLATE, 0,
230+
Build.VERSION.RELEASE));
231+
}
232+
}
233+
234+
private byte[] readStreamToEnd(InputStream is) throws IOException {
235+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
236+
if (is != null) {
237+
byte[] buff = new byte[1024];
238+
while (true) {
239+
int nb = is.read(buff);
240+
if (nb < 0) {
241+
break;
242+
}
243+
bos.write(buff, 0, nb);
244+
}
245+
is.close();
246+
}
247+
return bos.toByteArray();
248+
}
249+
}
163250
}

0 commit comments

Comments
 (0)