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.
Related
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?
Trying to create a running gps in android, using this code to calculate the distance between two points every second (at least that's what I think it's doing):
gps = new GPSTracker(AndroidGPSTrackingActivity.this);
// check if GPS enabled
if (gps.canGetLocation()) {
final Handler h = new Handler();
final int delay = 1000; //milliseconds
h.postDelayed(new Runnable() {
public void run() {
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
Location locationA = new Location("point A");
final Location locationB = new Location("point B");
locationA.setLatitude(latitude);
locationA.setLongitude(longitude);
Timer t = new Timer();
h.postDelayed(new Runnable() {
public void run() {
double latitude1 = gps.getLatitude();
double longitude2 = gps.getLongitude();
locationB.setLatitude(latitude1);
locationB.setLongitude(longitude2);
}
}, delay);
float distance = locationA.distanceTo(locationB);
finalDistance[0] = (finalDistance[0] + distance);
displayDistance.setText(String.valueOf(finalDistance[0]));
h.postDelayed(this, delay);
}
}, delay);
The distance changes more or less by the same increment whether I'm walking or not walking.
The distance I get is also a weird value, e.g.: 6.47875890357E9
My questions: 1)What unit is this distance in?
2)Am I getting some random gobbledigook because of crap programming skills?
1) The units are meters (see distanceTo()).
2) Yes. But like all programmers, you're still learning, so to be more helpful I won't just leave it there! The reason you are getting a huge distance is because your code is getting the distance between locationA and locationB, and you haven't set locationB at the time you execute the line:
float distance = locationA.distanceTo(locationB);
So you're getting the distance between locationA and lat/long 0,0.
You're only setting the latitude and longitude of locationB in your Runnable which will be executed after distance has been set. So, you probably need to move your distance calculation and the code that outputs it to within your Runnable that sets the latitude and longitude for locationB. You'll also have to make locationA final to do that.
I have used the following code to check GPS coordinates, but problem is that if i am standing at same place the coordinates changes and distance is anywhere between 4 to 20 mts.
I want to change it only when I have moved min 10 mtrs.
locationManager_gps = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
locationManager_gps.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0,
new MyLocationListener_gps());
class MyLocationListener_gps implements LocationListener {
public void onLocationChanged(Location location) {
clat = location.getLatitude();
clon = location.getLongitude();
if (clat != plat || clon != plon) {
float[] results = new float[3];
Location.distanceBetween(plat, plon, clat, clon, results);
if (flag_gps == 0) {
flag_gps = 1;
} else {
GeoPoint geoPoint = new GeoPoint((int) (clat * 1E6),
(int) (clon * 1E6));
mapView.getController().animateTo(geoPoint);
draw = new MyOverLay(geoPoint);
mapView.getOverlays().add(draw);
dist_mtr += results[0];
}
plat = clat;
plon = clon;
}
}
If I use 50 as min distance between updates then it is working fine. I also tried making it 30 but also data was wrong over a period of 4 km while traveling in car.
Please suggest what I should do.
I've seen this too, when taking several location readings and I haven't moved. You can get variable results with different accuracies.
You could try taking, say, 10 location readings and take the one with the best accuracy and disregard the rest. Then when taking the next reading, make sure it is located at a distance which is twice the accuracy of the previous location. For example, if your first location has an accuracy of, say 16 meters, make sure the next reading is at least 32 meters away from the previous location AND has an accuracy better than 32 meters.
You need to use the minTime and minDistance in combination. You pass zero and zero for both, so the min time between updates will be at least zero seconds and the min distance will be zero. So set minTime to a reasonable time and minDistance to 10 for ten meters.
locationManager_gps.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0,
new MyLocationListener_gps());
There is no magic bullet to solve this... the gps is not 100% accurate and you will always have different readings every time you get a new location update.
You can minimize the issue using a low pass filter for the location values:
clat = plat + (clat-plat) * 0.2; // you should adjust the 0.2 value to the best results
clon = plon + (clon-plon) * 0.2;
....
//your code
....
plat = clat;
plon = clon;
With this the effect of sudden changes to the values will be minimized, which is good for the fake changes in position, but it will also delay the response to the real changes in the positions when the device is moving. You should choose careffuly the value of the constant multiplying (0.2 above) to have the best results.
You can even do better, using a variable instead of a constant, and adjust the value of it based on the accuracy of the loaction update (good accuracy you make the variable close to 1, pour accuracy you make the variable close to 0)
good luck
I am new in android, I want to know how can I calculate the area of a Map in miles on Zoom Level, so that I can call my web service and make a marker according to the distance of my current location.
Your question slightly confusing, area and distance are two different things.
Use the Location.distanceTo function to calculate distance between two points on the map.
OverlayItem item = mOverlays.get(index);
GeoPoint mPoint = item.getPoint(); // get Point of your marker
Location locationMy = m_MyLocationOverlay.getLastFix(); // get current location
if (locationMy != null)
{
Location locationPoint = new Location(locationMy);
locationPoint.setLatitude((double)mPoint.getLatitudeE6() / 1000000.0f);
locationPoint.setLongitude((double)mPoint.getLongitudeE6() / 1000000.0f);
String str = String.format("%.1f miles", locationMy.distanceTo(locationPoint) * 0.000621371192); // meters to miles
}
Im using this code for getting the location for my app:
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 200.0f, this);
But when i tried the app in my real android phone it show this location about 80 kilometers away from the location im actualy at.. How would i make this code more accurate.. I want the result to be way more accurate for what im making..
Im using the onLocationChanged to display it at the map.. Here it is:
public void onLocationChanged(Location location) {
if (location != null) {
//Gets users longitude and latitude
lat = location.getLatitude();
lng = location.getLongitude();
//sets the GeoPoint usersLocation equal lat and lng
userLocation = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
OverlayItem usersLocationIcon = new OverlayItem(userLocation, null, null);
LocationPin myLocationPin = new LocationPin(userIcon, MainActivity.this);
//Removes the previous location
if(previousLocation != null)
mainMap.getOverlays().remove(previousLocation);
myLocationPin.getLocation(usersLocationIcon);
overlayList.add(myLocationPin);
//refresh the map
mainMap.invalidate();
//Making myLocationPin into the previousLocation just to be able to remove it later
previousLocation = myLocationPin;
}
The call requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 200.0f, this); is asking to be updated no more than once every 1000ms when the location from GPS changes by more than 200.0 meters from the last update. If you want finer precision, try lowering these numbers.
However, you shouldn't be off by 80km. Are you testing this outside with a clear view of the sky?
I think the issue is with rounding. You are using new GeoPoint((int) lat * 1000000, (int) lng * 1000000);, but instead do this:
new GeoPoint((int) (lat * 1e6), (int) (lng * 1e6));
The difference is, the double values were converted to integers before the multiplication. This way the multiplication happens afterwards, and so the digits after the decimal point are maintained.
There are 2 possible answers...
You can either ask for fine permission, this uses nearby wi-fi networks along with GPS in order to get a better track on where you are:
http://developer.android.com/reference/android/Manifest.permission.html#ACCESS_FINE_LOCATION
or you might just be getting bad GPS data. Have you tried to restart the phone? Are you getting the correct location in Google Maps?
Hope this helps.