I am trying to get the user's speed from their Android device, but which is the most reliable way to do it?
There is the location.getSpeed()
function that uses GPS; is this a reliable way to obtain the speed? Should I instead calculate speed manually using GPS coordinates obtained? Or is there another way that I'm missing to accomplish this?
hasSpeed() ( location. getSpeed() will always return 0). If you find that location. getSpeed() isn't accurate enough, or it is unstable (i.e. fluctuates drastically) then you can calculate speed yourself by taking the average distance between a few GPS locations and divide by the time elapsed.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With