11package org .microg .nlp .backend .nominatim ;
22
3+ import android .content .Context ;
34import android .content .pm .PackageManager ;
45import android .location .Address ;
6+ import android .net .Uri ;
57import android .os .Build ;
68import android .util .Log ;
79
10+ import org .json .JSONArray ;
811import org .json .JSONException ;
912import org .json .JSONObject ;
1013import org .microg .nlp .api .GeocoderBackendService ;
1821import java .util .ArrayList ;
1922import java .util .List ;
2023import java .util .Locale ;
24+ import java .util .concurrent .atomic .AtomicBoolean ;
2125
2226public 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