why getSpeed() always return 0 on android
There is my custom LocationListener used to get speed manually and by location object if has speed.
new LocationListener() {
private Location mLastLocation;
@Override
public void onLocationChanged(Location pCurrentLocation) {
//calcul manually speed
double speed = 0;
if (this.mLastLocation != null)
speed = Math.sqrt(
Math.pow(pCurrentLocation.getLongitude() - mLastLocation.getLongitude(), 2)
+ Math.pow(pCurrentLocation.getLatitude() - mLastLocation.getLatitude(), 2)
) / (pCurrentLocation.getTime() - this.mLastLocation.getTime());
//if there is speed from location
if (pCurrentLocation.hasSpeed())
//get location speed
speed = pCurrentLocation.getSpeed();
this.mLastLocation = pCurrentLocation;
////////////
//DO WHAT YOU WANT WITH speed VARIABLE
////////////
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
};
On a spherical planet distance should be calculated with these formulas :
private static Double distance(Location one, Location two) {
int R = 6371000;
Double dLat = toRad(two.getLatitude() - one.getLatitude());
Double dLon = toRad(two.getLongitude() - one.getLongitude());
Double lat1 = toRad(one.getLatitude());
Double lat2 = toRad(two.getLatitude());
Double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
Double d = R * c;
return d;
}
private static double toRad(Double d) {
return d * Math.PI / 180;
}
Imbru's answer looks really good, but it is not very helpful if you are working with units.
Here's what I did to calculate the speed in meters per second (m/s).
object : LocationListener() {
var previousLocation: Location? = null
override fun onLocationChanged(location: Location) {
val speed = if (location.hasSpeed()) {
location.speed
} else {
previousLocation?.let { lastLocation ->
// Convert milliseconds to seconds
val elapsedTimeInSeconds = (location.time - lastLocation.time) / 1_000.
val distanceInMeters = lastLocation.distanceTo(location)
// Speed in m/s
distanceInMeters / elapsedTimeInSeconds
} ?: 0.0
}
previousLocation = location
/* There you have it, a speed value in m/s */
functionThatUsesSpeedInMeterPerSecond(speed)
. . .
}
. . .
}
location.getSpeed() only returns what was set with location.setSpeed(). This is a value that you can set for a location object.
To calculate the speed using GPS, you'll have to do a little math:
Speed = distance / time
So you would need to do:
(currentGPSPoint - lastGPSPoint) / (time between GPS points)
All converted to ft/sec, or however you want to show the speed. This is how I did it when I made a runner app.
More specifically, you'll need to calculate for absolute distances:
(sqrt((currentGPSPointX - lastGPSPointX)^2) + (currentGPSPointY - lastGPSPointY)^2)) / (time between GPS points)
It might help to make a new TrackPoint class or something, which keeps the GPS location and time it was taken inside.