为啥 getSpeed() 在 android 上总是返回 0
Posted
技术标签:
【中文标题】为啥 getSpeed() 在 android 上总是返回 0【英文标题】:why getSpeed() always return 0 on android为什么 getSpeed() 在 android 上总是返回 0 【发布时间】:2011-06-16 06:20:00 【问题描述】:我需要通过 GPS 获取速度和航向。但是,我从location.getSpeed()
获得的唯一数字是 0 或有时不可用。我的代码:
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;
我尝试玩标准但没有成功。有谁知道问题出在哪里?
【问题讨论】:
【参考方案1】:location.getSpeed() 仅返回使用 location.setSpeed() 设置的内容。这是您可以为位置对象设置的值。
要使用 GPS 计算速度,您需要做一些数学运算:
Speed = distance / time
所以你需要这样做:
(currentGPSPoint - lastGPSPoint) / (time between GPS points)
全部转换为 ft/sec,或者您想要显示的速度。这就是我在制作跑步者应用时的做法。
更具体地说,您需要计算绝对距离:
(sqrt((currentGPSPointX - lastGPSPointX)^2) + (currentGPSPointY - lastGPSPointY)^2)) / (time between GPS points)
创建一个新的 TrackPoint 类或其他东西可能会有所帮助,它将 GPS 位置和时间保存在里面。
【讨论】:
它会返回米还是公里的距离? 我看到 getSpeed() 返回零的问题,即使 'hasSpeed()' 为真并且有运动。在一台 6.0.1 设备上,它总是返回零!来自 Fused Location 服务。常规 LocationManager 提供速度,但似乎不太准确且更新频率较低。所以我按照这里的建议进行了自己的速度计算。 9 年后,这对我有用,location.speed (kotlin) 从 android Studio 模拟器位置路线运动返回了正确的结果(假设),但是,现实世界的驾驶总是返回 0 KM/H叮叮叮。 这个答案是错误的,它并不总是返回0,也不需要使用setSpeed()
方法使其不为零。安卓无需你也能提速,无需人工计算【参考方案2】:
Imbru 的answer 看起来确实不错,但如果您使用单位,它就不是很有帮助。
这是我计算速度的方法,以米/秒 (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.hasSpeed()==false
才应该进行速度计算。也有人报告location.getSpeed()
总是返回0,即使location.hasSpeed()==true
。因此,我会使用location.hasSpeed() && location.getSpeed()>0
作为条件。
我第二次 Julien Kroneggs 建议更喜欢使用 direkt getSpeed(如果 .hasSpeed()==true),因为 GPS 不需要两个位置及其距离来计算速度,但可以使用多普勒效应来计算速度更准确。这意味着 getSpeed 在时间上会更准确,而距离/时间计算会随着两个位置之间经过的时间更长而变得更精确,但只会给您两个测量值之间的平均速度,而不是新位置进入时的速度.
@JulienKronegg 报告说即使 hasSpeed 也可以为 0?
@user924 你可以在 SO google.com/…找到一些帖子
@JulienKronegg mb 他们没有正确的检查(使用 hasSpeed)【参考方案3】:
我的自定义 LocationListener 用于手动获取速度,如果有速度,则通过位置对象获取速度。
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)
;
【讨论】:
我使用了你的代码,它的工作原理是这样的,它返回速度为 2.25,但我的车速约为 60km/h。如何准确计算移动速度? @Kevin ABRIOUX 计算速度的单位是什么。是公里/小时吗? 我建议使用 location.distanceTo(other_location) 的内置方法,而不是自行计算位置之间的距离。具有时间增量的除数可以保持不变。输出是米每秒,所以乘以 3.6 得到公里/小时 我错误地建议除数是正确的。但它以毫秒为单位计算时间增量,但速度以米每秒为单位。【参考方案4】:在球形行星上的距离应该用这些公式计算:
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;
【讨论】:
如果用户在斜坡上怎么办?? 即使是谷歌似乎也忘记了海拔增量。也许是因为糟糕的卫星修复和蜂窝塔/wifi 只能提供 2D 位置?查看 Location.distanceTo 代码 - 我不完全理解 - 我可以看到两个位置的纬度和经度以及方位在起作用,但看不到高度。【参考方案5】:(1) 我相信您可以使用requestLocationUpdates()
方法,然后创建一个LocationListener 类,并设置一个onLocationChange 方法来显示getSpeed()
。这就是我最近看到使用 Location.getLatitude 和 Location.getLongitude 完成的方式,所以我相信您可以以同样的方式使用 getSpeed(),对吗?
(2) 但是,在刚刚阅读了 eclipse 描述窗口之后,我看到它与前人所说的完全一样:“如果 hasSpeed() 为假,则返回 0.0f。” 但也许这会有所帮助:http://www.ehow.com/how_5708473_convert-latitude-feet.html :)
【讨论】:
【参考方案6】:getSpeed() 方法实际上工作得很好,但是你必须使用像 1 秒这样的高请求间隔并且你需要高精度,首先我做了 3 秒的间隔和 PRIORITY_BALANCED_POWER_ACCURACY,我一直得到 0 值,直到我像我说的那样改变它.我正在使用融合位置提供程序 api。
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<Location> 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();
【讨论】:
我会假设使用融合的位置提供程序,您不会总是获得速度或非常糟糕的速度,因为如果 GPS 不良或没有 GPS,您将获得非常精确的三角单元塔或 wifi 附近读数准确性不准确,速度一定很糟糕。我建议仅在速度很高的情况下使用 GPS Prodiver。不过我不是专家,我只使用 GPS 以在 wifi 关闭的情况下省电。【参考方案7】:嘿,我也遭受同样的痛苦,但现在我已经解决了! 只需将值乘以 18/5 即可得出几乎准确的值。
speed=location.getSpeed()*18/5
还将interval
指定为1000*2
,将fastest interval
指定为1000*1
以提高准确性
【讨论】:
这个18/5
幻数从何而来?另外,这对 " getSpeed()
返回 0 " 的问题有什么帮助?
getSpeed() 方法返回以 m/s 为单位的值,该值始终返回零,因此使用 18/5 1 m/s=18/5 Km/hr 转换为 km/h
一小时秒数 = 3600;以千米为单位的米 = 1000。因此 1 m/s = 3600/1000 km/h = 36/10 km/h = 18/5 km/h = 3.6 km/h。【参考方案8】:
getspeed() 工作正常。您不必使用距离公式进行数学计算。 getspeed里已经有了,只要有经纬度,getspeed里就会有速度。
【讨论】:
我不认为这是真的,我确实有经度和纬度,但 getSpeed() 总是返回 0.0【参考方案9】:我之前也遇到过这个问题, 我希望这会有所帮助。
返回 0 是因为您的设备无法锁定 GPS,或无法连接到 GPS。
我尝试使用较旧的 lenovo 设备获取速度,但它返回 0,因为它无法锁定 gps。
我尝试使用三星 Galaxy nexus,它返回了我的速度(有更好的 GPS 传感器)。
您手机中的 GPS 传感器可能不好,或者您位于 GPS 信号较弱的区域,例如房屋或建筑物内。
【讨论】:
【参考方案10】:我基本上计算瞬时速度,然后使用 setSpeed() 方法将其添加到位置。它非常准确,因为我在可以检查测速仪的车辆内进行了比较。
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;
【讨论】:
【参考方案11】:根据此处的其他建议,我将这段代码与 cmets 放在一起,说明原因:
public static float getSpeedKmh(Location newLocation, Location previousLocation)
if(newLocation == null) throw new IllegalArgumentException("newLocation must not be null");
float speed = -1.0f;
if(newLocation.hasSpeed()) /* gps doppler speed at the current moment preferred */
speed = newLocation.getSpeed();
else /* may be wifi or celltower based location: compute AVERAGE speed since last fix */
if(previousLocation == null) throw new IllegalArgumentException("Cannot compute speed without previousLocation (was null)");
if(previousLocation.getTime()==newLocation.getTime())
throw new IllegalArgumentException("Cannot compute speed from same time locations!"); /* diff by zero protection */
speed = newLocation.distanceTo(previousLocation) * 1000.0f /* time diff in millis so multiply by 1000 */
/ Math.abs(newLocation.getTime() - previousLocation.getTime()); /* Math abs: so you can even swap new and older location without effect */
return speed * 3.6f; /* m/s -> km/h */
【讨论】:
以上是关于为啥 getSpeed() 在 android 上总是返回 0的主要内容,如果未能解决你的问题,请参考以下文章
如何获取Android设备用户移动的速度? Location.getSpeed 可靠吗?