aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2014-08-05 11:24:34 +0200
committerSamuel Tardieu <sam@rfc1149.net>2014-08-05 11:24:34 +0200
commit878ed6668113a29eb8695cb556ff83fb75626061 (patch)
treec1525cc475225a25bb884170c37119559a04bc95
parent8dfc859f5418c93a2cd8799d251170ac7b2df8f3 (diff)
downloadcgeo-878ed6668113a29eb8695cb556ff83fb75626061.zip
cgeo-878ed6668113a29eb8695cb556ff83fb75626061.tar.gz
cgeo-878ed6668113a29eb8695cb556ff83fb75626061.tar.bz2
Use the Google Play fused location service when available
-rw-r--r--main/res/values/strings.xml1
-rw-r--r--main/src/cgeo/geocaching/CgeoApplication.java4
-rw-r--r--main/src/cgeo/geocaching/enumerations/LocationProviderType.java1
-rw-r--r--main/src/cgeo/geocaching/playservices/LocationProvider.java99
-rw-r--r--main/src/cgeo/geocaching/sensors/GeoData.java7
5 files changed, 109 insertions, 3 deletions
diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml
index ade4bf6..a2d1b8f 100644
--- a/main/res/values/strings.xml
+++ b/main/res/values/strings.xml
@@ -228,6 +228,7 @@
<!-- location service -->
<string name="loc_last">Last known</string>
<string name="loc_net">Network</string>
+ <string name="loc_fused">Fused</string>
<string name="loc_gps">GPS</string>
<string name="loc_sat">Sat</string>
<string name="loc_trying">Trying to Locate</string>
diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java
index 1b3cb05..c8a68f4 100644
--- a/main/src/cgeo/geocaching/CgeoApplication.java
+++ b/main/src/cgeo/geocaching/CgeoApplication.java
@@ -1,5 +1,6 @@
package cgeo.geocaching;
+import cgeo.geocaching.playservices.LocationProvider;
import cgeo.geocaching.sensors.DirectionProvider;
import cgeo.geocaching.sensors.GeoDataProvider;
import cgeo.geocaching.sensors.GpsStatusProvider;
@@ -85,7 +86,8 @@ public class CgeoApplication extends Application {
public synchronized Observable<IGeoData> geoDataObservable() {
if (geoDataObservable == null) {
- final ConnectableObservable<IGeoData> onDemand = GeoDataProvider.create(this).replay(1);
+ final Observable<IGeoData> rawObservable = isGooglePlayServicesAvailable() ? LocationProvider.create(this) : GeoDataProvider.create(this);
+ final ConnectableObservable<IGeoData> onDemand = rawObservable.replay(1);
onDemand.subscribe(new Action1<IGeoData>() {
@Override
public void call(final IGeoData geoData) {
diff --git a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java
index f2c79fe..e6024aa 100644
--- a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java
+++ b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.R;
public enum LocationProviderType {
GPS(R.string.loc_gps),
NETWORK(R.string.loc_net),
+ FUSED(R.string.loc_fused),
LAST(R.string.loc_last);
public final int resourceId;
diff --git a/main/src/cgeo/geocaching/playservices/LocationProvider.java b/main/src/cgeo/geocaching/playservices/LocationProvider.java
new file mode 100644
index 0000000..714eaeb
--- /dev/null
+++ b/main/src/cgeo/geocaching/playservices/LocationProvider.java
@@ -0,0 +1,99 @@
+package cgeo.geocaching.playservices;
+
+import cgeo.geocaching.sensors.GeoData;
+import cgeo.geocaching.sensors.IGeoData;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RxUtils.ConnectableLooperCallbacks;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
+import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
+import com.google.android.gms.location.LocationClient;
+import com.google.android.gms.location.LocationListener;
+import com.google.android.gms.location.LocationRequest;
+
+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.Location;
+import android.os.Bundle;
+
+import java.util.concurrent.TimeUnit;
+
+public class LocationProvider implements OnSubscribe<IGeoData>, ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
+
+ private final BehaviorSubject<IGeoData> subject;
+ private final LocationClient locationClient;
+ private static final LocationRequest LOCATION_REQUEST =
+ LocationRequest.create().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(2000).setInterval(1000);
+ private static boolean firstLocation = true;
+
+ /**
+ * Build a new geo data 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 LocationProvider(final Context context) {
+ locationClient = new LocationClient(context, this, this);
+ subject = BehaviorSubject.create();
+ }
+
+ public static Observable<IGeoData> create(final Context context) {
+ final LocationProvider provider = new LocationProvider(context);
+ return provider.worker.refCount();
+ }
+
+ @Override
+ public void call(final Subscriber<? super IGeoData> subscriber) {
+ subject.subscribe(subscriber);
+ }
+
+ final ConnectableObservable<IGeoData> worker = new ConnectableLooperCallbacks<IGeoData>(this, 2500, TimeUnit.MILLISECONDS) {
+ @Override
+ protected void onStart() {
+ Log.d("LocationProvider: starting the location listener");
+ locationClient.connect();
+ }
+
+ @Override
+ protected void onStop() {
+ Log.d("LocationProvider: stopping the location listener");
+ locationClient.removeLocationUpdates(LocationProvider.this);
+ locationClient.disconnect();
+ }
+ };
+
+ @Override
+ public void onConnected(final Bundle bundle) {
+ if (firstLocation) {
+ final Location initialLocation = locationClient.getLastLocation();
+ if (initialLocation != null) {
+ subject.onNext(new GeoData(initialLocation));
+ }
+ firstLocation = false;
+ }
+ locationClient.requestLocationUpdates(LOCATION_REQUEST, this);
+ }
+
+ @Override
+ public void onDisconnected() {
+ }
+
+ @Override
+ public void onConnectionFailed(final ConnectionResult connectionResult) {
+ Log.e("cannot connect to Google Play location service: " + connectionResult);
+ subject.onError(new RuntimeException("Connection failed: " + connectionResult));
+ }
+
+ @Override
+ public void onLocationChanged(final Location location) {
+ subject.onNext(new GeoData(location));
+ }
+}
diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java
index 2061b6b..ea6c241 100644
--- a/main/src/cgeo/geocaching/sensors/GeoData.java
+++ b/main/src/cgeo/geocaching/sensors/GeoData.java
@@ -6,9 +6,9 @@ import cgeo.geocaching.geopoint.Geopoint;
import android.location.Location;
import android.location.LocationManager;
-class GeoData extends Location implements IGeoData {
+public class GeoData extends Location implements IGeoData {
- GeoData(final Location location) {
+ public GeoData(final Location location) {
super(location);
}
@@ -24,6 +24,9 @@ class GeoData extends Location implements IGeoData {
if (provider.equals(LocationManager.NETWORK_PROVIDER)) {
return LocationProviderType.NETWORK;
}
+ if (provider.equals("fused")) {
+ return LocationProviderType.FUSED;
+ }
return LocationProviderType.LAST;
}