1
1
package org .microg .nlp .backend .nominatim ;
2
2
3
+ import android .content .Context ;
3
4
import android .content .pm .PackageManager ;
4
5
import android .location .Address ;
6
+ import android .net .Uri ;
5
7
import android .os .Build ;
6
8
import android .util .Log ;
7
9
10
+ import org .json .JSONArray ;
8
11
import org .json .JSONException ;
9
12
import org .json .JSONObject ;
10
13
import org .microg .nlp .api .GeocoderBackendService ;
18
21
import java .util .ArrayList ;
19
22
import java .util .List ;
20
23
import java .util .Locale ;
24
+ import java .util .concurrent .atomic .AtomicBoolean ;
21
25
22
26
public class BackendService extends GeocoderBackendService {
23
- private static final String TAG = BackendService . class . getName () ;
27
+ private static final String TAG = "NominatimGeocoderBackend" ;
24
28
private static final String SERVICE_URL_MAPQUEST = "http://open.mapquestapi.com/nominatim/v1/" ;
25
29
private static final String SERVICE_URL_OSM = " http://nominatim.openstreetmap.org/" ;
26
30
private static final String REVERSE_GEOCODE_URL =
27
31
"%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" ;
28
37
private static final String WIRE_LATITUDE = "lat" ;
29
38
private static final String WIRE_LONGITUDE = "lon" ;
30
39
private static final String WIRE_ADDRESS = "address" ;
@@ -45,51 +54,20 @@ protected List<Address> getFromLocation(double latitude, double longitude, int m
45
54
String url = String .format (Locale .US , REVERSE_GEOCODE_URL , SERVICE_URL_MAPQUEST ,
46
55
locale .split ("_" )[0 ], latitude , longitude );
47
56
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 ());
53
59
Address address = parseResponse (localeFromLocaleString (locale ), result );
54
60
if (address != null ) {
55
- List <Address > addresses = new ArrayList <Address >();
61
+ List <Address > addresses = new ArrayList <>();
56
62
addresses .add (address );
57
63
return addresses ;
58
64
}
59
- } catch (IOException | JSONException e ) {
65
+ } catch (Exception e ) {
60
66
Log .w (TAG , e );
61
67
}
62
68
return null ;
63
69
}
64
70
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
-
93
71
private static Locale localeFromLocaleString (String localeString ) {
94
72
String [] split = localeString .split ("_" );
95
73
if (split .length == 1 ) {
@@ -106,6 +84,31 @@ private static Locale localeFromLocaleString(String localeString) {
106
84
protected List <Address > getFromLocationName (String locationName , int maxResults ,
107
85
double lowerLeftLatitude , double lowerLeftLongitude , double upperRightLatitude ,
108
86
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
+ }
109
112
return null ;
110
113
}
111
114
@@ -160,4 +163,88 @@ private Address parseResponse(Locale locale, JSONObject result) throws JSONExcep
160
163
161
164
return address ;
162
165
}
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
+ }
163
250
}
0 commit comments