aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java36
-rw-r--r--main/src/cgeo/geocaching/location/AndroidGeocoder.java45
-rw-r--r--main/src/cgeo/geocaching/location/MapQuestGeocoder.java22
3 files changed, 67 insertions, 36 deletions
diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java
index de80f5c..399de83 100644
--- a/main/src/cgeo/geocaching/MainActivity.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -11,7 +11,9 @@ import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.list.PseudoList;
import cgeo.geocaching.list.StoredList;
+import cgeo.geocaching.location.AndroidGeocoder;
import cgeo.geocaching.location.Geopoint;
+import cgeo.geocaching.location.MapQuestGeocoder;
import cgeo.geocaching.location.Units;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.network.Network;
@@ -37,12 +39,11 @@ import com.google.zxing.integration.android.IntentResult;
import org.apache.commons.lang3.StringUtils;
import rx.Observable;
-import rx.Observable.OnSubscribe;
-import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.android.view.ViewObservable;
import rx.functions.Action0;
import rx.functions.Action1;
+import rx.functions.Func1;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
@@ -54,7 +55,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.location.Address;
-import android.location.Geocoder;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
@@ -75,7 +75,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import java.util.Locale;
public class MainActivity extends AbstractActionBarActivity {
@InjectView(R.id.nav_satellites) protected TextView navSatellites;
@@ -572,30 +571,21 @@ public class MainActivity extends AbstractActionBarActivity {
navAccuracy.setText(null);
}
+ final Geopoint currentCoords = geo.getCoords();
if (Settings.isShowAddress()) {
if (addCoords == null) {
navLocation.setText(R.string.loc_no_addr);
}
- if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5)) {
- final Observable<String> address = Observable.create(new OnSubscribe<String>() {
+ if (addCoords == null || (currentCoords.distanceTo(addCoords) > 0.5)) {
+ addCoords = currentCoords;
+ final Observable<String> address = (new AndroidGeocoder(MainActivity.this).getFromLocation(currentCoords)
+ .onErrorResumeNext(MapQuestGeocoder.getFromLocation(currentCoords))).map(new Func1<Address, String>() {
@Override
- public void call(final Subscriber<? super String> subscriber) {
- try {
- addCoords = geo.getCoords();
- final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
- final List<Address> addresses = geocoder.getFromLocation(addCoords.getLatitude(), addCoords.getLongitude(), 1);
- if (!addresses.isEmpty()) {
- subscriber.onNext(formatAddress(addresses.get(0)));
- }
- subscriber.onCompleted();
- } catch (final Exception e) {
- subscriber.onError(e);
- }
+ public String call(final Address address) {
+ return formatAddress(address);
}
- });
- ViewObservable.bindView(navLocation, address.onErrorResumeNext(Observable.just(geo.getCoords().toString())))
- .subscribeOn(RxUtils.networkScheduler)
- .subscribe(new Action1<String>() {
+ }).onErrorResumeNext(Observable.just(currentCoords.toString()));
+ ViewObservable.bindView(navLocation, address).subscribe(new Action1<String>() {
@Override
public void call(final String address) {
navLocation.setText(address);
@@ -603,7 +593,7 @@ public class MainActivity extends AbstractActionBarActivity {
});
}
} else {
- navLocation.setText(geo.getCoords().toString());
+ navLocation.setText(currentCoords.toString());
}
}
}
diff --git a/main/src/cgeo/geocaching/location/AndroidGeocoder.java b/main/src/cgeo/geocaching/location/AndroidGeocoder.java
index 98ea285..d0d07e8 100644
--- a/main/src/cgeo/geocaching/location/AndroidGeocoder.java
+++ b/main/src/cgeo/geocaching/location/AndroidGeocoder.java
@@ -16,11 +16,6 @@ import android.location.Geocoder;
import java.util.List;
import java.util.Locale;
-/**
- * Encapsulation of the Android {@link Geocoder} with default error handling. All methods of this class
- * are blocking and will do network lookups.
- *
- */
public class AndroidGeocoder {
private final Geocoder geocoder;
@@ -39,21 +34,49 @@ public class AndroidGeocoder {
* @see Geocoder#getFromLocationName(String, int)
*/
public Observable<Address> getFromLocationName(@NonNull final String keyword) {
+ if (!Geocoder.isPresent()) {
+ return Observable.error(new RuntimeException("no Android geocoder"));
+ }
return Observable.defer(new Func0<Observable<Address>>() {
@Override
public Observable<Address> call() {
try {
- final List<Address> addresses = geocoder.getFromLocationName(keyword, 20);
- if (CollectionUtils.isEmpty(addresses)) {
- return Observable.error(new RuntimeException("no result from Android geocoder"));
- }
- return Observable.from(addresses);
+ return addressesToObservable(geocoder.getFromLocationName(keyword, 20));
} catch (final Exception e) {
- Log.i("Unable to use Android geocoder: " + e.getMessage());
+ Log.i("Unable to use Android reverse geocoder: " + e.getMessage());
return Observable.error(e);
}
}
}).subscribeOn(RxUtils.networkScheduler);
}
+ /**
+ * Retrieve the physical address for coordinates. The work happens on the network scheduler.
+ *
+ * @param coords the coordinates
+ * @return an observable containing one location or an error
+ */
+ public Observable<Address> getFromLocation(@NonNull final Geopoint coords) {
+ if (!Geocoder.isPresent()) {
+ return Observable.error(new RuntimeException("no Android reverse geocoder"));
+ }
+ return Observable.defer(new Func0<Observable<Address>>() {
+ @Override
+ public Observable<Address> call() {
+ try {
+ return addressesToObservable(geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1));
+ } catch (final Exception e) {
+ Log.i("Unable to use Android reverse geocoder: " + e.getMessage());
+ return Observable.error(e);
+ }
+ }
+ }).subscribeOn(RxUtils.networkScheduler).first();
+ }
+
+ private static Observable<Address> addressesToObservable(final List<Address> addresses) {
+ return CollectionUtils.isEmpty(addresses) ?
+ Observable.<Address>error(new RuntimeException("no result from Android geocoder")) :
+ Observable.from(addresses);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/location/MapQuestGeocoder.java b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java
index 537ae40..cc4a6b5 100644
--- a/main/src/cgeo/geocaching/location/MapQuestGeocoder.java
+++ b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java
@@ -39,11 +39,25 @@ public class MapQuestGeocoder {
* @see android.location.Geocoder#getFromLocationName(String, int)
*/
public static Observable<Address> getFromLocationName(@NonNull final String address) {
+ return get("address", new Parameters("location", address, "maxResults", "20", "thumbMaps", "false"));
+ }
+
+ /**
+ * Retrieve the physical address for coordinates. The work happens on the network scheduler.
+ *
+ * @param coords the coordinates
+ * @return an observable containing one location or an error
+ */
+ public static Observable<Address> getFromLocation(@NonNull final Geopoint coords) {
+ return get("reverse", new Parameters("location", String.format(Locale.US, "%f,%f", coords.getLatitude(), coords.getLongitude()))).first();
+ }
+
+ private static Observable<Address> get(@NonNull final String method, @NonNull final Parameters parameters) {
return Observable.defer(new Func0<Observable<Address>>() {
@Override
public Observable<Address> call() {
- final ObjectNode response = Network.requestJSON("https://www.mapquestapi.com/geocoding/v1/address",
- new Parameters("key", MAPQUEST_KEY, "location", address, "maxResults", "20", "thumbMaps", "false"));
+ final ObjectNode response = Network.requestJSON("https://www.mapquestapi.com/geocoding/v1/" + method,
+ parameters.put("key", MAPQUEST_KEY));
if (response == null) {
Log.w("MapQuest decoder error: no response");
return Observable.error(new RuntimeException("no answer from MapQuest geocoder"));
@@ -110,6 +124,10 @@ public class MapQuestGeocoder {
break;
case "Country":
address.setCountryCode(content);
+ address.setCountryName(new Locale("", content).getDisplayCountry());
+ break;
+ // Make checkers happy
+ default:
break;
}
}