¿Por qué getSpeed ​​() siempre devuelve 0 en Android?

Necesito obtener la velocidad y el rumbo de los gps. Sin embargo, el único número que tengo de location.getSpeed() es 0 o, a veces, no está disponible. mi código:

  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; } 

Traté de jugar los criterios con pero sin éxito. ¿Alguien tiene una idea de cuál es el problema?

location.getSpeed ​​() solo devuelve lo que se estableció con location.setSpeed ​​(). Este es un valor que puede establecer para un objeto de ubicación.

Para calcular la velocidad con GPS, tendrás que hacer un poco de matemáticas:

 Speed = distance / time 

Entonces necesitarías hacer:

 (currentGPSPoint - lastGPSPoint) / (time between GPS points) 

Todo convertido a ft / seg, o como quiera mostrar la velocidad. Así es como lo hice cuando hice una aplicación de corredor.

Más específicamente, deberá calcular las distancias absolutas:

 (sqrt((currentGPSPointX - lastGPSPointX)^2) + (currentGPSPointY - lastGPSPointY)^2)) / (time between GPS points) 

Podría ser útil crear una nueva clase de TrackPoint o algo así, que mantenga la ubicación del GPS y la hora en que se tomó dentro.

Hay mi LocationListener personalizado usado para obtener velocidad manualmente y por objeto de ubicación si tiene velocidad.

  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) { } }; 

La respuesta de Imbru se ve muy bien, pero no es muy útil si estás trabajando con unidades.

Esto es lo que hice para calcular la velocidad en metros por segundo (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 */ . . . } . . . } 

En un planeta esférico, la distancia debe calcularse con estas fórmulas:

 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; } 

(1) Creo que puede usar el método requestLocationUpdates() y luego crear una clase LocationListener con un método onLocationChange configurado para mostrar getSpeed() . Así es como recientemente lo vi hecho con Location.getLatitude y Location.getLongitude, así que creo que podrías usar getSpeed ​​() de la misma manera, ¿correcto?

(2) Después de leer la ventana de descripción de eclipse, veo que dice exactamente lo que dijo la persona anterior: “si hasSpeed ​​() es falso, se devuelve 0.0f”. Pero tal vez esto ayude: http://www.ehow.com/how_5708473_convert-latitude-feet.html 🙂

getspeed () funciona bien. No tienes que hacer los cálculos usando la fórmula de distancia. Ya está allí en la velocidad, siempre que haya latitud y longitud, habrá una velocidad en la velocidad.

El método getSpeed ​​() realmente funciona bien, pero tienes que usar un intervalo de solicitud alto como 1 segundo y necesitas una gran precisión. Primero estaba haciendo un intervalo de 3 segundos y PRIORITY_BALANCED_POWER_ACCURACY y sigo obteniendo 0 valores hasta que lo cambio como digo. Estoy usando una API de proveedor de ubicación fusionada.

 public class Main3Activity extends AppCompatActivity { private FusedLocationProviderClient mFusedLocationClient; private int speed; private double lat; private double lng; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); } @Override protected void onResume() { super.onResume(); if(!runtime_permissions()) { requestLocations(); } } @Override protected void onPause() { super.onPause(); //stop location updates when Activity is no longer active if (mFusedLocationClient != null) { mFusedLocationClient.removeLocationUpdates(mLocationCallback); } } @SuppressLint("MissingPermission") private void requestLocations(){ LocationRequest mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(1000);; mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper()); } LocationCallback mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { List locationList = locationResult.getLocations(); if (locationList.size() > 0) { //The last location in the list is the newest Location location = locationList.get(locationList.size() - 1); lat = location.getLatitude(); lng = location.getLongitude(); //speed in km/h speed = (int) ((location.getSpeed() * 3600) / 1000); } } }; private boolean runtime_permissions() { if(Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){ requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100); return true; } return false; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == 100){ if( grantResults[0] == PackageManager.PERMISSION_GRANTED){ onResume(); }else{ runtime_permissions(); } } } 

}

También encontré este problema antes, espero que esto pueda ayudar.

Devuelve 0 porque su dispositivo no puede bloquear el GPS o no puede conectarse al GPS.

Traté de obtener la velocidad con un dispositivo lenovo anterior y devuelve 0 porque no se puede bloquear en un gps.

Intenté usar un Samsung Galaxy Nexus y devolvió mi velocidad (tiene un mejor sensor de GPS).

Es posible que el sensor GPS de su teléfono no sea bueno o que se encuentre en un área con una señal de GPS débil, como dentro de una casa o edificio.

Principalmente calculo la velocidad instantánea y luego uso el método setSpeed ​​() para agregarlo a la ubicación. Es bastante preciso porque lo comparé dentro de un vehículo donde podría revisar el taquímetro.

 private double calculateInstantaneousSpeed(Location location) { double insSpeed = 0; if (y1 == null && x1 <= -1) { //mark the location y1 at time x1 y1 = location; x1 = duration.getDurationAsSeconds(); } else { //mark the location y2 at time x2 y2 = location; x2 = duration.getDurationAsSeconds(); //calculate the slope of the curve (instantaneous speed) dy = y1.distanceTo(y2); dx = x2 - x1; insSpeed = dy / dx; y1 = y2; x1 = x2; } Singleton.getInstance().instantaneousSpeedSamples.add(insSpeed); //System.out.println("Instantaneous Speed m/s: "+insSpeed); return insSpeed; } 

¡Hola, yo también estaba sufriendo lo mismo, pero ahora lo tengo resuelto! Simplemente multiplique el valor por 18/5, da casi el valor exacto.

speed=location.getSpeed()*18/5

También especifique el interval como 1000*2 y el fastest interval como 1000*1 para una mayor precisión