From 408bcf32d480e4117920a7a8921f514872df1d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Mart=C3=ADnez?= Date: Mon, 12 Jun 2017 14:16:54 +0200 Subject: [PATCH 1/6] Request for address to Google API --- .../geocoder/api/AddressBuilderShould.java | 85 +++++++++++++++++++ .../leku/geocoder/GeocoderAPIInteractor.java | 61 +++++++++++++ .../leku/geocoder/api/AddressBuilder.java | 83 ++++++++++++++++++ .../leku/geocoder/api/NetworkClient.java | 63 ++++++++++++++ .../leku/geocoder/api/NetworkException.java | 18 ++++ 5 files changed, 310 insertions(+) create mode 100644 leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java create mode 100644 leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java create mode 100644 leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java create mode 100644 leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkClient.java create mode 100644 leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkException.java diff --git a/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java b/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java new file mode 100644 index 00000000..bbda7220 --- /dev/null +++ b/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java @@ -0,0 +1,85 @@ +package com.schibsted.leku.geocoder.api; + +import android.location.Address; +import android.support.annotation.NonNull; +import com.schibstedspain.leku.geocoder.api.AddressBuilder; +import java.util.List; +import org.json.JSONException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.junit.MockitoRule; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static org.mockito.junit.MockitoJUnit.rule; + +public class AddressBuilderShould { + + @Rule public MockitoRule mockitoRule = rule(); + + private AddressBuilder addressBuilder; + + @Before + public void setUp() { + addressBuilder = new AddressBuilder(); + } + + @Test + public void returnExpectedAddress_WhenJsonProvided() throws JSONException { + String json = getJson(); + + List
addresses = addressBuilder.parseResult(json); + + assertEquals("Barcelona", addresses.get(0).getLocality()); + assertEquals("Carrer del Comte d'Urgell, 102", addresses.get(0).getAddressLine(0)); + assertEquals("08011", addresses.get(0).getPostalCode()); + assertTrue(Double.valueOf(41.3838035).equals(addresses.get(0).getLatitude())); + assertTrue(Double.valueOf(2.1568617).equals(addresses.get(0).getLongitude())); + + } + + @Test + public void returnExpectedAddress_WhenJsonWithOnlyCityProvided() throws JSONException { + String json = getJsonForOnlyCity(); + + List
addresses = addressBuilder.parseResult(json); + + assertEquals("Barcelona", addresses.get(0).getLocality()); + assertEquals("", addresses.get(0).getAddressLine(0)); + assertEquals("", addresses.get(0).getPostalCode()); + assertTrue(Double.valueOf(41.3850639).equals(addresses.get(0).getLatitude())); + assertTrue(Double.valueOf(2.1734035).equals(addresses.get(0).getLongitude())); + + } + + @NonNull + private String getJson() { + return "{\"results\": [{\"address_components\": [{\"long_name\": \"102\",\"short_name\": \"102\",\"types\": " + + "[ \"street_number\"]},{\"long_name\": \"Carrer del Comte d'Urgell\",\"short_name\": \"Carrer del Comte d'Urgell\",\"types\": " + + "[ \"route\"]},{\"long_name\": \"Barcelona\",\"short_name\": \"Barcelona\",\"types\": [ \"locality\", \"political\"]}," + + "{\"long_name\": \"Barcelona\",\"short_name\": \"Barcelona\",\"types\": [ \"administrative_area_level_2\", \"political\"]}," + + "{\"long_name\": \"Catalunya\",\"short_name\": \"CT\",\"types\": [ \"administrative_area_level_1\", \"political\"]}," + + "{\"long_name\": \"Spain\",\"short_name\": \"ES\",\"types\": [ \"country\", \"political\"]},{\"long_name\": \"08011\"," + + "\"short_name\": \"08011\",\"types\": [ \"postal_code\"]}],\"formatted_address\"" + + ": \"Carrer del Comte d'Urgell, 102, 08011 Barcelona, Spain\",\"geometry\": {\"bounds\": {\"northeast\": " + + "{ \"lat\": 41.3839416, \"lng\": 2.1570442},\"southwest\": { \"lat\": 41.3836653, \"lng\": 2.1566792}},\"location\": " + + "{\"lat\": 41.3838035,\"lng\": 2.1568617},\"location_type\": \"ROOFTOP\",\"viewport\": {\"northeast\": " + + "{ \"lat\": 41.3851524302915, \"lng\": 2.158210680291502},\"southwest\": { \"lat\": 41.3824544697085, " + + "\"lng\": 2.155512719708498}}},\"partial_match\": true,\"place_id\": \"ChIJdehx-YiipBIR8hitzOckUuo\",\"types\": [\"premise\"] } " + + "], \"status\": \"OK\"}"; + } + + @NonNull + private String getJsonForOnlyCity() { + return "{\"results\": [{\"address_components\": [{\"long_name\": \"Barcelona\",\"short_name\": \"Barcelona\",\"types\": " + + "[\"locality\",\"political\"]},{\"long_name\": \"Barcelona\",\"short_name\": \"Barcelona\",\"types\": " + + "[\"administrative_area_level_2\",\"political\"]},{\"long_name\": \"Catalonia\",\"short_name\": \"CT\",\"types\": " + + "[\"administrative_area_level_1\",\"political\"]},{\"long_name\": \"Spain\",\"short_name\": \"ES\",\"types\": " + + "[\"country\",\"political\"]}],\"formatted_address\": \"Barcelona, Spain\",\"geometry\": {\"bounds\": {\"northeast\": " + + "{\"lat\": 41.4695761,\"lng\": 2.2280099},\"southwest\": {\"lat\": 41.320004,\"lng\": 2.0695258}},\"location\":" + + " {\"lat\": 41.3850639,\"lng\": 2.1734035},\"location_type\": \"APPROXIMATE\",\"viewport\": {\"northeast\": " + + "{\"lat\": 41.4695761,\"lng\": 2.2280099},\"southwest\": {\"lat\": 41.320004,\"lng\": 2.0695258}}},\"place_id\": " + + "\"ChIJ5TCOcRaYpBIRCmZHTz37sEQ\",\"types\": [\"locality\",\"political\"]}],\"status\": \"OK\"}"; + } +} \ No newline at end of file diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java new file mode 100644 index 00000000..4f514819 --- /dev/null +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java @@ -0,0 +1,61 @@ +package com.schibstedspain.leku.geocoder; + +import android.location.Address; +import android.location.Geocoder; +import com.google.android.gms.maps.model.LatLng; +import com.schibstedspain.leku.geocoder.api.NetworkClient; +import java.io.IOException; +import java.util.List; +import rx.Observable; + +public class GeocoderAPIInteractor implements GeocoderInteractorInterface { + + private final static int MAX_RESULTS = 5; + private final String apiKey; + private final NetworkClient networkClient; + private final Geocoder geocoder; + + public GeocoderAPIInteractor(String ApiKey, NetworkClient networkClient) { + apiKey = ApiKey; + this.networkClient = networkClient; + geocoder = new Geocoder(null); + } + + @Override + public Observable> getFromLocationName(String query) { + return Observable.create(subscriber -> { + try { + subscriber.onNext(geocoder.getFromLocationName(query, MAX_RESULTS)); + subscriber.onCompleted(); + } catch (IOException e) { + subscriber.onError(e); + } + }); + } + + @Override + public Observable> getFromLocationName(String query, LatLng lowerLeft, + LatLng upperRight) { + return Observable.create(subscriber -> { + try { + subscriber.onNext(geocoder.getFromLocationName(query, MAX_RESULTS, lowerLeft.latitude, + lowerLeft.longitude, upperRight.latitude, upperRight.longitude)); + subscriber.onCompleted(); + } catch (IOException e) { + subscriber.onError(e); + } + }); + } + + @Override + public Observable> getFromLocation(double latitude, double longitude) { + return Observable.create(subscriber -> { + try { + subscriber.onNext(geocoder.getFromLocation(latitude, longitude, MAX_RESULTS)); + subscriber.onCompleted(); + } catch (IOException e) { + subscriber.onError(e); + } + }); + } +} diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java new file mode 100644 index 00000000..4e24a411 --- /dev/null +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java @@ -0,0 +1,83 @@ +package com.schibstedspain.leku.geocoder.api; + +import android.location.Address; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class AddressBuilder { + + public List
parseResult(String json) throws JSONException { + List
addresses = new ArrayList<>(); + JSONObject root = new JSONObject(json); + JSONArray results = root.getJSONArray("results"); + for(int i = 0; i components = getAddressComponents(jsonObject.getJSONArray("address_components")); + + + String postalCode = ""; + String city = ""; + String number = ""; + String street = ""; + for (AddressComponent component : components) { + if (component.types.contains("postal_code")) { + postalCode = component.name; + } + if (component.types.contains("locality")) { + city = component.name; + } + if (component.types.contains("street_number")) { + number = component.name; + } + if (component.types.contains("route")) { + street = component.name; + } + } + StringBuilder fullAddress = new StringBuilder(); + fullAddress.append(street); + if (!street.isEmpty() && !number.isEmpty()) { + fullAddress.append(", ").append(number); + } + Address address = new Address(Locale.getDefault()); + address.setLatitude(latitude); + address.setLongitude(longitude); + address.setPostalCode(postalCode); + address.setAddressLine(0, fullAddress.toString()); + address.setLocality(city); + return address; + } + + List getAddressComponents(JSONArray jsonComponents) throws JSONException { + List components = new ArrayList<>(); + for (int i = 0;i(); + JSONArray jsonTypes = jsonComponent.getJSONArray("types"); + for (int j = 0; j < jsonTypes.length(); j++) { + component.types.add(jsonTypes.getString(j)); + } + components.add(component); + } + return components; + } + + class AddressComponent { + String name; + List types; + } +} diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkClient.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkClient.java new file mode 100644 index 00000000..86d763a3 --- /dev/null +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkClient.java @@ -0,0 +1,63 @@ +package com.schibstedspain.leku.geocoder.api; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.net.ssl.HttpsURLConnection; + +public class NetworkClient { + private static final int REPONSE_MAX_LENGTH = 1024; + private static final int READ_TIMEOUT = 3000; + private static final int CONNECT_TIMEOUT = 3000; + + public String requestFromLocationName(String request) { + String result = null; + InputStream stream = null; + HttpsURLConnection connection = null; + try { + URL url = new URL(request); + connection = (HttpsURLConnection) url.openConnection(); + connection.setReadTimeout(READ_TIMEOUT); + connection.setConnectTimeout(CONNECT_TIMEOUT); + connection.setRequestMethod("GET"); + connection.setDoInput(true); + connection.connect(); + int responseCode = connection.getResponseCode(); + if (responseCode != HttpsURLConnection.HTTP_OK) { + throw new NetworkException("HTTP error code: " + responseCode); + } + stream = connection.getInputStream(); + if (stream != null) { + result = readStream(stream, REPONSE_MAX_LENGTH); + } + } catch (IOException ioException) { + throw new NetworkException(ioException); + } finally { + + if (stream != null) { + try { + stream.close(); + } catch (IOException ioException) { + throw new NetworkException(ioException); + } + } + if (connection != null) { + connection.disconnect(); + } + } + return result; + } + + + private String readStream(InputStream stream, int maxLength) throws IOException { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[maxLength]; + int length; + while ((length = stream.read(buffer)) != -1) { + result.write(buffer, 0, length); + } + return result.toString("UTF-8"); + } + +} diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkException.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkException.java new file mode 100644 index 00000000..7b1d07f0 --- /dev/null +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/NetworkException.java @@ -0,0 +1,18 @@ +package com.schibstedspain.leku.geocoder.api; + +public class NetworkException extends RuntimeException { + public NetworkException() { + } + + public NetworkException(String message) { + super(message); + } + + public NetworkException(String message, Throwable cause) { + super(message, cause); + } + + public NetworkException(Throwable cause) { + super(cause); + } +} From 49778e4414b5ef231de62c87f19465ef9a41e06d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Mart=C3=ADnez?= Date: Mon, 12 Jun 2017 15:56:50 +0200 Subject: [PATCH 2/6] Presenter fallbacks on api interactor if android geocoder fails --- .../com/schibsted/mappicker/MainActivity.java | 1 + .../leku/LocationPickerActivity.java | 24 ++++++++- .../leku/geocoder/GeocoderAPIInteractor.java | 53 +++++++++++++++---- .../leku/geocoder/GeocoderPresenter.java | 14 +++-- .../leku/geocoder/api/AddressBuilder.java | 2 + 5 files changed, 79 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/schibsted/mappicker/MainActivity.java b/app/src/main/java/com/schibsted/mappicker/MainActivity.java index ebe4cb85..11ba38a2 100644 --- a/app/src/main/java/com/schibsted/mappicker/MainActivity.java +++ b/app/src/main/java/com/schibsted/mappicker/MainActivity.java @@ -36,6 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { public void onClick(View view) { Intent locationPickerIntent = new LocationPickerActivity.Builder() .withLocation(41.4036299, 2.1743558) + //.withGeolocApiKey("") //.withSearchZone("es_ES") //.shouldReturnOkOnBackPressed() //.withStreetHidden() diff --git a/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java b/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java index 8efd5e07..ba5c19e6 100644 --- a/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java +++ b/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java @@ -44,9 +44,12 @@ import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; +import com.schibstedspain.leku.geocoder.GeocoderAPIInteractor; import com.schibstedspain.leku.geocoder.GeocoderInteractor; import com.schibstedspain.leku.geocoder.GeocoderPresenter; import com.schibstedspain.leku.geocoder.GeocoderViewInterface; +import com.schibstedspain.leku.geocoder.api.AddressBuilder; +import com.schibstedspain.leku.geocoder.api.NetworkClient; import com.schibstedspain.leku.permissions.PermissionUtils; import com.schibstedspain.leku.tracker.TrackEvents; import java.util.ArrayList; @@ -77,6 +80,7 @@ public class LocationPickerActivity extends AppCompatActivity public static final String ENABLE_LOCATION_PERMISSION_REQUEST = "enable_location_permission_request"; public static final String POIS_LIST = "pois_list"; public static final String LEKU_POI = "leku_poi"; + private static final String GEOLOC_API_KEY = "geoloc_api_key"; private static final String LOCATION_KEY = "location_key"; private static final String LAST_LOCATION_QUERY = "last_location_query"; private static final String OPTIONS_HIDE_STREET = "street"; @@ -125,6 +129,8 @@ public class LocationPickerActivity extends AppCompatActivity private Map lekuPoisMarkersMap; private Marker currentMarker; private TextWatcher textWatcher; + private String apiKey; + private GeocoderAPIInteractor apiInteractor; @Override protected void onCreate(Bundle savedInstanceState) { @@ -154,8 +160,9 @@ protected void track(TrackEvents event) { private void setUpMainVariables() { Geocoder geocoder = new Geocoder(this, Locale.getDefault()); + apiInteractor = new GeocoderAPIInteractor(new NetworkClient(), new AddressBuilder()); geocoderPresenter = new GeocoderPresenter(new ReactiveLocationProvider(getApplicationContext()), - new GeocoderInteractor(geocoder)); + new GeocoderInteractor(geocoder), apiInteractor); geocoderPresenter.setUI(this); progressBar = (ProgressBar) findViewById(R.id.loading_progress_bar); progressBar.setVisibility(View.GONE); @@ -647,6 +654,9 @@ private void getSavedInstanceParams(Bundle savedInstanceState) { if (savedInstanceState.keySet().contains(LAYOUTS_TO_HIDE)) { setLayoutVisibilityFromBundle(savedInstanceState); } + if (savedInstanceState.keySet().contains(GEOLOC_API_KEY)) { + apiInteractor.setApiKey(savedInstanceState.getString(GEOLOC_API_KEY)); + } if (savedInstanceState.keySet().contains(SEARCH_ZONE)) { searchZone = savedInstanceState.getString(SEARCH_ZONE); } @@ -685,6 +695,9 @@ private void getTransitionBundleParams(Bundle transitionBundle) { if (transitionBundle.keySet().contains(POIS_LIST)) { poisList = transitionBundle.getParcelableArrayList(POIS_LIST); } + if (transitionBundle.keySet().contains(GEOLOC_API_KEY)) { + apiInteractor.setApiKey(transitionBundle.getString(GEOLOC_API_KEY)); + } } private void setLayoutVisibilityFromBundle(Bundle transitionBundle) { @@ -1057,6 +1070,7 @@ public static class Builder { private boolean enableSatelliteView = true; private boolean shouldReturnOkOnBackPressed = false; private List lekuPois; + private String geolocApiKey = null; public Builder() { } @@ -1110,6 +1124,11 @@ public Builder withPois(List pois) { return this; } + public Builder withGeolocApiKey(String apiKey) { + this.geolocApiKey = apiKey; + return this; + } + public Intent build(Context context) { Intent intent = new Intent(context, LocationPickerActivity.class); @@ -1130,6 +1149,9 @@ public Intent build(Context context) { if (lekuPois != null && !lekuPois.isEmpty()) { intent.putExtra(POIS_LIST, new ArrayList<>(lekuPois)); } + if (geolocApiKey != null) { + intent.putExtra(GEOLOC_API_KEY, geolocApiKey); + } return intent; } diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java index 4f514819..9512ce82 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java @@ -3,31 +3,48 @@ import android.location.Address; import android.location.Geocoder; import com.google.android.gms.maps.model.LatLng; +import com.schibstedspain.leku.geocoder.api.AddressBuilder; import com.schibstedspain.leku.geocoder.api.NetworkClient; import java.io.IOException; import java.util.List; +import java.util.Locale; +import org.json.JSONException; import rx.Observable; public class GeocoderAPIInteractor implements GeocoderInteractorInterface { private final static int MAX_RESULTS = 5; - private final String apiKey; + private static final String QUERY_REQUEST = "https://maps.googleapis.com/maps/api/geocode/json?address=%1$s&key=%2$s"; + private static final String QUERY_REQUEST_WITH_RECTANGLE + = "https://maps.googleapis.com/maps/api/geocode/json?address=%1$s&key=%2$s&bounds=%3$f,%4$f|%5$f,%6$f"; + private static final String QUERY_LAT_LONG = "https://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&key=%3$s"; + private String apiKey; private final NetworkClient networkClient; - private final Geocoder geocoder; + private final AddressBuilder addressBuilder; - public GeocoderAPIInteractor(String ApiKey, NetworkClient networkClient) { - apiKey = ApiKey; + public GeocoderAPIInteractor(NetworkClient networkClient, AddressBuilder addressBuilder) { this.networkClient = networkClient; - geocoder = new Geocoder(null); + this.addressBuilder = addressBuilder; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; } @Override public Observable> getFromLocationName(String query) { return Observable.create(subscriber -> { + if (apiKey == null) { + subscriber.onCompleted(); + return; + } try { - subscriber.onNext(geocoder.getFromLocationName(query, MAX_RESULTS)); + String result = networkClient.requestFromLocationName(String.format(Locale.ENGLISH, + QUERY_REQUEST, query.trim(), apiKey)); + List
addresses = addressBuilder.parseResult(result); + subscriber.onNext(addresses); subscriber.onCompleted(); - } catch (IOException e) { + } catch (JSONException e) { subscriber.onError(e); } }); @@ -37,11 +54,18 @@ public Observable> getFromLocationName(String query) { public Observable> getFromLocationName(String query, LatLng lowerLeft, LatLng upperRight) { return Observable.create(subscriber -> { + if (apiKey == null) { + subscriber.onCompleted(); + return; + } try { - subscriber.onNext(geocoder.getFromLocationName(query, MAX_RESULTS, lowerLeft.latitude, + String result = networkClient.requestFromLocationName(String.format(Locale.ENGLISH, + QUERY_REQUEST_WITH_RECTANGLE, query.trim(), apiKey, lowerLeft.latitude, lowerLeft.longitude, upperRight.latitude, upperRight.longitude)); + List
addresses = addressBuilder.parseResult(result); + subscriber.onNext(addresses); subscriber.onCompleted(); - } catch (IOException e) { + } catch (JSONException e) { subscriber.onError(e); } }); @@ -50,10 +74,17 @@ public Observable> getFromLocationName(String query, LatLng lowerL @Override public Observable> getFromLocation(double latitude, double longitude) { return Observable.create(subscriber -> { + if (apiKey == null) { + subscriber.onCompleted(); + return; + } try { - subscriber.onNext(geocoder.getFromLocation(latitude, longitude, MAX_RESULTS)); + String result = networkClient.requestFromLocationName(String.format(Locale.ENGLISH, + QUERY_LAT_LONG, latitude, longitude, apiKey)); + List
addresses = addressBuilder.parseResult(result); + subscriber.onNext(addresses); subscriber.onCompleted(); - } catch (IOException e) { + } catch (JSONException e) { subscriber.onError(e); } }); diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderPresenter.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderPresenter.java index c9667e75..20ca5917 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderPresenter.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderPresenter.java @@ -13,18 +13,21 @@ public class GeocoderPresenter { private static final int RETRY_COUNT = 3; private final GeocoderInteractorInterface interactor; + private final GeocoderInteractorInterface apiInteractor; private GeocoderViewInterface view; private final GeocoderViewInterface nullView = new GeocoderViewInterface.NullView(); private CompositeSubscription compositeSubscription; private final Scheduler scheduler; private ReactiveLocationProvider locationProvider; - public GeocoderPresenter(ReactiveLocationProvider reactiveLocationProvider, GeocoderInteractorInterface interactor) { - this(reactiveLocationProvider, interactor, AndroidSchedulers.mainThread()); + public GeocoderPresenter(ReactiveLocationProvider reactiveLocationProvider, GeocoderInteractorInterface interactor, + GeocoderInteractorInterface apiInteractor) { + this(reactiveLocationProvider, interactor, apiInteractor, AndroidSchedulers.mainThread()); } public GeocoderPresenter(ReactiveLocationProvider reactiveLocationProvider, GeocoderInteractorInterface interactor, - Scheduler scheduler) { + GeocoderInteractorInterface apiInteractor, Scheduler scheduler) { + this.apiInteractor = apiInteractor; this.view = nullView; this.scheduler = scheduler; this.locationProvider = reactiveLocationProvider; @@ -56,6 +59,7 @@ public void getFromLocationName(String query) { .subscribeOn(Schedulers.newThread()) .observeOn(scheduler) .retry(RETRY_COUNT) + .onErrorResumeNext(apiInteractor.getFromLocationName(query)) .subscribe(view::showLocations, throwable -> view.showLoadLocationError(), view::didLoadLocation); compositeSubscription.add(locationNameSubscription); @@ -67,6 +71,7 @@ public void getFromLocationName(String query, LatLng lowerLeft, LatLng upperRigh .subscribeOn(Schedulers.newThread()) .observeOn(scheduler) .retry(RETRY_COUNT) + .onErrorResumeNext(apiInteractor.getFromLocationName(query, lowerLeft, upperRight)) .subscribe(view::showLocations, throwable -> view.showLoadLocationError(), view::didLoadLocation); compositeSubscription.add(locationNameSubscription); @@ -79,6 +84,7 @@ public void getDebouncedFromLocationName(String query, int debounceTime) { .subscribeOn(Schedulers.newThread()) .observeOn(scheduler) .retry(RETRY_COUNT) + .onErrorResumeNext(apiInteractor.getFromLocationName(query)) .subscribe(view::showDebouncedLocations, throwable -> view.showLoadLocationError(), view::didLoadLocation); compositeSubscription.add(locationNameDebounceSubscription); @@ -91,6 +97,7 @@ public void getDebouncedFromLocationName(String query, LatLng lowerLeft, LatLng .subscribeOn(Schedulers.newThread()) .observeOn(scheduler) .retry(RETRY_COUNT) + .onErrorResumeNext(apiInteractor.getFromLocationName(query, lowerLeft, upperRight)) .subscribe(view::showDebouncedLocations, throwable -> view.showLoadLocationError(), view::didLoadLocation); compositeSubscription.add(locationNameDebounceSubscription); @@ -102,6 +109,7 @@ public void getInfoFromLocation(LatLng latLng) { .subscribeOn(Schedulers.newThread()) .observeOn(scheduler) .retry(RETRY_COUNT) + .onErrorResumeNext(apiInteractor.getFromLocation(latLng.latitude, latLng.longitude)) .subscribe(view::showLocationInfo, throwable -> view.showGetLocationInfoError(), view::didGetLocationInfo); compositeSubscription.add(locationSubscription); diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java index 4e24a411..5b3977b3 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java @@ -56,6 +56,8 @@ Address parseAddress(JSONObject jsonObject) throws JSONException { address.setLongitude(longitude); address.setPostalCode(postalCode); address.setAddressLine(0, fullAddress.toString()); + address.setAddressLine(1, postalCode); + address.setAddressLine(2, city); address.setLocality(city); return address; } From 67161b26f15a2482475b8fd9505738b006a34fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Mart=C3=ADnez?= Date: Tue, 13 Jun 2017 11:03:08 +0200 Subject: [PATCH 3/6] Checkstyle --- .../com/schibsted/leku/geocoder/api/AddressBuilderShould.java | 4 ++-- .../schibstedspain/leku/geocoder/GeocoderAPIInteractor.java | 2 -- .../com/schibstedspain/leku/geocoder/api/AddressBuilder.java | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java b/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java index bbda7220..35cd8fc9 100644 --- a/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java +++ b/leku/src/androidTest/java/com/schibsted/leku/geocoder/api/AddressBuilderShould.java @@ -26,7 +26,7 @@ public void setUp() { } @Test - public void returnExpectedAddress_WhenJsonProvided() throws JSONException { + public void returnExpectedAddressWhenJsonProvided() throws JSONException { String json = getJson(); List
addresses = addressBuilder.parseResult(json); @@ -40,7 +40,7 @@ public void returnExpectedAddress_WhenJsonProvided() throws JSONException { } @Test - public void returnExpectedAddress_WhenJsonWithOnlyCityProvided() throws JSONException { + public void returnExpectedAddressWhenJsonWithOnlyCityProvided() throws JSONException { String json = getJsonForOnlyCity(); List
addresses = addressBuilder.parseResult(json); diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java index 9512ce82..69dd3048 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java @@ -1,11 +1,9 @@ package com.schibstedspain.leku.geocoder; import android.location.Address; -import android.location.Geocoder; import com.google.android.gms.maps.model.LatLng; import com.schibstedspain.leku.geocoder.api.AddressBuilder; import com.schibstedspain.leku.geocoder.api.NetworkClient; -import java.io.IOException; import java.util.List; import java.util.Locale; import org.json.JSONException; diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java index 5b3977b3..4469c8ea 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java @@ -14,7 +14,7 @@ public List
parseResult(String json) throws JSONException { List
addresses = new ArrayList<>(); JSONObject root = new JSONObject(json); JSONArray results = root.getJSONArray("results"); - for(int i = 0; i getAddressComponents(JSONArray jsonComponents) throws JSONException { List components = new ArrayList<>(); - for (int i = 0;i Date: Tue, 13 Jun 2017 11:09:11 +0200 Subject: [PATCH 4/6] findbugs --- .../schibstedspain/leku/geocoder/api/AddressBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java index 4469c8ea..6f9c9a38 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/api/AddressBuilder.java @@ -20,7 +20,7 @@ public List
parseResult(String json) throws JSONException { return addresses; } - Address parseAddress(JSONObject jsonObject) throws JSONException { + private Address parseAddress(JSONObject jsonObject) throws JSONException { JSONObject location = jsonObject.getJSONObject("geometry").getJSONObject("location"); double latitude = location.getDouble("lat"); double longitude = location.getDouble("lng"); @@ -62,7 +62,7 @@ Address parseAddress(JSONObject jsonObject) throws JSONException { return address; } - List getAddressComponents(JSONArray jsonComponents) throws JSONException { + private List getAddressComponents(JSONArray jsonComponents) throws JSONException { List components = new ArrayList<>(); for (int i = 0; i < jsonComponents.length(); i++) { AddressComponent component = new AddressComponent(); @@ -78,7 +78,7 @@ List getAddressComponents(JSONArray jsonComponents) throws JSO return components; } - class AddressComponent { + private static class AddressComponent { String name; List types; } From 4c58a5c2d8188edd1826484a4e0b90e5c2142727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Mart=C3=ADnez?= Date: Tue, 13 Jun 2017 11:21:56 +0200 Subject: [PATCH 5/6] PMD --- .../java/com/schibstedspain/leku/LocationPickerActivity.java | 1 - .../com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java | 1 - 2 files changed, 2 deletions(-) diff --git a/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java b/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java index ba5c19e6..86e2a2de 100644 --- a/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java +++ b/leku/src/main/java/com/schibstedspain/leku/LocationPickerActivity.java @@ -129,7 +129,6 @@ public class LocationPickerActivity extends AppCompatActivity private Map lekuPoisMarkersMap; private Marker currentMarker; private TextWatcher textWatcher; - private String apiKey; private GeocoderAPIInteractor apiInteractor; @Override diff --git a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java index 69dd3048..8719277e 100644 --- a/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java +++ b/leku/src/main/java/com/schibstedspain/leku/geocoder/GeocoderAPIInteractor.java @@ -11,7 +11,6 @@ public class GeocoderAPIInteractor implements GeocoderInteractorInterface { - private final static int MAX_RESULTS = 5; private static final String QUERY_REQUEST = "https://maps.googleapis.com/maps/api/geocode/json?address=%1$s&key=%2$s"; private static final String QUERY_REQUEST_WITH_RECTANGLE = "https://maps.googleapis.com/maps/api/geocode/json?address=%1$s&key=%2$s&bounds=%3$f,%4$f|%5$f,%6$f"; From b58e0d85361fc25a1aa69ca7a67aba075ea76587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Mart=C3=ADnez?= Date: Tue, 13 Jun 2017 11:27:18 +0200 Subject: [PATCH 6/6] adding documentation about new feature --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index f1cd1fec..36a3c907 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ You only need to use the Builder setters like: ```java Intent intent = new LocationPickerActivity.Builder() .withLocation(41.4036299, 2.1743558) + .withGeolocApiKey("") .withSearchZone("es_ES") .shouldReturnOkOnBackPressed() .withStreetHidden() @@ -305,6 +306,13 @@ Available tracking events are: |RESULT_OK|Return location| |CANCEL|Return without location| +#### Geocoding API Fallback + +In few cases, the geocoding service from Android fails due to an issue with the NetworkLocator. The only way of fixing this is rebooting the device. + +In order to cover these cases, you can instruct Leku to use the Geocoding API. To enable it, just use the method '''withGeolocApiKey''' when invoking the LocationPicker. + +You should provide your Server Key as parameter. Keep in mind that the free tier only allows 2,500 requests per day. You can track how many times is it used in the Developer Console from Google. #### Extra