0

Hi I'm using FusedLocationClient for getting the location from the user .its working I'm able to get latitude and longitude periodically, but sometimes the distance showing wrong like it will go from 10.0 to 200.0 in seconds and then return to 10.0. I would like to show the user they are 200m away from a shop. but even if they are only 10m away app sometimes show they are 200m away from the shop.

Is there anything I can do to improve the accuracy of location Client.

   class LocServices : Service() { 
        private val TAG = ""
        private val UPDATE_INTERVAL_IN_MILLISECONDS: Long = 5000
        private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2

        private var mLocationRequest: LocationRequest? = null
        private var mFusedLocationClient: FusedLocationProviderClient? = null
        private var mLocationCallback: LocationCallback? = null
        private var mLocation: Location? = null

        var existLongitude: String? = null
        var existLatitude: String? = null
        var sharedPrefs: SharedPreferences? = null

        override fun onCreate() {
            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
            mLocationCallback = object : LocationCallback() {
                override fun onLocationResult(locationResult: LocationResult?) {
                    super.onLocationResult(locationResult)
                    onNewLocation(locationResult!!.lastLocation)
                }
            }
            createLocationRequest()
            getLastLocation()
            requestLocationUpdates()
        }

        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            Log.i(TAG, "Service started")
            return Service.START_STICKY
        }

        override fun onBind(intent: Intent): IBinder? {
            return null

        }

        private fun requestLocationUpdates() {

         sharedPrefs = this.getSharedPreferences("GEO", Context.MODE_PRIVATE)
            if (sharedPrefs != null) {
                existLatitude = sharedPrefs!!.getString("LAT", null)
                existLongitude = sharedPrefs!!.getString("LONG", null)
            }

                    if (existLatitude != null && existLongitude != null) {
                        Log.i(TAG, "Requesting location updates")
                        setRequestingLocationUpdates(this, true)
                        try {
                            mFusedLocationClient!!.requestLocationUpdates(mLocationRequest, mLocationCallback!!, Looper.myLooper())
                        } catch (unlikely: SecurityException) {
                            setRequestingLocationUpdates(this, false)
                            Log.e(TAG, "Lost location permission. Could not request updates. $unlikely")
                        }
                    }


        }
        private fun getLastLocation() {
            try {
                mFusedLocationClient!!.lastLocation
                        .addOnCompleteListener { task ->
                            if (task.isSuccessful && task.result != null) {
                                mLocation = task.result
                            } else {
                                Log.w(TAG, "Failed to get location.")
                            }
                        }
            } catch (unlikely: SecurityException) {
                Log.e(TAG, "Lost location permission.$unlikely")
            }

        }

        private fun onNewLocation(location: Location) {
            Log.i(TAG, "New location: $location")
            mLocation = location


                    if (existLatitude != null && existLongitude != null) {
                        val selected_location = Location("locationA")
                        selected_location.latitude = existLatitude!!.toDouble()
                        selected_location.longitude = existLongitude!!.toDouble()
                        val near_locations = Location("locationB")
                        near_locations.latitude = mLocation!!.latitude
                        near_locations.longitude = mLocation!!.longitude
                        val distance = selected_location.distanceTo(near_locations)
                        Toast.makeText(this, distance.toString(), Toast.LENGTH_SHORT).show()
                        if (distance > 53.0) {
                            Toast.makeText(this, "You are outside $distance", Toast.LENGTH_SHORT).show()
                        }
                    }
                }

        private fun createLocationRequest() {
            mLocationRequest = LocationRequest()
            mLocationRequest!!.interval = UPDATE_INTERVAL_IN_MILLISECONDS
            mLocationRequest!!.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
            mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }

       companion object {

            val KEY_REQUESTING_LOCATION_UPDATES = "requesting_locaction_updates"

            fun setRequestingLocationUpdates(context: Context, requestingLocationUpdates: Boolean) {
                PreferenceManager.getDefaultSharedPreferences(context)
                        .edit()
                        .putBoolean(KEY_REQUESTING_LOCATION_UPDATES, requestingLocationUpdates)
                        .apply()
            }
        }

    }
J. Shiv
  • 144
  • 4

1 Answers1

0

I think what's best to calculate distance from GPS is to calculate distance between two Locations and add. To calculate distance between two locations -

 public static double GetDistanceInMeter(Location source, Location destination) {
    double distance = 0d;
    if (source != null && destination != null) {
        double lat1 = source.getLatitude();
        double lon1 = source.getLongitude();
        double lat2 = destination.getLatitude();
        double lon2 = destination.getLongitude();

        final int R = 6371;
        // Radius of the earth in km
        double dLat = deg2rad(lat2 - lat1);
        // deg2rad below
        double dLon = deg2rad(lon2 - lon1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        // Distance in m
        distance = (R * c) * 1000;
    }
    return distance;
}

The approach is to save the previous location, and then calculate distance between the old and the new and then add it to total distance. This the best approach to this problem and also the most accurate. Since the GPS is not that accurate so your total traveled distance will be +-50 meters.

Ashutosh Sagar
  • 981
  • 8
  • 20
  • i have edited the question, problem was not with the distance calculation , your methods is giving the same result as "float distanceTo(Location dest)". i think latlong value changes to more than 50m when entering and exiting a building. can this happen or is my implementation wrong? – J. Shiv Jun 04 '18 at 06:25