Получение географических координат очень далеко от предыдущего.

В моем приложении есть возможность отслеживать расстояние, на которое человек проехал. Есть класс обслуживания для периодического получения текущей широты и долготы. Иногда с получением баллов все в порядке. Иногда это не так. около 500 м и вернулся к той же точке, но рассчитанное расстояние было 3,5 км. Для определения пройденного расстояния я беру разницу между текущим и предыдущим местоположением. Значения добавляются с новым значением и продолжаются до последнего. Возникает проблема. Иногда получение точки gps очень далеко от предыдущего (иногда получение точка будет более чем на 700 метров от предыдущей).

Вот мой класс, просветите, пожалуйста, если я что-то не так делаю.

public class LocationUpdateService extends Service implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    protected static final String TAG = "LocationUpdateService";
    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
    public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 3; // 10 meters
    public static Boolean mRequestingLocationUpdates;
    protected String mLastUpdateTime;
    protected GoogleApiClient mGoogleApiClient;
    protected LocationRequest mLocationRequest;
    protected Location mCurrentLocation;
    protected Location mLastLocation;
    Location currentLocation, previousLocation;
    public static boolean isEnded = false;
    private Context mContext;
    ServiceListener listener;
    SharedPreferences sharedPreferences;
    double latitude; // latitude
    double longitude; // longitude
    private String locationProvider;                                                                // source of fetched location
    LocationManager locationManager;
    private IBinder mBinder = new MyBinder();

    public LocationUpdateService() {
        super();
    }

    public void setListener(ServiceListener listener) {
        this.listener = listener;

    }

    @Override
    public void onCreate() {
        super.onCreate();
        // Kick off the process of building a GoogleApiClient and requesting the LocationServices
        mContext = getApplicationContext();
        //locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        sharedPreferences = mContext.getSharedPreferences(WebServiceHelper.PREFS_NAME, 0);
        System.out.println("GPS TRACKER STARTED");
        deletefile("asap_distance.csv");
    }

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


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Within {@code onPause()}, we pause location updates, but leave the
        // connection to GoogleApiClient intact.  Here, we resume receiving
        // location updates if the user has requested them.
        System.out.println(TAG + "onStartCommand");

        Log.d("LOC", "Service init...");
        isEnded = false;
        mRequestingLocationUpdates = false;
        mLastUpdateTime = "";
        buildGoogleApiClient();
        if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
            startLocationUpdates();
        }
        return Service.START_REDELIVER_INTENT;
    }


    @Override
    public void onConnected(Bundle bundle) {
        System.out.println(TAG + "onConnected");
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {
        // The connection to Google Play services was lost for some reason. We call connect() to
        // attempt to re-establish the connection.
        Log.i(TAG, "Connection suspended==");
        mGoogleApiClient.connect();
    }

    @Override
    public void onLocationChanged(Location location) {
        System.out.println(TAG + "onLocationChanged");
        if (location == null) {
            getLastKnownLocation();
        } else {
            mCurrentLocation = location;
            if (mCurrentLocation.hasAccuracy() && mCurrentLocation.getAccuracy() > MIN_DISTANCE_CHANGE_FOR_UPDATES)
                setLocationData(mCurrentLocation);
            mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());

        }

//
//        updateUI();
//        Toast.makeText(this, "Location changed",
//                Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // Refer to the javadoc for ConnectionResult to see what error codes might be returned in
        // onConnectionFailed.
        Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
    }

    /**
     * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the
     * LocationServices API.
     */
    protected synchronized void buildGoogleApiClient() {
        Log.i(TAG, "Building GoogleApiClient===");
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        createLocationRequest();
    }

    public void setLocationData(Location location) {

        if (location != null) {
            currentLocation = location;
            double previous_latitude, previous_longitude, current_lat, current_long;

            latitude = location.getLatitude();
            longitude = location.getLongitude();
            //  Toast.makeText(mContext, "Current lattitude:" + latitude + "Current Longitude:" + longitude, Toast.LENGTH_LONG).show();

            previous_latitude = previousLocation.getLatitude();
            previous_longitude = previousLocation.getLongitude();
            current_lat = currentLocation.getLatitude();
            current_long = currentLocation.getLongitude();
            Log.d(TAG, "Previous lattitude:" + previous_latitude + "Previous Longitude:" + previous_longitude);
            Log.d(TAG, "Current lattitude:" + current_lat + "Current Longitude:" + current_long);

            sharedPreferences.edit().putFloat("lastSavedLat", (float) current_lat).apply();
            sharedPreferences.edit().putFloat("lastSavedLon", (float) current_long).apply();

            if (previousLocation != null && sharedPreferences.contains("sdeMarkedStartLocLat")) {

                if (current_lat == previous_latitude && current_long == previous_longitude) {
                    Log.d(TAG, "No  Displacement");

                } else {
                    Log.d(TAG, "Device Displaced");
                    //  double d = getDistance(previous_latitude, previous_longitude, current_lat, current_long);
                    double d = ((int) (previousLocation.distanceTo(currentLocation) * 1000)) / 1000;
                    Log.d(TAG, "Distance calculated in between previousLocation and currentLocation is" + d);
                    if (d < 5000) {
                        d = d + sharedPreferences.getFloat("sum_dist", 0);
                        sharedPreferences.edit().putFloat("sum_dist", (float) d).apply();
                        //           Toast.makeText(mContext, "Total Distance travelled is " + d + "km", Toast.LENGTH_LONG).show();

                        // Log.d("Distance Calculator ON", "distance" + d);
                        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                        writeToFile(sdf.format(new Date()) + "," + currentLocation.getLatitude() + "," + currentLocation.getLongitude() + ", " + d + " meters" + "\n", "asap.csv");
                        writeToFile(currentLocation.getLatitude() + "," + currentLocation.getLongitude() + "\n", "asap_distance.csv");

                    }


                }

            }

            if (listener != null)
                listener.onLocationReceived(location);
            System.out.println("GPS TRACKER " + latitude + " " + longitude);
            previousLocation = currentLocation;
        } else {
            Log.d(TAG, "Location is null");
            return;
        }

    }

    public double getDistance(double start_lat, double start_long, double dest_lat, double dest_long) {

        double dist = 0;
        Location locationA = new Location("point A");

        locationA.setLatitude(start_lat);
        locationA.setLongitude(start_long);

        Location locationB = new Location("point B");

        locationB.setLatitude(dest_lat);
        locationB.setLongitude(dest_long);

        dist = locationA.distanceTo(locationB);


        if (dist != 0) {
            dist = dist / 1000;
        }
        return dist;
    }


    /**
     * Updates the latitude, the longitude, and the last location time in the UI.
     */
    private void updateUI() {
        Toast.makeText(this, "Latitude: =" + mCurrentLocation.getLatitude() + " Longitude:=" + mCurrentLocation
                .getLongitude(), Toast.LENGTH_SHORT).show();
        System.out.println("updateUI");
        Log.d(TAG, "Latitude:==" + mCurrentLocation.getLatitude() + "\n Longitude:==" + mCurrentLocation.getLongitude
                ());

    }


    /**
     * Sets up the location request. Android has two location request settings:
     * {@code ACCESS_COARSE_LOCATION} and {@code ACCESS_FINE_LOCATION}. These settings control
     * the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
     * the AndroidManifest.xml.
     * <p/>
     * When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
     * interval (5 seconds), the Fused Location Provider API returns location updates that are
     * accurate to within a few feet.
     * <p/>
     * These settings are appropriate for mapping applications that show real-time location
     * updates.
     */
    protected void createLocationRequest() {
        mGoogleApiClient.connect();
        mLocationRequest = new LocationRequest();

        // Sets the desired interval for active location updates. This interval is
        // inexact. You may not receive updates at all if no location sources are available, or
        // you may receive them slower than requested. You may also receive updates faster than
        // requested if other applications are requesting location at a faster interval.
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);

        // Sets the fastest rate for active location updates. This interval is exact, and your
        // application will never receive updates faster than this value.
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(MIN_DISTANCE_CHANGE_FOR_UPDATES);
    }

    /**
     * Requests location updates from the FusedLocationApi.
     */
    protected void startLocationUpdates() {
        if (!mRequestingLocationUpdates) {
            mRequestingLocationUpdates = true;

            // The final argument to {@code requestLocationUpdates()} is a LocationListener
            // (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
            LocationServices.FusedLocationApi.requestLocationUpdates(
                    mGoogleApiClient, mLocationRequest, this);
            Log.i(TAG, " startLocationUpdates===");
            isEnded = true;
        }
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        previousLocation = mLastLocation;

        if (mLastLocation != null) {
            onLocationChanged(mLastLocation);
        }
    }

    /**
     * Function to get latitude
     */
    public double getLatitude() {
        if (mCurrentLocation != null) {
            latitude = mCurrentLocation.getLatitude();
        }

        // return latitude
        return latitude;
    }


    /**
     * Function to get longitude
     */
    public double getLongitude() {
        if (mCurrentLocation != null) {
            longitude = mCurrentLocation.getLongitude();
        }

        // return longitude
        return longitude;
    }


    /**
     * Removes location updates from the FusedLocationApi.
     */
    protected void stopLocationUpdates() {
        if (mRequestingLocationUpdates) {
            mRequestingLocationUpdates = false;
            // It is a good practice to remove location requests when the activity is in a paused or
            // stopped state. Doing so helps battery performance and is especially
            // recommended in applications that request frequent location updates.

            Log.d(TAG, "stopLocationUpdates();==");
            // The final argument to {@code requestLocationUpdates()} is a LocationListener
            // (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopLocationUpdates();
        System.out.println("GPS TRACKER STOPPED");

    }

    public Location getLastKnownLocation() {
        //  locationProvider = LocationManager.GPS_PROVIDER;
        Location lastKnownLocation = null;
        // Or use LocationManager.GPS_PROVIDER
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return lastKnownLocation;
        }
        try {
            //lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
            lastKnownLocation = LocationServices.FusedLocationApi.getLastLocation(
                    mGoogleApiClient);
            return lastKnownLocation;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return lastKnownLocation;
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.v("GPS", "in onBind");
        return mBinder;

    }

    @Override
    public void onRebind(Intent intent) {
        Log.v("GPS", "in onRebind");
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v("GPS", "in onUnbind");
        return true;
    }

    public void deletefile(String filename) {
        File sdCard = Environment.getExternalStorageDirectory();
        File directory = new File(sdCard.getAbsolutePath() + "/ASAPLog");
        //Now delete the file in the above directory and write the contents into it
        try {
            File file = new File(directory.getAbsolutePath() + "/" + filename);
            if (file.exists()) {
                boolean deleted = file.delete();
                System.out.println("deleted" + deleted);

            } else {
                System.out.println("File Doesnot Exists");

            }
        } catch (Exception e) {
            e.printStackTrace();

        }

    }

    public void writeToFile(String text, String filename) {


        File sdCard = Environment.getExternalStorageDirectory();
        File directory = new File(sdCard.getAbsolutePath() + "/ASAPLog");
        if (!directory.exists())
            directory.mkdirs();
        // String savedText = readFromFile(filename).toString();

        //Now create the file in the above directory and write the contents into it
        try {
            File file = new File(directory.getAbsolutePath() + "/" + filename);
            FileOutputStream fOut = new FileOutputStream(file, true);
            OutputStreamWriter osw = new OutputStreamWriter(fOut);
            osw.append(text);
            osw.flush();
            osw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public class MyBinder extends Binder {
        LocationUpdateService getService() {
            return LocationUpdateService.this;
        }
    }

}

person Noufal    schedule 08.11.2016    source источник