Updated Location Service to use Google Play Location Service

This commit is contained in:
2014-09-17 20:27:13 -04:00
parent fcb4aecf8a
commit c2f98c526f
3 changed files with 183 additions and 56 deletions

View File

@@ -72,6 +72,8 @@ public final class LocationLibraryConstants {
public static final String INTENT_EXTRA_LOCATION_CHANGED = LocationManager.KEY_LOCATION_CHANGED; public static final String INTENT_EXTRA_LOCATION_CHANGED = LocationManager.KEY_LOCATION_CHANGED;
public static final String INTENT_EXTRA_LOCATION_ATUO = "RockBarrette.action.LocationAuto";
/** /**
* Used to tell the service how accurate of a location you want reported * Used to tell the service how accurate of a location you want reported
*/ */
@@ -82,4 +84,15 @@ public final class LocationLibraryConstants {
* no data * no data
*/ */
public static final long FAIL_SAFE_UPDATE_INVERVAL = AlarmManager.INTERVAL_FIFTEEN_MINUTES; public static final long FAIL_SAFE_UPDATE_INVERVAL = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
// Milliseconds per second
private static final int MILLISECONDS_PER_SECOND = 1000;
// Update frequency in seconds
private static final int UPDATE_INTERVAL_IN_SECONDS = 30;
// Update frequency in milliseconds
public static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// The fastest update frequency, in seconds
private static final int FASTEST_INTERVAL_IN_SECONDS = 30;
// A fast frequency ceiling in milliseconds
public static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
} }

View File

@@ -133,9 +133,7 @@ public class GeoUtils {
* *
* we are solving this equation for lon2Rad * we are solving this equation for lon2Rad
* *
* lon2Rad = * lon2Rad = lon1Rad+acos(cos(meters/6371)sec(lat1Rad)sec(lat2Rad)-tan(lat1Rad)tan(lat2Rad))
* lon1Rad+acos(cos(meters/6371)sec(lat1Rad)sec(lat2Rad)-tan(lat1Rad
* )tan(lat2Rad))
* *
* NOTE: sec(x) = 1/cos(x) * NOTE: sec(x) = 1/cos(x)
* *
@@ -148,10 +146,35 @@ public class GeoUtils {
* device, and the distanceKm() from google and has been proven to be * device, and the distanceKm() from google and has been proven to be
* damn close * damn close
*/ */
final double lon2Rad = lon1Rad + Math.acos(Math.cos(distance / 6371) * (1 / Math.cos(lat1Rad)) * (1 / Math.cos(lat1Rad)) - Math.tan(lat1Rad) * Math.tan(lat1Rad)); final double lon2Rad = lon1Rad + Math.acos(Math.cos(distance / 6371) * sec(lat1Rad) * sec(lat1Rad) - Math.tan(lat1Rad) * Math.tan(lat1Rad));
// return a LatLng that is x meters away from the LatLng supplied // return a LatLng that is x meters away from the LatLng supplied
return new LatLng(point.latitude, (int) (Math.toDegrees(lon2Rad) * 1e6)); return new LatLng(point.latitude, Math.toDegrees(lon2Rad));
}
public static LatLng distanceFrom(final LatLng point, final double distance, final float bearing) {
final double dist = distance / 6371;
final double brng = Math.toRadians(bearing);
final double lat1 = Math.toRadians(point.latitude);
final double lon1 = Math.toRadians(point.longitude);
final double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) + Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
final double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(lat1), Math.cos(dist) - Math.sin(lat1) * Math.sin(lat2));
// if (isNaN(lat2) || isNaN(lon2))
// return null;
return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
/**
* compute secant
* @param theta angle in radians
* @return secant of theta.
*/
public static double sec ( double theta ){
return 1.0 / Math.cos( theta );
} }
/** /**

View File

@@ -25,16 +25,17 @@ import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.location.Location; import android.location.Location;
import android.location.LocationListener; import android.os.*;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock;
import android.util.Log; import android.util.Log;
import com.TwentyCodes.android.debug.Debug; import com.TwentyCodes.android.debug.Debug;
import com.TwentyCodes.android.debug.LocationLibraryConstants; import com.TwentyCodes.android.debug.LocationLibraryConstants;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
/** /**
* This service class will be used broadcast the users location either one time, * This service class will be used broadcast the users location either one time,
@@ -42,10 +43,21 @@ import com.TwentyCodes.android.debug.LocationLibraryConstants;
* *
* @author ricky barrette * @author ricky barrette
*/ */
public class LocationService extends Service implements LocationListener { public class LocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
public static final String TAG = "LocationService"; public static final String TAG = "LocationService";
private static final int REQUEST_CODE = 7893749; private static final int REQUEST_CODE = 7893749;
private IBinder mBinder;
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;
private Boolean servicesAvailable = false;
private WakeLock mWakeLock;
private Location mLocation;
private int mStartId;
private int mRequiredAccuracy;
private Intent mIntent;
/** /**
* a convince method for getting an intent to start the service * a convince method for getting an intent to start the service
@@ -76,14 +88,6 @@ public class LocationService extends Service implements LocationListener {
}; };
} }
private WakeLock mWakeLock;
private Location mLocation;
private int mStartId;
private AndroidGPS mLocationManager;
private int mRequiredAccuracy;
private Intent mIntent;
/* /*
* this runnable will be qued when the service is created. this will be used * this runnable will be qued when the service is created. this will be used
* as a fail safe * as a fail safe
@@ -116,20 +120,6 @@ public class LocationService extends Service implements LocationListener {
} }
} }
/**
* (non-Javadoc)
*
* @see android.app.Service#onBind(android.content.Intent)
* @param arg0
* @return
* @author ricky barrette
*/
@Override
public IBinder onBind(final Intent arg0) {
// UNUSED
return null;
}
/** /**
* called when the service is created. this will initialize the location * called when the service is created. this will initialize the location
* manager, and acquire a wakelock (non-Javadoc) * manager, and acquire a wakelock (non-Javadoc)
@@ -139,7 +129,6 @@ public class LocationService extends Service implements LocationListener {
*/ */
@Override @Override
public void onCreate() { public void onCreate() {
mLocationManager = new AndroidGPS(this);
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.acquire(); mWakeLock.acquire();
@@ -150,6 +139,24 @@ public class LocationService extends Service implements LocationListener {
*/ */
new Handler().postDelayed(failSafe, LocationLibraryConstants.MAX_LOCATION_SERVICE_RUN_TIME); new Handler().postDelayed(failSafe, LocationLibraryConstants.MAX_LOCATION_SERVICE_RUN_TIME);
super.onCreate(); super.onCreate();
mInProgress = false;
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(LocationLibraryConstants.UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(LocationLibraryConstants.FASTEST_INTERVAL);
servicesAvailable = servicesConnected();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
} }
/** /**
@@ -162,7 +169,15 @@ public class LocationService extends Service implements LocationListener {
@Override @Override
public void onDestroy() { public void onDestroy() {
broadcastLocation(); broadcastLocation();
mLocationManager.disableLocationUpdates();
// Turn off the request flag
mInProgress = false;
if(servicesAvailable && mLocationClient != null) {
// Destroy the current location client
mLocationClient.removeLocationUpdates(this);
mLocationClient = null;
}
if (mWakeLock.isHeld()) if (mWakeLock.isHeld())
mWakeLock.release(); mWakeLock.release();
} }
@@ -177,18 +192,6 @@ public class LocationService extends Service implements LocationListener {
stopSelf(mStartId); stopSelf(mStartId);
} }
@Override
public void onProviderDisabled(final String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(final String provider) {
// TODO Auto-generated method stub
}
/** /**
* This method is called when startService is called. only used in 2.x * This method is called when startService is called. only used in 2.x
* android. * android.
@@ -203,13 +206,19 @@ public class LocationService extends Service implements LocationListener {
parseIntent(intent); parseIntent(intent);
mLocationManager.enableLocationUpdates(this); super.onStartCommand(intent, flags, startId);
if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
return START_STICKY; return START_STICKY;
setUpLocationClientIfNeeded();
if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress)
{
mInProgress = true;
mLocationClient.connect();
} }
@Override return START_STICKY;
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
// TODO Auto-generated method stub
} }
/** /**
@@ -228,4 +237,86 @@ public class LocationService extends Service implements LocationListener {
mRequiredAccuracy = intent.getIntExtra(LocationLibraryConstants.INTENT_EXTRA_REQUIRED_ACCURACY, LocationLibraryConstants.MINIMUM_REQUIRED_ACCURACY); mRequiredAccuracy = intent.getIntExtra(LocationLibraryConstants.INTENT_EXTRA_REQUIRED_ACCURACY, LocationLibraryConstants.MINIMUM_REQUIRED_ACCURACY);
} }
} }
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
private void setUpLocationClientIfNeeded()
{
if(mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
@Override
public void onConnected(Bundle bundle) {
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
@Override
public void onDisconnected() {
// Turn off the request flag
mInProgress = false;
mLocationClient.removeLocationUpdates(this);
// Destroy the current location client
mLocationClient = null;
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
// If no resolution is available, display an error dialog
} else {
}
}
} }