Updated Location Service to use Google Play Location Service
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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,14 +43,25 @@ 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
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @return a intent that will start the service
|
* @return a intent that will start the service
|
||||||
* @author ricky barrette
|
* @author ricky barrette
|
||||||
@@ -60,7 +72,7 @@ public class LocationService extends Service implements LocationListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* a convince method for stopping the service and removing it's alarm
|
* a convince method for stopping the service and removing it's alarm
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @return a runnable that will stop the service
|
* @return a runnable that will stop the service
|
||||||
* @author ricky barrette
|
* @author ricky barrette
|
||||||
@@ -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);
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
|
||||||
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
|
return START_STICKY;
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
setUpLocationClientIfNeeded();
|
||||||
|
if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress)
|
||||||
|
{
|
||||||
|
mInProgress = true;
|
||||||
|
mLocationClient.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user