0

I am using onLocationChanged but it isn't giving a very precise location even though I am using the FINE_LOCATION permission. getAccuracy() usually returns 100.000 (exactly!) even though I can see from the recorded results that the accuracy is sometimes far worse than 100 metres (I am ignoring any results where the accuracy is measured as less than 101),

However, if I run another app (which also uses location) at the same time, my reported accuracy figures are much better (e.g 6.66 metres in the same location as the 100 metres otherwise recorded). So it would appear that my app isn't waiting long enough to get an accurate fix before firing onLocationChanged().

I have looked at a possible solution here but this uses GpsStatus.Listener which was deprecated a while ago, and I cannot find an example of how to use its replacent GnssStatus.Callback in a similar way.

I could try using the FusedLocationProvider API but unsure if this would fix the problem - anyway I would like to stick to the LocationManager method if possible

criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
if (setProvider() == false)
    Notify("Location Provider Error");
....
....
public boolean setProvider() {
    provider = locationManager.getBestProvider(criteria, true);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return false;
    }
    locationManager.requestLocationUpdates(provider, UPDATE_TIME, 0, locationListener);
    return true;
 }

UPDATE_TIME is normally 2 minutes but I have tried shorter times without success. I am using the location methods in a background service, but the problem still occurs while the app is running in the foreground.

public void onLocationChanged(Location location) {
    float accuracy = location.getAccuracy();
    if (accuracy < 101){
        double lat = location.getLatitude();
        double lng = location.getLongitude();
        long time = System.currentTimeMillis();
        UploadLocation(lat, lng, time);
}
quilkin
  • 874
  • 11
  • 31

1 Answers1

0

Well, I converted to using the FusedLocationProvider API and that seems to have done the trick. Simpler code as well (or will be when I have removed all the extra debugging notififactions etc)

mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, UPDATE_TIME)
            .setWaitForAccurateLocation(true)
            .setMinUpdateIntervalMillis(LocationRequest.Builder.IMPLICIT_MIN_UPDATE_INTERVAL)
            .setMaxUpdateDelayMillis(1000)
            .build();
    locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(@NonNull LocationResult locationResult) {
            List <Location> locations = locationResult.getLocations();
            Log.i("*****", String.format("%d locations",locations.size()));
            for (Location location : locations) {
                if (location != null) {
                    float accuracy = location.getAccuracy();

                    long locationTime = location.getTime();
                    long timeDelta = 0;
                    if (previousBestLocation != null)
                        timeDelta = locationTime - previousBestLocation.getTime();
                    double lat = location.getLatitude();
                    double lng = location.getLongitude();
                    if (lat < 0.01 && lng < 0.01) {
                        Notify("error: zero lat & long");
                    } else {
                        if (accuracy > 101){

                            if (timeDelta < UPDATE_TIME * 10) {
                                Notify(String.format("Poor accuracy: %f",accuracy));
                            }
                            else {
                                Notify("Poor accuracy but 20 minutes late so saving anyway");
                                UploadLocation(lat, lng,locationTime);
                                previousBestLocation = location;
                            }

                        }
                        else {
                            Notify(String.format("Accuracy %f",accuracy));
                            // try to upload to remote server. Will save locally if upload fails
                            UploadLocation(lat, lng, locationTime);
                            previousBestLocation = location;
                        }
                    }
                }
            }
        }
    };
mFusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper());
quilkin
  • 874
  • 11
  • 31