why getSpeed() always return 0 on android

前端 未结 11 1243
半阙折子戏
半阙折子戏 2020-11-28 07:35

I need to get the speed and heading from the gps. However the only number i have from location.getSpeed() is 0 or sometimes not available. my code:

         


        
相关标签:
11条回答
  • 2020-11-28 08:00

    On a spherical planet distance should be calculated with these formulas :

    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;
       }
    
    0 讨论(0)
  • 2020-11-28 08:01

    There is my custom LocationListener used to get speed manually and by location object if has speed.

     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) {
    
            }
        };
    
    0 讨论(0)
  • 2020-11-28 08:02

    getspeed() works fine. You don't have to do the math using distance formula. It is already there in getspeed, As long as there are latitude and longitude, there will be a speed in getspeed.

    0 讨论(0)
  • 2020-11-28 08:04

    getSpeed() method actually works fine but you have to use a high request interval like 1 second and you need high accuracy, first i was doing 3 second interval and PRIORITY_BALANCED_POWER_ACCURACY and i kept getting 0 values until i change it like i say. I am using fused location provider 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();
            }
        }
    }
    

    }

    0 讨论(0)
  • 2020-11-28 08:10

    Based on other suggestions here I put together this code with comments to why:

    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 */
    }
    
    0 讨论(0)
  • 2020-11-28 08:11

    location.getSpeed() only returns what was set with location.setSpeed(). This is a value that you can set for a location object.

    To calculate the speed using GPS, you'll have to do a little math:

    Speed = distance / time
    

    So you would need to do:

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

    All converted to ft/sec, or however you want to show the speed. This is how I did it when I made a runner app.

    More specifically, you'll need to calculate for absolute distances:

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

    It might help to make a new TrackPoint class or something, which keeps the GPS location and time it was taken inside.

    0 讨论(0)
提交回复
热议问题