diff options
Diffstat (limited to 'main/src/cgeo/geocaching/CgeoApplication.java')
| -rw-r--r-- | main/src/cgeo/geocaching/CgeoApplication.java | 131 |
1 files changed, 95 insertions, 36 deletions
diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index a81319d..34dab09 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -1,15 +1,26 @@ package cgeo.geocaching; -import cgeo.geocaching.sensors.DirectionProvider; +import cgeo.geocaching.playservices.LocationProvider; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDataProvider; +import cgeo.geocaching.sensors.GpsStatusProvider; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.OrientationProvider; +import cgeo.geocaching.sensors.RotationProvider; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.OOMDumpingUncaughtExceptionHandler; +import cgeo.geocaching.utils.RxUtils; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesUtil; + +import org.eclipse.jdt.annotation.NonNull; import rx.Observable; import rx.functions.Action1; -import rx.observables.ConnectableObservable; +import rx.functions.Func1; import android.app.Application; import android.view.ViewConfiguration; @@ -23,9 +34,20 @@ public class CgeoApplication extends Application { private boolean liveMapHintShownInThisSession = false; // livemap hint has been shown private static CgeoApplication instance; private Observable<IGeoData> geoDataObservable; + private Observable<IGeoData> geoDataObservableLowPower; private Observable<Float> directionObservable; - private volatile IGeoData currentGeo = null; + private Observable<Status> gpsStatusObservable; + @NonNull private volatile IGeoData currentGeo = GeoData.DUMMY_LOCATION; + private volatile boolean hasValidLocation = false; private volatile float currentDirection = 0.0f; + private boolean isGooglePlayServicesAvailable = false; + private final Action1<IGeoData> rememberGeodataAction = new Action1<IGeoData>() { + @Override + public void call(final IGeoData geoData) { + currentGeo = geoData; + hasValidLocation = true; + } + }; public static void dumpOnOutOfMemory(final boolean enable) { @@ -60,12 +82,7 @@ public class CgeoApplication extends Application { final Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); - } catch (final IllegalArgumentException e) { - // ignore - } catch (final NoSuchFieldException e) { - // ignore - } catch (final IllegalAccessException e) { - // ignore + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException ignore) { } // Set language to English if the user decided so. @@ -73,6 +90,52 @@ public class CgeoApplication extends Application { // ensure initialization of lists DataStore.getLists(); + + // Check if Google Play services is available + if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) { + isGooglePlayServicesAvailable = true; + } + Log.i("Google Play services are " + (isGooglePlayServicesAvailable ? "" : "not ") + "available"); + setupGeoDataObservables(Settings.useGooglePlayServices(), Settings.useLowPowerMode()); + setupDirectionObservable(Settings.useLowPowerMode()); + gpsStatusObservable = GpsStatusProvider.create(this).replay(1).refCount(); + + // Attempt to acquire an initial location before any real activity happens. + geoDataObservableLowPower.subscribeOn(RxUtils.looperCallbacksScheduler).first().subscribe(rememberGeodataAction); + } + + public void setupGeoDataObservables(final boolean useGooglePlayServices, final boolean useLowPowerLocation) { + if (useGooglePlayServices) { + geoDataObservable = LocationProvider.getMostPrecise(this).doOnNext(rememberGeodataAction); + if (useLowPowerLocation) { + geoDataObservableLowPower = LocationProvider.getLowPower(this, true).doOnNext(rememberGeodataAction); + } else { + geoDataObservableLowPower = geoDataObservable; + } + } else { + geoDataObservable = GeoDataProvider.create(this).replay(1).refCount().doOnNext(rememberGeodataAction); + geoDataObservableLowPower = geoDataObservable; + } + } + + public void setupDirectionObservable(final boolean useLowPower) { + directionObservable = RotationProvider.create(this, useLowPower).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() { + @Override + public Observable<? extends Float> call(final Throwable throwable) { + return OrientationProvider.create(CgeoApplication.this); + } + }).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() { + @Override + public Observable<? extends Float> call(final Throwable throwable) { + Log.e("Device orientation will not be available as no suitable sensors were found"); + return Observable.<Float>never().startWith(0.0f); + } + }).replay(1).refCount().doOnNext(new Action1<Float>() { + @Override + public void call(final Float direction) { + currentDirection = direction; + } + }); } @Override @@ -81,40 +144,32 @@ public class CgeoApplication extends Application { DataStore.removeAllFromCache(); } - public synchronized Observable<IGeoData> geoDataObservable() { - if (geoDataObservable == null) { - final ConnectableObservable<IGeoData> onDemand = GeoDataProvider.create(this).replay(1); - onDemand.subscribe(new Action1<IGeoData>() { - @Override - public void call(final IGeoData geoData) { - currentGeo = geoData; - } - }); - geoDataObservable = onDemand.refCount(); - } - return geoDataObservable; - } - - public synchronized Observable<Float> directionObservable() { - if (directionObservable == null) { - final ConnectableObservable<Float> onDemand = DirectionProvider.create(this).replay(1); - onDemand.subscribe(new Action1<Float>() { - @Override - public void call(final Float direction) { - currentDirection = direction; - } - }); - directionObservable = onDemand.refCount(); - } + public Observable<IGeoData> geoDataObservable(final boolean lowPower) { + return lowPower ? geoDataObservableLowPower : geoDataObservable; + } + + public Observable<Float> directionObservable() { return directionObservable; } + public Observable<Status> gpsStatusObservable() { + if (gpsStatusObservable == null) { + gpsStatusObservable = GpsStatusProvider.create(this).share(); + } + return gpsStatusObservable; + } + + @NonNull public IGeoData currentGeo() { - return currentGeo != null ? currentGeo : geoDataObservable().toBlocking().first(); + return currentGeo; + } + + public boolean hasValidLocation() { + return hasValidLocation; } public Float distanceNonBlocking(final ICoordinates target) { - if (currentGeo == null || target.getCoords() == null) { + if (target.getCoords() == null) { return null; } return currentGeo.getCoords().distanceTo(target); @@ -150,4 +205,8 @@ public class CgeoApplication extends Application { forceRelog = true; } + public boolean isGooglePlayServicesAvailable() { + return isGooglePlayServicesAvailable; + } + } |
