aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/sensors/GpsStatusProvider.java')
-rw-r--r--main/src/cgeo/geocaching/sensors/GpsStatusProvider.java112
1 files changed, 112 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java
new file mode 100644
index 0000000..61243c3
--- /dev/null
+++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java
@@ -0,0 +1,112 @@
+package cgeo.geocaching.sensors;
+
+import cgeo.geocaching.sensors.GpsStatusProvider.Status;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils.ConnectableLooperCallbacks;
+
+import rx.Observable;
+import rx.Observable.OnSubscribe;
+import rx.Subscriber;
+import rx.observables.ConnectableObservable;
+import rx.subjects.BehaviorSubject;
+
+import android.content.Context;
+import android.location.GpsSatellite;
+import android.location.GpsStatus;
+import android.location.LocationManager;
+
+public class GpsStatusProvider implements OnSubscribe<Status> {
+
+ public static class Status {
+ final public boolean gpsEnabled;
+ final public int satellitesVisible;
+ final public int satellitesFixed;
+
+ public Status(final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed) {
+ this.gpsEnabled = gpsEnabled;
+ this.satellitesVisible = satellitesVisible;
+ this.satellitesFixed = satellitesFixed;
+ }
+ }
+
+ private final LocationManager geoManager;
+ private final BehaviorSubject<Status> subject;
+
+ private Status latest = new Status(false, 0, 0);
+
+ /**
+ * Build a new gps status provider object.
+ * <p/>
+ * There is no need to instantiate more than one such object in an application, as observers can be added
+ * at will.
+ *
+ * @param context the context used to retrieve the system services
+ */
+ protected GpsStatusProvider(final Context context) {
+ geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+ subject = BehaviorSubject.create(latest);
+ }
+
+ public static Observable<Status> create(final Context context) {
+ final GpsStatusProvider provider = new GpsStatusProvider(context);
+ return provider.worker.refCount();
+ }
+
+ @Override
+ public void call(final Subscriber<? super Status> subscriber) {
+ subject.subscribe(subscriber);
+ }
+
+ final ConnectableObservable<Status> worker = new ConnectableLooperCallbacks<Status>(this) {
+ private final GpsStatus.Listener gpsStatusListener = new GpsStatusListener();
+
+ @Override
+ protected void onStart() {
+ Log.d("GpsStatusProvider: starting the GPS status listener");
+ geoManager.addGpsStatusListener(gpsStatusListener);
+ }
+
+ @Override
+ protected void onStop() {
+ Log.d("GpsStatusProvider: stopping the GPS status listener");
+ geoManager.removeGpsStatusListener(gpsStatusListener);
+ }
+ };
+
+ private final class GpsStatusListener implements GpsStatus.Listener {
+
+ @Override
+ public void onGpsStatusChanged(final int event) {
+ switch (event) {
+ case GpsStatus.GPS_EVENT_FIRST_FIX:
+ case GpsStatus.GPS_EVENT_SATELLITE_STATUS: {
+ final GpsStatus status = geoManager.getGpsStatus(null);
+ int visible = 0;
+ int fixed = 0;
+ for (final GpsSatellite satellite : status.getSatellites()) {
+ if (satellite.usedInFix()) {
+ fixed++;
+ }
+ visible++;
+ }
+ if (visible == latest.satellitesVisible && fixed == latest.satellitesFixed) {
+ return;
+ }
+ latest = new Status(true, visible, fixed);
+ break;
+ }
+ case GpsStatus.GPS_EVENT_STARTED:
+ latest = new Status(true, 0, 0);
+ break;
+ case GpsStatus.GPS_EVENT_STOPPED:
+ latest = new Status(false, 0, 0);
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+
+ subject.onNext(latest);
+ }
+ }
+
+}