The Geo-Cordinates getting is Very Far from previo

2019-07-29 18:56发布

问题:

In my application there is provision to track how much distance a person is travelled.There is a Service class for getting the current lat and long perodically.Some times the points getting is fine.Othertimes it is not.I started from a point and walked around 500m and came back to the samepoint ,but the distance calculated was 3.5 k.m. For finding the distance travelled ,I take the difference in between Current and previous location.The values are added with new value and goes on until last.The problem occurs ,Some times the gps point getting is very far from previous one(Some times getting point would be more than 700 meters from previous).

Here is my class.Please enlighten me if i do anything wrong.

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

}