aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/sensors/GeoData.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/sensors/GeoData.java')
-rw-r--r--main/src/cgeo/geocaching/sensors/GeoData.java128
1 files changed, 85 insertions, 43 deletions
diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java
index c0b3974..b8b16fd 100644
--- a/main/src/cgeo/geocaching/sensors/GeoData.java
+++ b/main/src/cgeo/geocaching/sensors/GeoData.java
@@ -1,67 +1,109 @@
package cgeo.geocaching.sensors;
-import cgeo.geocaching.enumerations.LocationProviderType;
-import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.location.Geopoint;
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.Log;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
+import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
-class GeoData extends Location implements IGeoData {
- private final boolean gpsEnabled;
- private final int satellitesVisible;
- private final int satellitesFixed;
- private final boolean pseudoLocation;
+public class GeoData extends Location {
- GeoData(final Location location, final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed, final boolean pseudoLocation) {
- super(location);
- this.gpsEnabled = gpsEnabled;
- this.satellitesVisible = satellitesVisible;
- this.satellitesFixed = satellitesFixed;
- this.pseudoLocation = pseudoLocation;
+ public static final String INITIAL_PROVIDER = "initial";
+ public static final String HOME_PROVIDER = "home";
+ public static final String FUSED_PROVIDER = "fused";
+ public static final String LOW_POWER_PROVIDER = "low-power";
+
+ // Some devices will not have the last position available (for example the emulator). In this case,
+ // rather than waiting forever for a position update which might never come, we emulate it by placing
+ // the user arbitrarly at Paris Notre-Dame, one of the most visited free tourist attractions in the world.
+ final public static GeoData DUMMY_LOCATION = new GeoData(new Location(INITIAL_PROVIDER));
+
+ static {
+ DUMMY_LOCATION.setLatitude(48.85308);
+ DUMMY_LOCATION.setLongitude(2.34962);
}
- @Override
- public Location getLocation() {
- return this;
+ public GeoData(final Location location) {
+ super(location);
}
- private static LocationProviderType getLocationProviderType(final String provider) {
- if (provider.equals(LocationManager.GPS_PROVIDER)) {
- return LocationProviderType.GPS;
+ @Nullable
+ static Location best(@Nullable final Location gpsLocation, @Nullable final Location netLocation) {
+ if (netLocation == null || (gpsLocation != null && System.currentTimeMillis() <= gpsLocation.getTime() + 30000)) {
+ return gpsLocation;
}
- if (provider.equals(LocationManager.NETWORK_PROVIDER)) {
- return LocationProviderType.NETWORK;
+ if (gpsLocation == null) {
+ return netLocation;
}
- return LocationProviderType.LAST;
+ return gpsLocation.getTime() >= netLocation.getTime() ? gpsLocation : netLocation;
}
- @Override
public LocationProviderType getLocationProvider() {
- return getLocationProviderType(getProvider());
+ switch (getProvider()) {
+ case LocationManager.GPS_PROVIDER:
+ return LocationProviderType.GPS;
+ case LocationManager.NETWORK_PROVIDER:
+ return LocationProviderType.NETWORK;
+ case FUSED_PROVIDER:
+ // LocationManager.FUSED_PROVIDER constant is not available at API level 9
+ return LocationProviderType.FUSED;
+ case LOW_POWER_PROVIDER:
+ return LocationProviderType.LOW_POWER;
+ case HOME_PROVIDER:
+ return LocationProviderType.HOME;
+ default:
+ return LocationProviderType.LAST;
+ }
}
- @Override
+ @NonNull
public Geopoint getCoords() {
return new Geopoint(this);
}
- @Override
- public boolean getGpsEnabled() {
- return gpsEnabled;
- }
-
- @Override
- public int getSatellitesVisible() {
- return satellitesVisible;
- }
-
- @Override
- public int getSatellitesFixed() {
- return satellitesFixed;
+ @Nullable
+ public static GeoData getInitialLocation(final Context context) {
+ final LocationManager geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+ if (geoManager != null) {
+ try {
+ // Try to find a sensible initial location from the last locations known to Android.
+ final Location lastGpsLocation = geoManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ final Location lastNetworkLocation = geoManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
+ final Location bestLocation = best(lastGpsLocation, lastNetworkLocation);
+ if (bestLocation != null) {
+ bestLocation.setProvider(INITIAL_PROVIDER);
+ return new GeoData(bestLocation);
+ }
+ } catch (final Exception e) {
+ // This error is non-fatal as its only consequence is that we will start with a dummy location
+ // instead of a previously known one.
+ Log.e("Error when retrieving last known location", e);
+ }
+ } else {
+ Log.w("No LocationManager available");
+ }
+ final String homeLocationStr = Settings.getHomeLocation();
+ if (StringUtils.isNotBlank(homeLocationStr)) {
+ try {
+ assert homeLocationStr != null;
+ final Geopoint homeLocation = new Geopoint(homeLocationStr);
+ Log.i("No last known location available, using home location");
+ final Location initialLocation = new Location(HOME_PROVIDER);
+ initialLocation.setLatitude(homeLocation.getLatitude());
+ initialLocation.setLongitude(homeLocation.getLongitude());
+ return new GeoData(initialLocation);
+ } catch (final Geopoint.ParseException e) {
+ Log.w("Unable to parse home location " + homeLocationStr, e);
+ }
+ }
+ Log.i("No last known location nor home location available");
+ return null;
}
- @Override
- public boolean isPseudoLocation() {
- return pseudoLocation;
- }
-}
+} \ No newline at end of file