How to get accurate GPS Coordinates Android LocationServices - android

I am just trying to figure out what can I do to ensure I get precise GPS Coordinates from the mobile device. When I add the distances together, I get a crazy reading that I have gone 8m when the phone has not moved from my table. I do not know if it is because of the way I have set up my LocationRequest. I was reading on google something about GPS coordinates being 68% accurate, and some readings may fall out of the 68%... perhaps I should do something to remove the inaccurate readings??
Here is the location request I have created, so I can receive the location updates:
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(2000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
//Some other code below which checks location settings
}
This is my onLocationChanged... this is where I get updates of the new location, and then calculate the distance between the two points:
#Override
public void onLocationChanged(Location location) {
//For the first location update, we will assume this is the starting point
if (currentLocation == null) {
currentLocation = location;
}
float distance = 0L;
double height = 0;
double speed = 0;
height = location.getAltitude();
if (runStarted && !runPaused) {
locationsList.add(location); //This adds the current location to the list
runnerLocations.add(location); //This adds the current route the runner is running (without pauses)
} else {
locationsList.add(location);
}
//Calculate the distance from the last recorded gps point
if (currentLocation != null && runStarted && !runPaused){
distance = currentLocation.distanceTo(location);
}
currentLocation = location;
//move the map view to the user's current location, regardless of their running state (paused or run)
mapObject.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 18));
if (runStarted && !runPaused) {
if (location.getSpeed() > 0) {
speed = location.getSpeed() * 3.6;// convert m/sec to km/h
}
DecimalFormat format = new DecimalFormat("###.##");
speed = Double.valueOf(format.format(speed));
recordedSpeeds.add(speed);
totalDistance = totalDistance + distance;
updateUI(speed, location, distance);
if (height > 0) {
height = Double.valueOf(format.format(height));
}
calculateCurrentCaloriesBurnt(height, speed);
}
}
I was thinking of calculating the distances manually, with some formula. What else can I try, to get accurate distance calculations?

Related

Finding out if a phone's current longitude and latitude is within the radius of a gps location

I'm hoping someone can help with this.
I've seen many posts and answers but none of them seem to address my specific problem, but if I've missed one, I apologise in advance.
I'm building a small app that stores a phones current longitude and latitude as doubles. This is done via android's LocationManager
#TargetApi(23)
private void initLocationService(Context context) {
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
this.longitude = 0.0;
this.latitude = 0.0;
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// Get GPS and network status
this.isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
this.isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (forceNetwork) isGPSEnabled = false;
if (!isNetworkEnabled && !isGPSEnabled) {
// cannot get location
this.locationServiceAvailable = false;
}
else
{
this.locationServiceAvailable = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateCoordinates();
}
}//end if
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateCoordinates();
}
}
}
} catch (Exception ex) {
}
}
public void updateCoordinates()
{
longitude = location.getLongitude();
latitude = location.getLatitude();
}
I've got a set of longitude and latitude coordinates hardcoded into the app, but need a way to work out if my user is within a specific metre radius of a hardcoded point.
I'm using just the Android API's for the project and can't deviate from that.
I've already found out how to convert the longitude and latitude from degrees to metres:
public double longOffset(int offsetX, double lon){
double longoff = offsetX / earthRadius;
return lon + longoff * 180 / Math.PI;
}
public double latOffset(int offsetY, double lat){
double latoff = offsetY / (earthRadius * cos(Math.PI*lat/180));
return lat + latoff * 180 / Math.PI;
}
But I admit to being stumped on the rest.
I'm wondering if creating a small bounding box around the longitude and latitude and then using a method similar to the one shown here:
http://www.sanfoundry.com/java-program-check-whether-given-point-lies-given-polygon/
I'm getting to the point now where i'm going crosseyed so any help would be appreciated.
Like #EugenPechanec says, you can use SphericalUtil.computeDistanceBetween() from Google Maps Android API utility library . Something like this:
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double longitude = location.getLongitude();
double latitude = location.getLatitude();
LatLng positionLatLng = new LatLng(latitude, longitude);
// sample hardcoded point.
LatLng specificPointLatLang = new LatLng(1.333434, 1.3333);
// Returns the distance between two LatLngs, in meters.
double distance = SphericalUtil.computeDistanceBetween(positionLatLng, specificPointLatLang);

How to get always the newest current Coordinates

I am trying to calculate the distance between your current location and three markers.
Everything is working fine, but if I change my position the distance is equal to the distance before, I dont get the new coordinates. Here is my code:
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location current = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, true));
latng = String.valueOf(current.getLatitude());
lngon = String.valueOf(current.getLongitude());
Location club = new Location("clubloc");
club.setLatitude(Double.parseDouble(marker_data.get("lat")));
club.setLongitude(Double.parseDouble(marker_data.get("lng")));
double distance = current.distanceTo(club);
distance = distance / 1000;
distance = Math.round(distance * 100);
distance = distance / 100;
TextView dis = (TextView) findViewById(R.id.distance);
dis.setText(String.valueOf(distance) + "KM");
}
So my question is how can I update my coordinates so I always get the right distance?
You are always getting the last known location of the user (using getLastKnownLocation). You are not actively asking for location updates. You can read more about this here.

I can't get the speed of the user, have tried many methods

I've been currently trying to get the speed of the user.
I've got the location and time of the two points, but it seems that I just kind find the correct way to calculate the speed, despite many attempts.
This is what I am trying right now:
public void onLocationChanged(Location location) {
Toast.makeText(this, "Location Changed", Toast.LENGTH_SHORT).show();
if (settings == null) {
settings = getSharedPreferences(PREFS_NAME, 0);
}
int ExceedingLimit = settings.getInt("ExceedLimit", 10);
int LowerLimit = settings.getInt("LowerLimit", 2);
int UpperLimit = settings.getInt("UpperLimit", 12);
double speed = 0;
if (location != null) {
double calc_long = Math.pow(location.getLongitude() - OldLocation.getLongitude(), 2);
double calc_lat = Math.pow(location.getLatitude() - OldLocation.getLatitude(), 2);
double time = (double) location.getTime() - (double) OldLocation.getTime();
speed = Math.sqrt(calc_long + calc_lat) / time;
}
if (location != null && location.hasSpeed()) {
speed = location.getSpeed();
}
if (LowerLimit < speed && speed < UpperLimit) {
ExceedInstance += 1;
}
OldLocation = location;
It doesn't seem to work, as it stays on zero even when moving.
I initialise Old Location here:
public void onConnected(Bundle connectionHint) {
Toast.makeText(this, "You have connected", Toast.LENGTH_LONG).show();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(UPDATE_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mLocationClient, mLocationSettingsRequest
);
result.setResultCallback(ViewingWindow.this);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, this);
OldLocation = LocationServices.FusedLocationApi.getLastLocation(mLocationClient);
}
}
I've also attempted calculate the two separately and dividing the two, but it ended up as a casting error and it still stayed on zero.
Casting doesn't work either. When I cast it to double, it gives me E-10 to E-11 numbers, absurdly low but still changing every time the location updates.
The problem is, even when I move the speed doesn't go but.
I actually have no idea why any of this is wrong. Can someone help me?
Did you try to cast the needed time to double ?
speed = (double)Math.sqrt(
Math.pow(location.getLongitude() - OldLocation.getLongitude(), 2)
+ Math.pow(location.getLatitude() - OldLocation.getLatitude(), 2)
) / (double)(location.getTime() - OldLocation.getTime());
Because i dont know what the Math.sqrt() returns. It may be returnes a float because it is much faster in caculation.
If your speed isnt to high you can also change the speed variable to float.
Try this
double calc_long = Math.pow(location.getLongitude() - OldLocation.getLongitude(), 2);
double calc_lat = Math.pow(location.getLatitude() - OldLocation.getLatitude(), 2);
double time = location.getTime() - OldLocation.getTime();
speed = (double) Math.sqrt(calc_long + calc_lat) / time;
Also, how do you test the speed? From my experience longitude and latitude need a few seconds to update and register any move, so if you try to keep a constant speed for around a minute (doesn't matter how) it should trigger the speed meter.

getting gps updates in constant location also?

I am in constant location but i am getting gps updates continuosly and plot the line in constant location also.How to stop gps updates in constant location?
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
getActivity().runOnUiThread(new Runnable() {
public void run() {
gps = new GPSTracker(getActivity());
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
if(latitude>0.0&&longitude>0.0){
Toast.makeText(
getActivity(),
"Your Location is - \nLat: " + latitude
+ "\nLong: " + longitude,
Toast.LENGTH_SHORT).show();
}
// Creating a LatLng object for the current location
LatLng latLng = new LatLng(latitude, longitude);
RouteManager.sourceMarker(getActivity(), latLng,
googleMap, markpos, 0);
markpos++;
points.add(latLng);// addding Latlng to points array
Log.d("pointssize", "pointskal--->" + points.size());
Double distance = 0.0;
//if more than one point we can find duplicate points getting or not,if getting duplicate we remove duplicate point
if (points.size() > 1) {
// 2.comparing prev and nextlatitudes and longitudes
boolean duplicate = routemanage.isDuplicate(points,
googleMap);
if (duplicate) {
points.remove(points.size() - 1);
Log.d("pointssize", "pointskalremnoveafter--->"
+ points.size());
duplicate = false;
} else {
int size = points.size();
//if not duplicate we can find out the distance
distance = routemanage.findDistanceOnRoute(
points.get(size - 2).latitude,
points.get(size - 2).longitude,
points.get(size - 1).latitude,
points.get(size - 1).longitude);
Log.d("sorrry", "distance initaial" + distance);
if (distance < 1) {
//if distance is less than 1 meter we simply remove the point
points.remove(points.size() - 1);
Log.d("pointssize",
"distance lessthan 1--->"
+ points.size());
} else {
// we have to check distance >1 m we can draw the route
sum = sum + distance;
RouteManager.drawRoute(getActivity(),
points, googleMap, sum);
Log.d("sorrry", "sorry dad sum" + sum);
settingmaprunDetails(points.get(size - 1),
sum);
}
duplicate = true;
}// else
}// if
//if points size is <=1 we can't draw the route
else if (points.size() == 1) {
settingmaprunDetails(points.get(0), 0.0);
}
}
I am attaching screen shot please see once and give me solution to avoid this clumsy ness of plotting the route on google map.
you can set Smallest Displacement somewhere in your GPSTracker (where the locationManager) is created. For example:
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Set the Smallest Displacement sets the minimum displacement between location updates in meters. By default this is 0. You can reduce the signal jitter using this with a reasonable value.

Tracking distance with "distanceBetween" is wrong and driving me nuts

I have trouble with the tracking of a driven distance.
I tried it like in this article: Source-Code is completely also there
The SUM of the driven distance is not the real driven distance that is displayed in my car.
After 2-3 km, I have a difference between my displayed distance in my car and the app of 200-800 meters. In this short distance :o)
What I also recognized is that the distance, e.g. while driving curves, is decrementing.
I have also tried several values for minTime and minDistance for the listener, but no success.
What I am doing wrong?
When I use the "MyTracks" app, the driven distance is caculated really, really fine and correct.
I only need a way to sum the completely driven way from start to end, without displaying it in google maps. Is this really so complicated?
kind regards
Frank
OK, the interesting part of the code:
public void startListening(final Activity activity)
{
if (locationManager == null)
{
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
}
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
final String bestProvider = locationManager.getBestProvider(criteria, true);
if (bestProvider != null && bestProvider.length() > 0)
{
locationManager.requestLocationUpdates(bestProvider, GPSManager.gpsMinTime,
GPSManager.gpsMinDistance, locationListener);
}
else
{
final List<String> providers = locationManager.getProviders(true);
for (final String provider : providers)
{
locationManager.requestLocationUpdates(provider, GPSManager.gpsMinTime,
GPSManager.gpsMinDistance, locationListener);
}
}
}
and:
private double calcGeoDistance(final double lat1, final double lon1, final double lat2, final double lon2)
{
double distance = 0.0;
try
{
final float[] results = new float[3];
Location.distanceBetween(lat1, lon1, lat2, lon2, results);
distance = results[0];
}
catch (final Exception ex)
{
distance = 0.0;
}
return distance;
}
and:
private void updateMeasurement(){
double distance = calcGeoDistance(startLat,startLon,currentLat,currentLon) * multipliers[unitindex];
String distanceText = "" + RoundDecimal(distance,2) + " " + unitstrings[unitindex];
((TextView)findViewById(R.id.distance)).setText(distanceText);
}
and:
public double RoundDecimal(double value, int decimalPlace)
{
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(decimalPlace, 6);
return bd.doubleValue();
}
Ohhh, and as I am writing this down it seems that the distance is caculated between the start point and the current point. Not between the last two measurements with the sum of all values, right?
With the Criteria that you specify, you're likely to get innacurate locations. Increase the power requirement. Also, pay attention to the name of the provider being returned. If you want accuracy, then you're going to want the GPS provider.
See the following link for more information:
I keep getting an inaccurate location in Android

Categories

Resources