I am trying to calculate speed in android device, but which is the best practice to do it, already it has location.getSpeed() function using GPS, is this best way to use? or
IMO, best current approach on Android is to use Location.getSpeed()
along with the Google Services Location API and the fused location provider. Then, reality-check this value against Google Play Services Activity Recognition.
The fused location provider integrates some other on-board sensors to tweak location data, which is better than GPS alone. Then, check the ActivityRecognition.getMostProbableActivity() method. If the DetectedActivity is type STILL
, your true speed is probably equal to 0. If its ON_FOOT
, it's probably a low speed (e.g., 1 m/s). If its ON_BICYCLE
or IN_VEHICLE
, you're probably fine relying on the speed output obtained directly from Location.getSpeed()
. You'll also want to check the DetectedActivity.getConfidence() value too, and set your own threshold for a confidence level you feed "confident" with :) when relying on these values.
I'd also definitely suggest that you do NOT simply average sequential positions to get an average speed between two position (if you do this, it needs to be an average over a large number of positions). In my benchmarking on mobile devices (see my dissertation here, pages 105-106, and 137-138 especially), I've found instantaneous speed calculated by the GPS subsystem (which is typically based off of the Doppler shift of GPS carrier signals) to be far more accurate than the positions derived from GPS. 95th percentile of speed observed while stationary indoors (using assisted GPS only, no sensor fusion) was 1 m/s on a Sanyo Pro 200 I tested. I was able to filter out a significant number of position outliers using speed data (see page 137-138) in some intelligent energy management techniques I was evaluating. With sensor fusion, and activity recognition to help filter outliers, accuracy should be better than this on a similar device.
Finally, and I can't emphasis this enough, do you own testing on real devices, as many as you can get a hold off, and preferably the most popular models out there. Android has a variety of OEMs putting out devices, which will all have their eccentricities. Your best bet it to create a solution that targets the most popular models, acknowledging that it's unrealistic to get a solution working perfectly on all models.
It seems that the getSpeed() method is not always reliable, especially at low speed and when gps coverage is not optimal. You can have a look at this question and this one which are both about alternatives for getSpeed(). The android developper page however says that you'll get better performance by using the Google Location API.
So it appears that the choice is depending on the usage of your app: if you target slow displacement in area with poor gps coverage (walking in the wood), use your own implementation. Fast in area with good GPS coverage, use the Google Location API.
Hope it helped you.
The best way for devices that are moving faster than walking speed, is to use directly the location.getSpeed().
For pedestrian, or other slow speed situations, this is not quite easy, maybe it is simply impossible to have a valid slow speed that is valid at the moment.
Some try to evaluate the history and do an averaging, or threshold based approach, this will improve for a specific application / usage.
But the simplest is to design your App to ignore low speeds.
Some links related to speed:
GPS position correction
Smooth GPS data