为什么getSpeed()在android上总是返回0

为什么getSpeed()在android上总是返回0,android,gps,performance,location,Android,Gps,Performance,Location,我需要从gps获取速度和航向。但是,我从location.getSpeed()获得的唯一数字是0,有时不可用。我的代码: String provider = initLocManager(); if (provider == null) return false; LocationListener locListener = new LocationListener() { public void onLocationChanged

我需要从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;
}
我试着按标准比赛,但没有成功。有人知道问题出在哪里吗?

location.getSpeed()只返回location.setSpeed()设置的内容。这是可以为位置对象设置的值

要使用GPS计算速度,您需要做一些数学计算:

Speed = distance / time
因此,您需要:

(currentGPSPoint - lastGPSPoint) / (time between GPS points)
全部转换为英尺/秒,或以您希望的方式显示速度。这就是我制作runner应用程序时的做法

更具体地说,您需要计算绝对距离:

(sqrt((currentGPSPointX - lastGPSPointX)^2) + (currentGPSPointY - lastGPSPointY)^2)) / (time between GPS points)
创建一个新的TrackPoint类或其他类可能会有所帮助,它会保留GPS位置和进入的时间。

(1)我相信您可以使用
requestLocationUpdates()
方法,然后创建一个LocationListener类,并将onLocationChange方法设置为display
getSpeed()
。这就是我最近看到如何使用Location.getLatitude和Location.getLatitude完成的,所以我相信您可以用同样的方法使用getSpeed(),对吗

(2) 但是,在阅读eclipse描述窗口之后,我看到它与前面的人所说的一模一样:“如果hasSpeed()为false,则返回0.0f。”
但这可能会有所帮助::)

在一个球形行星上,应该用以下公式计算距离:

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

getspeed()工作正常。你不必用距离公式来计算。它已经存在于getspeed中,只要有纬度和经度,getspeed中就会有速度。

我以前也遇到过这个问题, 我希望这能有所帮助

它返回0,因为您的设备无法锁定GPS或无法连接到GPS

我试着用一台旧的联想设备获得速度,但它返回0,因为它无法锁定gps

我试着使用三星galaxy nexus,它恢复了我的速度(有更好的GPS传感器)


您手机中的GPS传感器可能不好,或者您所在的区域GPS信号较弱,例如在房子或建筑物内。

我的自定义位置侦听器用于手动获取速度,如果有速度,则按位置对象获取速度

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

        }
    };
它看起来非常好,但是如果你在单位里工作,它并没有多大帮助

下面是我计算速度的步骤,单位为米/秒(m/s)


我基本上计算瞬时速度,然后使用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;
}
private double calculateinnstantaneousspeed(位置){
双insSpeed=0;
如果(y1==null&&x1getSpeed()方法实际上工作得很好,但是您必须使用高请求间隔,比如1秒,并且需要高精度,首先我要做的是3秒间隔,优先级和功率平衡精度,我一直得到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();
        }
    }
}
public class main3活动扩展了appcompative活动{
私有FusedLocationProviderClient mFusedLocationClient;
私人整数速度;
私人双lat;
私人双液化天然气;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mFusedLocationClient=LocationServices.getFusedLocationProviderClient(此);
}
@凌驾
受保护的void onResume(){
super.onResume();
如果(!运行时权限()){
请求位置();
}
}
@凌驾
受保护的void onPause(){
super.onPause();
//当活动不再处于活动状态时停止位置更新
if(mFusedLocationClient!=null){
mFusedLocationClient.RemovelocationUpdate(mlLocationCallback);
}
}
@SuppressLint(“丢失许可”)
私有void请求位置(){
LocationRequest MLLocationRequest=新的LocationRequest();
mlLocationRequest.setInterval(1000);;
mLocationRequest.setPriority(位置请求.优先级高精度);
mFusedLocationClient.RequestLocationUpdate(mlLocationRequest、mlLocationCallback、Looper.myLooper());
}
LocationCallback mlLocationCallback=新LocationCallback(){
@凌驾
public void onLocationResult(LocationResult LocationResult){
List locationList=locationResult.getLocations();
如果(locationList.size()>0){
//列表中的最后一个位置是最新位置
Location=locationList.get(locationList.size()-1);
lat=位置。getLatitude();
lng=location.getLongitude();
//速度(单位:km/h)
速度=(int)((location.getSpeed()*3600)/1000);
}
}
};
私有布尔运行时_权限(){
如果(Build.VERSION.SDK_INT>=23&&ContextCompat.checkSelfPermission(此,
Manifest.permission.ACCESS\u FINE\u LOCATION)!=PackageManager.permission\u provided){
requestPermissions(新字符串[]{Manifest.permission.ACCESS\u FINE\u LOCATION},100);
返回true;
}
返回false;
}
@凌驾
public void onRequestPermissionsResult(int-requestCode,@NonNull-String[]permissions,@NonNull-int[]grantResults){
super.onRequestPermissionsResult(请求代码、权限、授权结果);
if(requestCode==100){
if(grantResults[0]==已授予PackageManager.权限){
onResume();
}否则{
运行时权限();
}
}
}

}

嘿,我也曾遭受同样的痛苦,但现在我已经解决了! 只需将该值乘以18/5,即可得出几乎准确的值

speed=location.getSpeed()*18/5


同时指定
间隔
1000*2
最快间隔
1000*1
,以获得更高的准确性

基于此处的其他建议,我将此代码与原因注释放在一起:

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 */
}
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 */
}