سؤال

I have a service class to get speed, address, location, latitude and longitude from GPS. My existing app gets a good result with a little tolerance. But i want to get the most accurate speed from location.getSpeed() method. For example when i have constant 80km/h speed, it shows me 76 or 77km/h. How can i increase accuracy? I want to do it without any error margin.

My GPSLocation Service:

public class GPSLocationService extends Service {
    private static final String TAG = "GPSLocationService";
    private LocationManager locationManager;
    private LocationListener gpsLocationListener;
    private long lastGPStime;
    private double lastLatitude;
    private double lastLongitude;
    private float lastSpeed;
    private Address lastAddress;
    private Location mLastLocation;
    private float maxSpeed;
    private final float metersSec_in_KMPH = 3.6f;
    @SuppressLint("SimpleDateFormat")
    private SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");

    // other modules will call these public methonds
    public String getTime() {
        return timeFormat.format(new Date(lastGPStime));
    }

    public String getLocation(){
        if(mLastLocation != null)
            return mLastLocation.toString();
        else
            return "0";
    }

    public String getAddress(){
        if(lastAddress != null)
            return lastAddress.getAddressLine(0) + " " + lastAddress.getAddressLine(1) + " " + lastAddress.getAddressLine(2) + " " + lastAddress.getAddressLine(3);
        else
            return "0";
    }

    public float getSpeedFloat(){
        if (lastSpeed < 1.0f) { return 0; }
        float mph = lastSpeed * metersSec_in_KMPH;
        return mph;
    } 

    public Float getGpsStatus(){
        if(mLastLocation != null)
            return mLastLocation.getAccuracy();
        else
            return 0.0f;
    }

    // latitude ranges from 0.0 to 90.0
    // In the US, latitude is always double-digits: 44.xxyyzz
    // We'll keep six digits after the decimal point
    public String getLat() {
        String lValue = Double.toString(lastLatitude);
        if (lValue.length() < 9)
            return lValue;
        return lValue.substring(0, 9);
    } // latitude has max 2 digits before

    // in the US, Longitude is always three digits: 123.xxyyzz
    // We'll keep six digits after the decimal point (ITIS)
    public String getLong() {
        String lValue = Double.toString(lastLongitude);
        if (lValue.length() < 10)
            return lValue;
        return lValue.substring(0, 10);
    } // longitude has up to 3 digits

    // speed is reported in meters/second
    // speed needs three digits, and maybe three more past the decimal point:
    // 145.608
    public String getSpeed() {
        if (lastSpeed < 1.0f) { return "000"; }
        float mph = lastSpeed * metersSec_in_KMPH;
        String lValue = Integer.toString((int) mph);
        return lValue;
    }

    public String getMaxSpeed() {
        if (maxSpeed < 1.0f) { return "0.0"; }
        String lValue = Float.toString(maxSpeed * metersSec_in_KMPH);
        if (lValue.length() < 7) {
            return lValue;
        } else
            return lValue.substring(0, 7);
    }

    // setup this service to allow binding for access to public methods above.
    // http://developer.android.com/guide/components/bound-services.html
    private final IBinder mBinder = new GPSBinder();

    public class GPSBinder extends Binder {
        GPSLocationService getService() {
            return GPSLocationService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    // the usual 'Service' methods below
    @Override
    public void onCreate() {
        super.onCreate();
        // instantiate the inner class
        gpsLocationListener = new GPSLocationListener();
        // get the system manager
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        // and demand Speed values
        Criteria criteria = new Criteria();
        criteria.setSpeedRequired(true);
        locationManager.requestLocationUpdates(
                locationManager.getBestProvider(criteria, false), 250, 
                5, gpsLocationListener);
        Toast toast = Toast.makeText(GPSLocationService.this, "GPS updates requested.", Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        locationManager.removeUpdates(gpsLocationListener);
    }

    private class GPSLocationListener implements LocationListener,
            GpsStatus.Listener {
        boolean isGPSFix;

        public void onGpsStatusChanged(int event) {
            switch (event) {
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                if (mLastLocation != null)
                    isGPSFix = (SystemClock.elapsedRealtime() - lastGPStime) < 3000;
                if (isGPSFix) { // A fix has been acquired.
                    Toast toast = Toast.makeText(GPSLocationService.this, "GPS has a fix.", Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                } else { // The fix has been lost.
                    Toast toast = Toast.makeText(GPSLocationService.this, "GPS DOES NOT have a fix.", Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }
                break;
            case GpsStatus.GPS_EVENT_FIRST_FIX:
                Toast toast = Toast.makeText(GPSLocationService.this, "GPS got first fix.", Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                isGPSFix = true;
                break;
            }
        }

        @Override
        public void onLocationChanged(Location location) {
            mLastLocation = location;
            try {
                lastAddress = getAddressForLocation(Main.context, location);
            } catch (IOException e) {
                Log.i("EXCEPTION", "Exception on Address");
                e.printStackTrace();
            }
            lastGPStime = location.getTime();
            lastLatitude = location.getLatitude();
            lastLongitude = location.getLongitude();
            lastSpeed = location.getSpeed();
            if (lastSpeed > maxSpeed) {
                maxSpeed = lastSpeed;
            }
            Log.i(TAG, "GPS update received.");
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            String statusDescription = "unknown";
            switch (status) {
            case LocationProvider.OUT_OF_SERVICE:
                statusDescription = "OUT_OF_SERVICE";
                break;
            case LocationProvider.AVAILABLE:
                statusDescription = "AVAILABLE";
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                statusDescription = "TEMPORARILY_UNAVAILABLE";
                break;
            }

            Toast toast = Toast.makeText(GPSLocationService.this, TAG + " GPS provider status changed to "
                    + statusDescription + "and the last speed was: " + getSpeed()  , Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }

        @Override
        public void onProviderEnabled(String provider) {
            Toast toast = Toast.makeText(GPSLocationService.this, "GPS provider enabled.", Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }

        @Override
        public void onProviderDisabled(String provider) {
            Toast toast = Toast.makeText(GPSLocationService.this, "GPS provider disabled?", Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }

    }

    public void zeroMaxSpeed() {
        maxSpeed = 0.0f;
    }

    public Address getAddressForLocation(Context context, Location location) throws IOException {

        if (location == null) {
            return null;
        }
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        int maxResults = 1;

        Geocoder gc = new Geocoder(context, Locale.getDefault());
        List<Address> addresses = gc.getFromLocation(latitude, longitude, maxResults);

        return addresses.get(0);
    }

}

I use this service's methods from my Main class:

public class Main extends Activity {
    private GPSLocationService gpsService;
    private ServiceConnection gpsSvcConn;
    private boolean isGPSserviceBound;
    private static final String TAG = "FullScreenSpeed";
    private Thread updateThread;
    private Handler handler = new Handler();
    private TextView address;
    private TextView lat;
    private TextView longi;
    private TextView velocity;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        address = (TextView) findViewById(R.id.address);
        lat = (TextView) findViewById(R.id.latitude);
        longi = (TextView) findViewById(R.id.longitude);
        velocity = (TextView) findViewById(R.id.velocity);
        updateThread = new Thread() {
            public void run() {
                if (isGPSserviceBound) {
                    speed = gpsService.getSpeed();
                    latitude = gpsService.getLat();
                    longitude = gpsService.getLong();
                    address.setText("Address: " + gpsService.getAddress());
                    lat.setText("Latitude: " + latitude);
                    longi.setText("Longitude: " + longitude);
                    velocity.setText("Velocity: " + speed + " Km/h");   
                    if(i == 10){
                    i=0;
                    }
                    else{
                        arrayVelocity[i] = speed;
                        arrayLatitude[i] = latitude;
                        arrayLongitude[i] = longitude;
                        Log.i("HIZ","arrayVelocity[" + i + "] = " + speed);
                        Log.i("HIZ","arrayLatitude[" + i + "] = " + latitude);
                        Log.i("HIZ","arrayLongitude[" + i + "] = " + longitude);
                    i++;
                    }

                }  // GPS service isn't bound, can't do anything
                handler.postDelayed(this, 14000); // wait a while
            }
        };
    }
    private void startGPSService() {
        startService(new Intent(this, GPSLocationService.class));
        gpsSvcConn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                GPSBinder gpsBinder = (GPSBinder) binder;
                gpsService = gpsBinder.getService();
                isGPSserviceBound = true;
                Toast toast = Toast.makeText(Main.this, "GPS service bound", Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                isGPSserviceBound = false;
                Toast toast = Toast.makeText(Main.this, "GPS service came unbound?", Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
            }
        };
        Intent intent = new Intent(this, GPSLocationService.class);
        bindService(intent, gpsSvcConn, Context.BIND_AUTO_CREATE);
        Log.i(TAG, "started gps service");
        Toast toast = Toast.makeText(Main.this, "Started to bind to GPS service", Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        handler.postDelayed(updateThread, 0);
        Toast toast = Toast.makeText(Main.this, "MainActivity resumed", Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast toast = Toast.makeText(Main.this, "MainActivity stopped", Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();

    }

}
هل كانت مفيدة؟

المحلول

After checking these links Link1 and Link2, i realize that my speed is correct and the speedometer of the cars where i tested my app on do not show correct value. They always show much then real speed of the car. So, the value from my app is better than the cars' speedometers.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top