Search code examples
androidandroid-locationandroid-fusedlocation

FusedLocationProviderClient gives different location sometimes


 public void getDeviceLocation() {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(getMvpView().getActivity());
        settingsClient = LocationServices.getSettingsClient(getMvpView().getActivity());
        createLocationCallback();
        createLocationRequest();
        buildLocationSettingsRequest();
        startLocationUpdates();
    }


    private void createLocationRequest() {
        locationRequest = new LocationRequest();
        locationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        locationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }


    private void createLocationCallback() {
        getMvpView().showProgressDialog();
        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                Location currentLocation = locationResult.getLastLocation();
                getMvpView().showSelectedAddress(getAddressFromLatLng(currentLocation.getLatitude(), currentLocation.getLongitude()));
                fusedLocationClient.removeLocationUpdates(locationCallback);
                getMvpView().hideProgressDialog();
            }
        };
    }


    private void buildLocationSettingsRequest() {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(locationRequest);
        locationSettingsRequest = builder.build();
    }


    private void startLocationUpdates() {
        settingsClient.checkLocationSettings(locationSettingsRequest)
                .addOnSuccessListener(getMvpView().getActivity(), locationSettingsResponse -> {

                    if (ActivityCompat.checkSelfPermission(getMvpView().getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getMvpView().getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    fusedLocationClient.requestLocationUpdates(locationRequest,
                            locationCallback, Looper.myLooper());

                }).addOnFailureListener(getMvpView().getActivity(), e -> {
            getMvpView().hideProgressDialog();
            getMvpView().showErrorToast(R.string.please_enable_location);
        });
    }


    @SuppressLint("MissingPermission")
    private void startLocationUpdates() {
        settingsClient.checkLocationSettings(locationSettingsRequest)
                .addOnSuccessListener(getMvpView().getActivity(), locationSettingsResponse -> {
                    fusedLocationClient.requestLocationUpdates(locationRequest,
                            locationCallback, Looper.myLooper());

                }).addOnFailureListener(getMvpView().getActivity(), e -> {
            getMvpView().hideProgressDialog();
            getMvpView().showErrorToast(R.string.please_enable_location);
        });
    }


    private String getAddressFromLatLng(double latitude, double longitude) {
        Geocoder geocoder = new Geocoder(getMvpView().getActivity(), Locale.getDefault());
        List<Address> addresses = null;
        try {
            addresses = geocoder.getFromLocation(
                    latitude,
                    longitude,
                    1);
        } catch (IOException e) {
            e.printStackTrace();
        }

        Address address = addresses.get(0);
        StringBuilder addressStringBuilder = new StringBuilder();
        for (int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
            addressStringBuilder.append(address.getAddressLine(i));
        }

        return addressStringBuilder.toString();
    }

I have converted the lat, lng to address text but after i query again for location the address changes even i have not moved from my current location, enabled accuracy in phone settings too. The issue is when i always query it should give me the same location address if my lat, lng postion is not changed.


Solution

  • FusedLocationProviderClient means combining gps and google-translating-received-wlan-cellphone-tower-signals-to-lat-lon.

    The google-translating-received-wlan-cellphone-tower-signals-to-lat-lon is an inexact heuristics that among other factors depends to which cellphone-tower your handy is connected to (and where google has lat/lon for each tower) and how stronge the strongest 3 cellphonetowers are.

    If your cellphone changes it's cellphone-tower-connection then for googl-s algorithm your phone position has changed.

    If your cellphone can receive more than 3 cellphone towers the strongest 3 cellphonetowers will also change depending how much trafic each celltower has.

    A gps-receiver costs a lot of energy. When gps-energy-optimisation is enabled then there may be also gps-precision issuses causing the fused location to jump.

    I learned this the hard way when doing geocaching for the first time with my brand new cellpone and wondered why my own position jumped in the map