package cgeo.geocaching.sensors; import cgeo.geocaching.utils.AndroidRxUtils; import android.content.Context; import android.location.GpsSatellite; import android.location.GpsStatus; import android.location.GpsStatus.Listener; import android.location.LocationManager; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; public class GpsStatusProvider { private GpsStatusProvider() { // Utility class, not to be instantiated } public static class Status { public final boolean gpsEnabled; public final int satellitesVisible; public final int satellitesFixed; public Status(final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed) { this.gpsEnabled = gpsEnabled; this.satellitesVisible = satellitesVisible; this.satellitesFixed = satellitesFixed; } } private static final Status NO_GPS = new Status(false, 0, 0); public static Observable<Status> create(final Context context) { final Observable<Status> observable = Observable.create(new ObservableOnSubscribe<Status>() { @Override public void subscribe(final ObservableEmitter<Status> subscriber) throws Exception { final LocationManager geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); final Listener listener = new Listener() { Status latest = new Status(false, 0, 0); @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: subscriber.onError(new IllegalStateException()); return; } subscriber.onNext(latest); } }; subscriber.onNext(NO_GPS); geoManager.addGpsStatusListener(listener); subscriber.setDisposable(AndroidRxUtils.disposeOnCallbacksScheduler(new Runnable() { @Override public void run() { geoManager.removeGpsStatusListener(listener); } })); } }); return observable.subscribeOn(AndroidRxUtils.looperCallbacksScheduler); } }