可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I need to get the speed and heading from the gps. However the only number i have from location.getSpeed()
is 0 or sometimes not available. my code:
String provider = initLocManager(); if (provider == null) return false; LocationListener locListener = new LocationListener() { public void onLocationChanged(Location location) { updateWithNewLocation(location, interval, startId); Log.i(getString(R.string.logging_tag), "speed =" + location.getSpeed()); } public void onProviderDisabled(String provider){ updateWithNewLocation(null, interval, startId); } public void onProviderEnabled(String provider) {} public void onStatusChanged(String provider, int status, Bundle extras) {} }; _locManager.requestLocationUpdates(provider, interval, DEFAULT_GPS_MIN_DISTANCE, locListener); private String initLocManager() { String context = Context.LOCATION_SERVICE; _locManager = (LocationManager) getSystemService(context); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(false); criteria.setBearingRequired(true); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); //criteria.setPowerRequirement(Criteria.POWER_LOW); String provider = _locManager.getBestProvider(criteria, true); if (provider == null || provider.equals("")) { displayGPSNotEnabledWarning(this); return null; } return provider; }
I tried to play the Criteria with but no success. Does anyone have an idea what is the problem?
回答1:
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.
回答2:
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) { } };
回答3:
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; }
回答4:
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).
new LocationListener() { private Location lastLocation = null; private double calculatedSpeed = 0; @Override public synchronized void onLocationChanged(Location location) { if (lastLocation != null) { double elapsedTime = (location.getTime() - lastLocation.getTime()) / 1_000; // Convert milliseconds to seconds calculatedSpeed = lastLocation.distanceTo(location) / elapsedTime; } this.lastLocation = location; double speed = location.hasSpeed() ? location.getSpeed() : calculatedSpeed; /* There you have it, a speed value in m/s */ . . . } . . . }
回答5:
getspeed() works fine. You don't have to do the math using distance formula. It is already there in getspeed, As long as there are latitude and longitude, there will be a speed in getspeed.
回答6:
(1) I believe you can use the requestLocationUpdates()
method and then create a LocationListener class with an onLocationChange method set to display getSpeed()
. This is how i recently saw it done with Location.getLatitude and Location.getLongitude, so I believe you could just use getSpeed() the same way, correct?
(2) After just reading the eclipse description window, though, I see it says exactly what the previous person said: "if hasSpeed() is false, 0.0f is returned." But maybe this will help: http://www.ehow.com/how_5708473_convert-latitude-feet.html :)
回答7:
I also encountered this problem before, I hope this can help.
It returns 0 because your device cannot get a lock on the GPS, or cannot connect to the GPS.
I tried to get the speed using an older lenovo device and it returns 0 because it cannot lock on a gps.
I tried using a samsung galaxy nexus and it returned my speed(has a better GPS sensor).
The GPS sensor in your phone might not be good or you are in an area that has a weak GPS signal such as inside a house or building.
回答8:
I basicaslly calculate the instantaneous speed and then use the setSpeed() method to add it in the location. Its pretty accurate because I compared it inside a vehicle where I could check the tachymeter.
private double calculateInstantaneousSpeed(Location location) { double insSpeed = 0; if (y1 == null && x1