Hi I am trying to fetch location in every 5 seconds and calculate the speed and total distance or the trip but it is not giving exact distance and speed, below is my code please help. TIA
public class LocationUpdater extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private double latitude ;
private double longitude ;
Session session;
Context context;
LocationRequest mLocationRequest;
private static final int MILLISECONDS_PER_SECOND = 1000;
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
private static final long UPDATE_INTERVAL =
MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 10;
private static final long FASTEST_INTERVAL =
MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
private static final int DESIRED_ACCURACY = 10;
private static final float SMALLEST_DISPLACEMENT = 10f;
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
public LocationUpdater() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = LocationUpdater.this;
session = Session.getSession(context);
buildGoogleApiClient();
mGoogleApiClient.connect();
return START_STICKY;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onConnected(Bundle bundle) {
try{
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(SMALLEST_DISPLACEMENT);
requestLocationUpdate();
}catch (SecurityException ex){
ex.printStackTrace();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mGoogleApiClient.connect();
}
#Override
public void onDestroy() {
super.onDestroy();
if(session.getTrip_status().equalsIgnoreCase(Utils.trip_status_started))
startService(new Intent(LocationUpdater.this,LocationUpdater.class));
}
I am able to get results but updates and not accurate and not smooth at all. Please let me know if it is the correct way of doing it or I should try something else.
Below is my location updater code
private void fetchMyLocation(){
try{
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.wtf("ankit","accuracy "+location.getAccuracy());
if (location.hasAccuracy() && location.getAccuracy() <= DESIRED_ACCURACY) {
// This is your most accurate location.
Log.wtf("ankit","latitude:::"+latitude);
Log.wtf("ankit","longitude:::"+longitude);
session.setCurrentLatitude(""+latitude);
session.setCurrentLongitude(""+longitude);
if(session.getTrip_status().equalsIgnoreCase(Utils.trip_status_started)){
updateDistanceAndSpeed(latitude,longitude);
} else {
UpdateLocationListner.getInstance().changeState(latitude,longitude,"");
}
}
}
}
});
}catch (SecurityException ex){
ex.printStackTrace();
}
}
and this is how i calculate speed and distance
// update speed and distance
private void updateDistanceAndSpeed(double latitude,double longitude){
long currentTimeMills = System.currentTimeMillis();
if (session.getLastLatitude().equalsIgnoreCase("")
&& session.getLastLongitude().equalsIgnoreCase("")) {
session.setLastLatitude(""+latitude);
session.setLastLongitude(""+longitude);
}else {
synchronized (this){
try{
String lat = ""+latitude;
String lng = ""+longitude;
double speed = 0;
if(!lat.equalsIgnoreCase(session.getLastLatitude())
&& !lng.equalsIgnoreCase(session.getLastLongitude())){
Location locationA = new Location("point A");
locationA.setLatitude(latitude);
locationA.setLongitude(longitude);
Location locationB = new Location("point B");
locationB.setLatitude(Double.parseDouble(session.getLastLatitude()));
locationB.setLongitude(Double.parseDouble(session.getLastLongitude()));
if(session.getDistance().equalsIgnoreCase(""))
session.setDistance("0");
Log.wtf("ankit","total distance:"+session.getDistance());
float lastDistance = Float.parseFloat(session.getDistance());
float distance[] = new float[1];
Location.distanceBetween(latitude, longitude,
Double.parseDouble(session.getLastLatitude()),
Double.parseDouble(session.getLastLongitude()), distance);
if(!session.getLastTimeStamp().equalsIgnoreCase("")){
long lastTime = Long.parseLong(session.getLastTimeStamp());
long timeDifference = currentTimeMills - lastTime;
long diffInSec = TimeUnit.MILLISECONDS.toSeconds(timeDifference);
speed = distance[0]/diffInSec;
} else {
speed = 0;
}
speed = speed*3.6;
speed = Utils.round(speed,2);
float roundDistance = Utils.round(distance[0],2);
Log.wtf("ankit","roundDistance"+roundDistance);
float final_distance = lastDistance+roundDistance;
UpdateLocationListner.getInstance().changeState(latitude,longitude,""+speed+"/"+final_distance);
session.setDistance(""+final_distance);
} else {
UpdateLocationListner.getInstance().changeState(latitude,longitude,"0/0");
}
// send speed
}catch (Exception ex){
ex.printStackTrace();
}
}
session.setLastLatitude(""+latitude);
session.setLastLongitude(""+longitude);
session.setLastTimeStamp(""+currentTimeMills);
}
}
You just need to pass latitudes and longitude
public void setLatLng(LatLng origins, LatLng destinations) {
url = "http://maps.googleapis.com/maps/api/distancematrix/json?" +
"origins=" + origins.latitude + "," + origins.longitude + "" +
"&destinations=" + destinations.latitude + "," + destinations.longitude + "" +
"&mode=driving" +
"&language=en-EN" +
"&sensor=false";
}
Handle the response of this URL here give the distance and time between two latitudes and longitude so now you need to calculate speed and for the speed you use
speed = distance / time
i want to show persistence notification my location traction service but the service gets killed once the onHandleIndent completes, there is a timertask to get the location periodically ,
my problem is,
Its working fine if onStartCommand not returning START_STICKY. but in this case notification is not appearing.
i want my service to be running forever with persistence notification.
here is my class
public class TrackLocation extends IntentService {
public static final String START_TRACKING = "START_TRACKING";
public static final String STOP_TRACKING = "STOP_TRACKING";
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1;
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 10000;
double totalDistance = 0;
Location locationFirstOld;
protected LocationManager locationManager;
static double n = 0;
Long s1, r1;
double plat, plon, clat, clon, dis;
Thread t1;
EditText e1;
boolean bool = true;
private String booking_id;
private FusedLocationProviderClient mFusedLocationClient;
public static boolean isTrackingEnabled;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
*/
public TrackLocation() {
super("Distance tracking service");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
String action = intent.getAction();
if (action.equals(START_TRACKING)) {
isTrackingEnabled = true;
booking_id = intent.getStringExtra("booking_id");
startTracking();
} else {
isTrackingEnabled = false;
}
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
return START_STICKY;
}
private void startTracking() {
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
if (isTrackingEnabled) {
Log.d("tracking", "run: " + new Date().toString());
getLocation();
} else {
timer.cancel();
}
}
};
timer.schedule(timerTask,0,5000);
Intent notificationIntent = new Intent(this, PickaupActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1,
notificationIntent, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("On going trip")
.setContentText("Active trips")
.setSmallIcon(R.drawable.ic_notification_auto_request)
.setContentIntent(pendingIntent)
.setTicker("Trip started")
.build();
startForeground(1337, notification);
}
private void getLocation() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mFusedLocationClient.getLastLocation().addOnSuccessListener( new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
Log.d("", "onSuccess: " + location.getLatitude());
submitData(location);
}
}
});
}
private void submitData(Location location) {
if (locationFirstOld == null) {
locationFirstOld = location;
return;
}
// sendMyLocation(location);
// double distance = getDistance(locationFirstOld.getLatitude(), locationFirstOld.getLongitude(), location.getLatitude(), location.getLongitude());
double distance = locationFirstOld.distanceTo(location);
Log.d("distance", "submitData: " + String.valueOf(distance));
locationFirstOld = location;
sendMessageToActivity(totalDistance);
totalDistance += distance;
}
public double getDistance(double lat1, double lon1, double lat2, double lon2) {
double latA = Math.toRadians(lat1);
double lonA = Math.toRadians(lon1);
double latB = Math.toRadians(lat2);
double lonB = Math.toRadians(lon2);
double cosAng = (Math.cos(latA) * Math.cos(latB) * Math.cos(lonB-lonA)) +
(Math.sin(latA) * Math.sin(latB));
double ang = Math.acos(cosAng);
double dist = ang *6371;
return dist;
}
private void sendMessageToActivity(double distance) {
Intent intent = new Intent("DISTANCE_UPDATE");
// You can also include some extra data.
intent.putExtra("distance", distance);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void sendMyLocation(Location location) {
Intent intent = new Intent();
intent.putExtra("lat", location.getLatitude());
intent.putExtra("lat", location.getLongitude());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
IntentService stops when it is done doing whatever it does.
Use Service instead, Service types are not stopped until the system, user or the app stops it
the service gets killed once the onHandleIndent completes
That is standard behavior for IntentService — IntentService calls stopSelf() when onHandleIntent() returns, if there are no more queued-up commands.
Do not use IntentService for this scenario. Create you own service with your own threading model, calling stopSelf() when you no longer need the service.
I created a class GPSController. The onReceive is called every Minute.
I want to get the current GPS Data with the GPSListener in my AsyncTask.
But the onLocationChanged Method is never called. :-/
Here is my Class:
public class GPSController extends SensorTimeController {
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0;
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 2;
private boolean isGPSEnabled = false;
private boolean isNetworkEnabled = false;
private double latitude = -1;
private double longitude = -1;
private double altitude = -1;
private double speed = 0L;
private double bearing = 0L;
private LocationManager locationManager;
private GPSLocationTask backgroundTask;
public GPSController(GPSModule module) {
super(module);
backgroundTask = new GPSLocationTask();
}
private void SensorDataFinished(double longitude, double latitude, double altitude, double speed, double bearing) {
Date date = new Date(System.currentTimeMillis());
SensorRecord record = new SensorRecord(module.getNextIndex(), date, structure);
if (longitude != -1)
record.addData("longitude", String.valueOf(longitude));
else
record.addData("longitude", " ");
if (latitude != -1)
record.addData("latitude", String.valueOf(longitude));
else
record.addData("latitude", " ");
if (altitude != -1)
record.addData("altitude", String.valueOf(altitude));
else
record.addData("altitude", " ");
if (bearing != 0L)
record.addData("bearing", String.valueOf(bearing));
else
record.addData("bearing", " ");
if (speed != 0L)
record.addData("speed", String.valueOf(speed));
else
record.addData("speed", " ");
module.log(record);
}
#Override
public void onReceive(Context context, Intent intent) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
backgroundTask.execute();
}
private class GPSLocationTask extends AsyncTask<Void, Void, Void> implements LocationListener {
#Override
protected Void doInBackground(Void... params) {
System.out.println("THREAD STARTED");
try {
Looper.prepare();
Looper.loop();
if(isNetworkEnabled)
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if(isGPSEnabled)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
}catch(SecurityException e) {
e.printStackTrace();
}
return null;
}
public void onLocationChanged(Location location) {
if (location != null) {
longitude = location.getLongitude();
latitude = location.getLatitude();
altitude = location.getAltitude();
// don't do anything if we get a null reading for some reason
if (longitude == 0.0f && latitude == 0.0f)
return;
// any speed information?
if (location.hasSpeed())
speed = (double) location.getSpeed();
// any bearing information?
if (location.hasBearing())
bearing = (double) location.getBearing();
System.out.println(longitude+", "+ latitude+", "+ altitude+", "+ speed+", "+ bearing);
SensorDataFinished(longitude, latitude, altitude, speed, bearing);
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}
I am currently trying the LocationClient provided by Google Services. When I am next to a building I receive frequent location updates but in the middle of a road they are less frequent and less accurate. In the country side, no updates at all. I wondered if the Google Location Services uses the GPS so I disabled all location providers but the GPS in the phone's settings and I instantly stopped receiving any update. Obviously my LocationClient does not receive any update using GPS data.
Am I missing something? Is there anything I have to set for the LocationClient or do I have to use the standard LocationManager.GPS_PROVIDER?
I am trying to build an app for running and I need accurate location data. Any advice would be much appreciated ;-)!
Here is the implementation that I use:
public class CustomLocationProvider implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener, android.location.LocationListener {
private static final float DATA_UPDATE_DISTANCE = 100.0f;
private static final long ONE_MIN = 1000 * 60;
private static final long FIVE_MIN = ONE_MIN * 5;
private static final int UPDATE_TIME = 5000;
private static final int FASTEST_INTERVAL = 16;
private static final int ACCURACY_THRESHOLD = 30;
private Context mContext;
private LocationClient mLocationClient;
private Location mPreviousLocation;
private float mTotalDistance;
private float mDistanceSinceLastUpdate = 0.0f;
private WeakReference<Activity> mDelegate;
public interface LocationProviderDelegate {
void locationUpdated(Location location);
}
// These settings are the same as the settings for the map. They will in fact give you updates
// at the maximal rates currently possible.
private static final LocationRequest REQUEST = LocationRequest.create()
.setInterval(UPDATE_TIME) // 5 seconds
.setFastestInterval(FASTEST_INTERVAL) // 16ms = 60fps
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
public CustomLocationProvider (Context context, Activity delegate) {
if(context != null) {
mContext = context;
mDelegate = new WeakReference<Activity>(delegate);
}
}
public void enableTracking(boolean enable) {
if(enable) {
setUpLocationClientIfNeeded();
mLocationClient.connect();
} else {
if(mLocationClient != null) {
mLocationClient.disconnect();
}
}
}
private void setUpLocationClientIfNeeded() {
if (mLocationClient == null) {
mLocationClient = new LocationClient(
mContext,
this, // ConnectionCallbacks
this); // OnConnectionFailedListener
}
}
#Override
public void onLocationChanged(Location location) {
if(mPreviousLocation != null
&& location.getTime() > mPreviousLocation.getTime()
&& location.getAccuracy() < ACCURACY_THRESHOLD)
{
float distanceIncrement = mPreviousLocation.distanceTo(location);
mDistanceSinceLastUpdate += distanceIncrement;
mTotalDistance += distanceIncrement;
if(mDistanceSinceLastUpdate >= DATA_UPDATE_DISTANCE)
{
mDistanceSinceLastUpdate = 0.0f;
requestDataUpdate(location);
}
updateLocation(location);
} else if( mPreviousLocation == null){
requestDataUpdate(location);
updateLocation(location);
}
}
private void updateLocation(Location location) {
try {
((LocationProviderDelegate) mDelegate.get()).locationUpdated(location);
} catch (Exception e) {
Logger.logError("Cannot cast as a LocationProviderDelegate");
}
mPreviousLocation = location;
}
/**
* Callback called when connected to GCore. Implementation of {#link ConnectionCallbacks}.
*/
#Override
public void onConnected(Bundle connectionHint) {
mLocationClient.requestLocationUpdates(
REQUEST,
this); // LocationListener
Location location = mLocationClient.getLastLocation();
if (location != null) {
if (age(location) < FIVE_MIN) {
mPreviousLocation = location;
requestDataUpdate(location);
}
}
}
/**
* Callback called when disconnected from GCore. Implementation of {#link ConnectionCallbacks}.
*/
#Override
public void onDisconnected() {
// Do nothing
}
/**
* Implementation of {#link OnConnectionFailedListener}.
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Logger.postMessageToTheUser("Connection failed", mDelegate.get());
}
public void Reset(){
mTotalDistance = 0;
}
public float TotalDistance() {
return mTotalDistance;
}
public void requestDataUpdate(Location location)
{
double latitude = location.getLatitude();
double longitude = location.getLongitude();
double offset = 0.002;
LatLngBounds bounds = LatLngBounds.builder()
.include(new LatLng(latitude - offset, longitude - offset))
.include(new LatLng(latitude + offset, longitude + offset))
.build();
updateData();
}
private long age(Location location) {
return System.currentTimeMillis() - location.getTime();
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
String newStatus = "";
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
newStatus = "OUT_OF_SERVICE";
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
newStatus = "TEMPORARILY_UNAVAILABLE";
break;
case LocationProvider.AVAILABLE:
newStatus = "AVAILABLE";
break;
}
String msg = provider + ": " + newStatus;
Logger.postMessageToTheUser(msg, mDelegate.get());
}
}
The LocationClient provided by Google Play Services, uses a fused location provider. This means that it will use the best provider available along with the phone's sensors to give you the most accurate location it can.
It seems from your code that you are disregarding updates if the location accuracy is less than 30m. Remember that even though GPS is the most accurate way to get a location you cannot control how accurate that location is.
Also, calling LocationRequest.create() will create the request with default parameters. I would think you want to call create() last (after setInterval(),etc ) instead of first.
I am using this given below code to get locations:
public Location getLocation() {
try {
mLocationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
// getting GPS status
boolean isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
boolean isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
// First get location from Network Provider
if (isNetworkEnabled) {
mLocationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (mLocationManager != null) {
location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
lat = location.getLatitude();
lng = location.getLongitude();
}
}
}
//get the location by gps
if (isGPSEnabled) {
if (location == null) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (mLocationManager != null) {location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
lat = location.getLatitude();
lng = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
It is working properly, but I would like to get GPS location first, and in case if it is unavailable , location manager should query for Network provider, in which I am getting trouble.
Please, recommend me the good way to do this.
You're saying that you need GPS location first if its available, but what you did is first you're getting location from network provider and then from GPS. This will get location from Network and GPS as well if both are available. What you can do is, write these cases in if..else if block. Similar to-
if( !isGPSEnabled && !isNetworkEnabled) {
// Can't get location by any way
} else {
if(isGPSEnabled) {
// get location from GPS
} else if(isNetworkEnabled) {
// get location from Network Provider
}
}
So this will fetch location from GPS first (if available), else it will try to fetch location from Network Provider.
EDIT:
To make it better, I'll post a snippet. Consider it is in try-catch:
boolean gps_enabled = false;
boolean network_enabled = false;
LocationManager lm = (LocationManager) mCtx
.getSystemService(Context.LOCATION_SERVICE);
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
Location net_loc = null, gps_loc = null, finalLoc = null;
if (gps_enabled)
gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (network_enabled)
net_loc = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (gps_loc != null && net_loc != null) {
//smaller the number more accurate result will
if (gps_loc.getAccuracy() > net_loc.getAccuracy())
finalLoc = net_loc;
else
finalLoc = gps_loc;
// I used this just to get an idea (if both avail, its upto you which you want to take as I've taken location with more accuracy)
} else {
if (gps_loc != null) {
finalLoc = gps_loc;
} else if (net_loc != null) {
finalLoc = net_loc;
}
}
Now you check finalLoc for null, if not then return it.
You can write above code in a function which returns the desired (finalLoc) location. I think this might help.
The recommended way to do this is to use LocationClient:
First, define location update interval values. Adjust this to your needs.
private static final int MILLISECONDS_PER_SECOND = 1000;
private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
Have your Activity implement GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, and LocationListener.
public class LocationActivity extends Activity implements
GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {}
Then, set up a LocationClientin the onCreate() method of your Activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLocationClient = new LocationClient(this, this, this);
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
}
Add the required methods to your Activity; onConnected() is the method that is called when the LocationClientconnects. onLocationChanged() is where you'll retrieve the most up-to-date location.
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.w(TAG, "Location client connection failed");
}
#Override
public void onConnected(Bundle dataBundle) {
Log.d(TAG, "Location client connected");
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
#Override
public void onDisconnected() {
Log.d(TAG, "Location client disconnected");
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.d(TAG, "Updated Location: " + Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude()));
} else {
Log.d(TAG, "Updated location NULL");
}
}
Be sure to connect/disconnect the LocationClient so it's only using extra battery when absolutely necessary and so the GPS doesn't run indefinitely. The LocationClient must be connected in order to get data from it.
public void onResume() {
super.onResume();
mLocationClient.connect();
}
public void onStop() {
if (mLocationClient.isConnected()) {
mLocationClient.removeLocationUpdates(this);
}
mLocationClient.disconnect();
super.onStop();
}
Get the user's location. First try using the LocationClient; if that fails, fall back to the LocationManager.
public Location getLocation() {
if (mLocationClient != null && mLocationClient.isConnected()) {
return mLocationClient.getLastLocation();
} else {
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocationGPS != null) {
return lastKnownLocationGPS;
} else {
return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
} else {
return null;
}
}
}
Main Class:
public class AndroidLocationActivity extends Activity {
Button btnGPSShowLocation;
Button btnNWShowLocation;
AppLocationService appLocationService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appLocationService = new AppLocationService(
AndroidLocationActivity.this);
btnGPSShowLocation = (Button) findViewById(R.id.btnGPSShowLocation);
btnGPSShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Location gpsLocation = appLocationService
.getLocation(LocationManager.GPS_PROVIDER);
if (gpsLocation != null) {
double latitude = gpsLocation.getLatitude();
double longitude = gpsLocation.getLongitude();
Toast.makeText(
getApplicationContext(),
"Mobile Location (GPS): \nLatitude: " + latitude
+ "\nLongitude: " + longitude,
Toast.LENGTH_LONG).show();
} else {
showSettingsAlert("GPS");
}
}
});
btnNWShowLocation = (Button) findViewById(R.id.btnNWShowLocation);
btnNWShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Location nwLocation = appLocationService
.getLocation(LocationManager.NETWORK_PROVIDER);
if (nwLocation != null) {
double latitude = nwLocation.getLatitude();
double longitude = nwLocation.getLongitude();
Toast.makeText(
getApplicationContext(),
"Mobile Location (NW): \nLatitude: " + latitude
+ "\nLongitude: " + longitude,
Toast.LENGTH_LONG).show();
} else {
showSettingsAlert("NETWORK");
}
}
});
}
public void showSettingsAlert(String provider) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
AndroidLocationActivity.this);
alertDialog.setTitle(provider + " SETTINGS");
alertDialog.setMessage(provider
+ " is not enabled! Want to go to settings menu?");
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
AndroidLocationActivity.this.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Next Class:
public class AppLocationService extends Service implements LocationListener {
protected LocationManager locationManager;
Location location;
private static final long MIN_DISTANCE_FOR_UPDATE = 10;
private static final long MIN_TIME_FOR_UPDATE = 1000 * 60 * 2;
public AppLocationService(Context context) {
locationManager = (LocationManager) context
.getSystemService(LOCATION_SERVICE);
}
public Location getLocation(String provider) {
if (locationManager.isProviderEnabled(provider)) {
locationManager.requestLocationUpdates(provider,
MIN_TIME_FOR_UPDATE, MIN_DISTANCE_FOR_UPDATE, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(provider);
return location;
}
}
return null;
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
Don't forget to add in your manifest.
<!-- to get location using GPS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- to get location using NetworkProvider -->
<uses-permission android:name="android.permission.INTERNET" />
use the fusion API that google developer have developed with fusion of GPS Sensor,Magnetometer,Accelerometer also using Wifi or cell location to calculate or estimate the location. It is also able to give location updates also inside the building accurately.
package com.example.ashis.gpslocation;
import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Location sample.
*
* Demonstrates use of the Location API to retrieve the last known location for a device.
* This sample uses Google Play services (GoogleApiClient) but does not need to authenticate a user.
* See https://github.com/googlesamples/android-google-accounts/tree/master/QuickStart if you are
* also using APIs that need authentication.
*/
public class MainActivity extends Activity implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final long ONE_MIN = 500;
private static final long TWO_MIN = 500;
private static final long FIVE_MIN = 500;
private static final long POLLING_FREQ = 1000 * 20;
private static final long FASTEST_UPDATE_FREQ = 1000 * 5;
private static final float MIN_ACCURACY = 1.0f;
private static final float MIN_LAST_READ_ACCURACY = 1;
private LocationRequest mLocationRequest;
private Location mBestReading;
TextView tv;
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!servicesAvailable()) {
finish();
}
setContentView(R.layout.activity_main);
tv= (TextView) findViewById(R.id.tv1);
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(POLLING_FREQ);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_FREQ);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onPause() {d
super.onPause();
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
tv.setText(location + "");
// Determine whether new location is better than current best
// estimate
if (null == mBestReading || location.getAccuracy() < mBestReading.getAccuracy()) {
mBestReading = location;
if (mBestReading.getAccuracy() < MIN_ACCURACY) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}
#Override
public void onConnected(Bundle dataBundle) {
// Get first reading. Get additional location updates if necessary
if (servicesAvailable()) {
// Get best last location measurement meeting criteria
mBestReading = bestLastKnownLocation(MIN_LAST_READ_ACCURACY, FIVE_MIN);
if (null == mBestReading
|| mBestReading.getAccuracy() > MIN_LAST_READ_ACCURACY
|| mBestReading.getTime() < System.currentTimeMillis() - TWO_MIN) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
//Schedule a runnable to unregister location listeners
#Override
public void run() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, MainActivity.this);
}
}, ONE_MIN, TimeUnit.MILLISECONDS);
}
}
}
#Override
public void onConnectionSuspended(int i) {
}
private Location bestLastKnownLocation(float minAccuracy, long minTime) {
Location bestResult = null;
float bestAccuracy = Float.MAX_VALUE;
long bestTime = Long.MIN_VALUE;
// Get the best most recent location currently available
Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
//tv.setText(mCurrentLocation+"");
if (mCurrentLocation != null) {
float accuracy = mCurrentLocation.getAccuracy();
long time = mCurrentLocation.getTime();
if (accuracy < bestAccuracy) {
bestResult = mCurrentLocation;
bestAccuracy = accuracy;
bestTime = time;
}
}
// Return best reading or null
if (bestAccuracy > minAccuracy || bestTime < minTime) {
return null;
}
else {
return bestResult;
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
private boolean servicesAvailable() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == resultCode) {
return true;
}
else {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0).show();
return false;
}
}
}
If you want to run inside a background service and take the data in foreground use the below one, it is tested and verified.
public class MyService extends Service
implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener {
private static final int ASHIS = 1234;
Intent intentForPendingIntent;
HandlerThread handlerThread;
Looper looper;
GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRrequest;
private static final int UPDATE_INTERVAL = 1000;
private static final int FASTEST_INTERVAL = 100;
private static final int DSIPLACEMENT_UPDATES = 1;
;
private Handler handler1;
private Runnable runable1;
private Location mLastLocation;
private float waitingTime;
private int waiting2min;
private Location locationOld;
private double distance;
private float totalWaiting;
private float speed;
private long timeGpsUpdate;
private long timeOld;
private NotificationManager mNotificationManager;
Notification notification;
PendingIntent resultPendingIntent;
NotificationCompat.Builder mBuilder;
// Sets an ID for the notification
int mNotificationId = 001;
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "speedExceeded";
private final Handler handler = new Handler();
Intent intentforBroadcast;
int counter = 0;
private Runnable sendUpdatesToUI;
#Nullable
#Override
public IBinder onBind(Intent intent) {
Toast.makeText(MyService.this, "binder", Toast.LENGTH_SHORT).show();
return null;
}
#Override
public void onCreate() {
showNotification();
intentforBroadcast = new Intent(BROADCAST_ACTION);
Toast.makeText(MyService.this, "created", Toast.LENGTH_SHORT).show();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
createLocationRequest();
mGoogleApiClient.connect();
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void showNotification() {
mBuilder =
(NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_media_play)
.setContentTitle("Total Waiting Time")
.setContentText(totalWaiting+"");
Intent resultIntent = new Intent(this, trackingFusion.class);
// Because clicking the notification opens a new ("special") activity, there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, mBuilder.build());
startForeground(001, mBuilder.getNotification());
}
#Override
public void onLocationChanged(Location location) {
//handler.removeCallbacks(runable);
Toast.makeText(MyService.this, "speed" + speed, Toast.LENGTH_SHORT).show();
timeGpsUpdate = location.getTime();
float delta = (timeGpsUpdate - timeOld) / 1000;
if (location.getAccuracy() < 100) {
speed = location.getSpeed();
distance += mLastLocation.distanceTo(location);
Log.e("distance", "onLocationChanged: " + distance);
//mLastLocation = location;
//newLocation = mLastLocation;
Log.e("location:", location + "");
//speed = (long) (distance / delta);
locationOld = location;
mLastLocation = location;
diaplayViews();
}
diaplayViews();
/*if (map != null) {
map.addMarker(new MarkerOptions()
.position(new LatLng(location.getLatitude(), location.getLongitude()))
.title("Hello world"));
}*/
}
private void createLocationRequest() {
mLocationRrequest = new LocationRequest();
mLocationRrequest.setInterval(UPDATE_INTERVAL);
mLocationRrequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRrequest.setSmallestDisplacement(DSIPLACEMENT_UPDATES);
}
private void methodToCalculateWaitingTime() {
if (handler1 != null) {
handler1.removeCallbacks(runable1);
}
Log.e("Here", "here1");
handler1 = new Handler(Looper.getMainLooper());
runable1 = new Runnable() {
public void run() {
Log.e("Here", "here2:" + mLastLocation.getSpeed());
if (mLastLocation != null) {
diaplayViews();
if ((mLastLocation.getSpeed() == 0.0)) {
increaseTime();
} else {
if (waitingTime <= 120) {
waiting2min = 0;
}
}
handler1.postDelayed(this, 10000);
} else {
if (ActivityCompat.checkSelfPermission(MyService.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MyService.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationOld = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastLocation = locationOld;
}
}
};
handler1.postDelayed(runable1, 10000);
}
private void diaplayViews() {
float price = (float) (14 + distance * 0.5);
//textDistance.setText(waitingTime);a
}
private void increaseTime() {
waiting2min = waiting2min + 10;
if (waiting2min >= 120)
{
if (waiting2min == 120) {
waitingTime = waitingTime + 2 * 60;
} else {
waitingTime = waitingTime + 10;
}
totalWaiting = waitingTime / 60;
showNotification();
Log.e("waiting Time", "increaseTime: " + totalWaiting);
}
}
#Override
public void onDestroy() {
Toast.makeText(MyService.this, "distroyed", Toast.LENGTH_SHORT).show();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(Bundle bundle) {
Log.e("Connection_fusion", "connected");
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
}
private void startLocationUpdates() {
Location location = plotTheInitialMarkerAndGetInitialGps();
if (location == null) {
plotTheInitialMarkerAndGetInitialGps();
} else {
mLastLocation = location;
methodToCalculateWaitingTime();
}
}
private Location plotTheInitialMarkerAndGetInitialGps() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return null;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRrequest, this);
locationOld = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if ((locationOld != null)) {
mLastLocation = locationOld;
timeOld = locationOld.getTime();
} else {
startLocationUpdates();
}
return mLastLocation;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
Toast.makeText(MyService.this, "start command", Toast.LENGTH_SHORT).show();
sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 10000); // 5 seconds
}
};
handler.postDelayed(sendUpdatesToUI, 10000); // 1 second
Log.i("LocalService", "Received start id " + startId + ": " + intent);
return START_NOT_STICKY;
}
#Override
public void onStart(Intent intent, int startId) {
sendUpdatesToUI = new Runnable() {
public void run() {
Log.e("sent", "sent");
DisplayLoggingInfo();
handler.postDelayed(this, 5000); // 5 seconds
}
};
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
Log.i("LocalService", "Received start id " + startId + ": " + intent);
super.onStart(intent, startId);
}
private void DisplayLoggingInfo() {
Log.d(TAG, "entered DisplayLoggingInfo");
intentforBroadcast.putExtra("distance", distance);
LocalBroadcastManager.getInstance(this).sendBroadcast(intentforBroadcast);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onMapReady(GoogleMap googleMap) {
}
}
I made some changes in above code to look for a location fix by both GPS and Network for about 5sec and give me the best known location out of it.
public class LocationService implements LocationListener {
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
final static long MIN_TIME_INTERVAL = 60 * 1000L;
Location location;
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1; // 1 minute
protected LocationManager locationManager;
private CountDownTimer timer = new CountDownTimer(5 * 1000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
stopUsingGPS();
}
};
public LocationService() {
super(R.id.gps_service_id);
}
public void start() {
if (Utils.isNetworkAvailable(context)) {
try {
timer.start();
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
Location tempLocation = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (tempLocation != null
&& isBetterLocation(tempLocation,
location))
location = tempLocation;
}
}
if (isGPSEnabled) {
locationManager.requestSingleUpdate(
LocationManager.GPS_PROVIDER, this, null);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
Location tempLocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (tempLocation != null
&& isBetterLocation(tempLocation,
location))
location = tempLocation;
}
}
} catch (Exception e) {
onTaskError(e.getMessage());
e.printStackTrace();
}
} else {
onOfflineResponse(requestData);
}
}
public void stopUsingGPS() {
if (locationManager != null) {
locationManager.removeUpdates(LocationService.this);
}
}
public boolean canGetLocation() {
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
return isGPSEnabled || isNetworkEnabled;
}
#Override
public void onLocationChanged(Location location) {
if (location != null
&& isBetterLocation(location, this.location)) {
this.location = location;
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public Object getResponseObject(Object location) {
return location;
}
public static boolean isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > MIN_TIME_INTERVAL;
boolean isSignificantlyOlder = timeDelta < -MIN_TIME_INTERVAL;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location,
// use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must
// be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
}
In the above class, I am registering a location listener for both GPS and network, so an onLocationChanged call back can be called by either or both of them multiple times and we just compare the new location fix with the one we already have and keep the best one.
there are better ways to do it as mentioned on android developer sites
http://developer.android.com/guide/topics/location/strategies.html