2

I've a challenges task for getting very high accuracy. So I am using GPS_PROVIDER. But my code is getting incorrect accuracy. some time it shows me 10 to 50 meter from my current location. and some time it shows me 5 to 15 meter distance from my current location. I've tested it two devices as XOLO and Sony. I've completed involved with that problems and not able to fix it. This is my code:-

@Override
protected void onResume() {
    super.onResume();

    if(mMap!= null)
        mMaprivate LatLng geo;
map.clear();

    locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);             
    mFragment = (SupportMapFragment) this.getSupportFragmentManager().findFragmentById(R.id.map);
    mMap = mFragment.getMap(); 
    }
   setListener();
 }

private void setListener() {    
    System.out.println("setListener()  locationListener = "+locationListener);
    if(locationListener != null){
        clearListener();
    }

    Toast toast = Toast.makeText(this, this.getResources().getString(R.string.maps_loading), Toast.LENGTH_LONG);
    toast.show();   
    private LatLng geo;

    locationListener = new CustomLocationListener();

    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    //criteria.setAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
    String bestProvider = locationManager.getBestProvider(criteria, true); 
    Toast.makeText(this, "bestProvider= "+bestProvider, Toast.LENGTH_SHORT).show();
//  locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
   locationManager.requestLocationUpdates(bestProvider, 0, 0, locationListener);

    handler=new Handler();
    timeoutTask = new TimeoutTask(locationListener);
    handler.postDelayed(timeoutTask, 50*1000);
}

private void clearListener(){
    if(locationListener != null){
        locationManager.removeUpdates(locationListener);
        locationListener = null;
    }
}

private void gotLocation(Location location){
    loc = location;
    System.out.println("getLocation = "+location.getLatitude());
 //   Toast.makeText(getBaseContext(), "new Lat = "+location.getLatitude(), Toast.LENGTH_LONG).show();
}

public class CustomLocationListener implements LocationListener {
    private boolean isCompleted = false;

    public CustomLocationListener() {}

    @Override
    public void onLocationChanged(Location location) {
        isCompleted=true;

        System.out.println("onLocationChanged 1");

          // Called when a new location is found by the GPS location provider.
          if(isBetterLocation(location, loc)){
            //  Toast.makeText(getBaseContext(), "yes", Toast.LENGTH_LONG).show();
              System.out.println("onLocationChanged 2");
              gotLocation(location);
          }
          System.out.println("onLocationChanged 3");
          clearListener();
          setUserPoint();
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) { }

    @Override
    public void onProviderEnabled(String provider) { }

    @Override
    public void onProviderDisabled(String provider) { }

    public boolean isCompleted() {
        return isCompleted;
    }private LatLng geo;

}   
private LatLng geo;

 public class TimeoutTask implements Runnable {

    private CustomLocationListener listener;

    public TimeoutTask(CustomLocationListener listener) {
        this.listener=listener;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        if (listener == null || listener.isCompleted()) {
            Log.e("provider", "completed");
       }
        else {
            Toast.makeText(ScorecardMapViewActivity.this, "We were unable to find your position, please try again", Toast.LENGTH_LONG).show();
            Log.e("provider", "timeout");
            clearListener();
            setUserPoint();
            if(goToScorecardStep3WithLocation) finish(); 
        }
    }
}



protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true;
    }

    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // If it's been more than two minutes since the current location, use the new location
    // because the user has likely moved
    if (isSignificantlyNewer) {
        return true;
    // If the new location is more than two minutes older, it must be worse
    } else if (isSignificantlyOlder) {
        return false;
    }

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
            currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true;
    }
    return false;
}

private LatLng geo;

private void setUserPoint() {
    if(!goToScorecardStep3WithLocation) {
    if(loc != null) {

         if(handler != null) { System.out.println("removed timeout task from handler");
            handler.removeCallbacks(timeoutTask); }

        geo = HelperUtil.getLatLng(loc);
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(geo, 18));
        mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        System.out.println("loc.getLatitude() = "+loc.getLatitude());
        System.out.println("loc.getLongitude() = "+loc.getLongitude());

        // your current position show.
         mMap.addMarker(new MarkerOptions().title("Player").position(geo)
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.map_point)));
}
}
}

Please any one expert help me. your help will be very helpful. Thank you!

updated:-

I noted if I am at same place. Sometime I am getting Long decimal points and sometime small decimal points. is there make any effect to calculate distance due to decimal points also? I am calculating distance in Yard.

current location = Lat 28.65361000000004 Long = 77.4122733333333

previous Current Location points ( this is same place but lat/long is different)

Lat = 28.653685000000003 Long = 77.4123083333334

I got 8 yard distance. I think some problem may be due to long or small digits points. is there way so that we can get only long decimal points?

Rahul Rawat
  • 999
  • 2
  • 17
  • 40
  • where you are testing your app?? as per fact that GPS does not work everywhere ( i.e. inside buildings). So they used other providers (WiFi, network, etc) along side sensors to give the best location possible. – Sree Jul 04 '14 at 08:33
  • 2
    Accuracy changes usually all the time (depending where you are). There is nothing that you can do about it. Some devices have better GPS (like those using GLONASS satellites also). – Hardy Jul 04 '14 at 08:34
  • @Sree Yes I am testing outdoor or open sky – Rahul Rawat Jul 04 '14 at 08:37
  • @Hardy said it, it all depends, we cant tell how you get, better try with different place and device, accuracy always change – Sree Jul 04 '14 at 08:39
  • @Hardy is there any one way for fixing it? or any logic – Rahul Rawat Jul 04 '14 at 08:39
  • There is an app named SWING BY SWING in google play and always show me good accuracy – Rahul Rawat Jul 04 '14 at 08:41
  • I did it **locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 900000, 500, locationListener);** and it gave me a bit more accuracy. – Rahul Rawat Jul 04 '14 at 08:45
  • Have you actually read the documentation and understood what those parameters are for? – jcaron Jul 04 '14 at 08:47
  • @jcaron yes, it will refresh and update to listener after 15 min if i covered a given distance. – Rahul Rawat Jul 04 '14 at 08:50
  • @jcaron i think, it will not make any effect in accuracy – Rahul Rawat Jul 04 '14 at 08:50
  • Accuracy depends of your device hardware so not really.. One option (that at least google maps is using) is to request new "fresh" location with some constant interval instead of using build-in interval. This is done by starting and stopping the gps. – Hardy Jul 04 '14 at 08:56
  • @Hardy thx, which constant should i need to use? so that as comparsion with googlemap, my location will also be display current as google map is showing – Rahul Rawat Jul 04 '14 at 09:27
  • http://en.wikipedia.org/wiki/Differential_GPS – TreyA Jul 04 '14 at 11:46
  • How do you know that you are off by 10m? What is your reference? A google map, or a high precision GPS device? – AlexWien Jul 04 '14 at 12:53
  • I am saving my current location by taping on map-point. and close the activity. afterthat I again opened that activity and it try to findout location. then i have **currentlocation lat/long** and **previous saved location lat/long** . then i am doing the distance between them. so i stand at same position and dong all these things, it should be display me **0.0** not incorrect like 10, 15, 45 etc – Rahul Rawat Jul 04 '14 at 12:57
  • @RahulRawat I think you need to get a better understanding of how physical devices (like GPS) work. Nothing is ever exact. There's too many random elements that can be just a bit off to insure exactitude. Hell, GPS has to take general relativity into account! Even if you were willing to pay thousands for a high end GPS device (cell phones are mid grade at best- a car GPS unit will be much more accurate, and military grade will kill them both) this is true. Whenever you deal with physical devices you should be thinking in terms of approximations and statistics, not expecting exact answers. – Gabe Sechan Jul 12 '14 at 06:16
  • I remember there was there a bounty of 100 points started, is that gone? – AlexWien Jul 19 '14 at 01:22
  • @AlexWien- I updated my question please check – Rahul Rawat Jul 21 '14 at 08:19
  • @RahulRawat THis is a new question, please remove your edit, and ask a new question. – AlexWien Jul 21 '14 at 11:16
  • @AlexWien- Th is not new question. Just has few logic for solving this question. – Rahul Rawat Jul 21 '14 at 13:43

2 Answers2

11

Consumer GPS receivers have an acuracy of 2.5-6m in 95% of cases, you cannot improve that for moving devices.

If you stand still (by user interaction that tells start of standstill, and end-of-standstill), you can calculate the average position.
Especially when standing still GPS chips have a bit less acuracy because the doppler shift can only be used while moving.

To caluclate the accuracy of your device you should take some measures, caluclate the average position, and calculate for each measure the distance to that average position. This then should give a value between 3-6m.

You wrote, that you expect 0m distance between two location while standing still.
But this does not work with GPS. Due fluctating conditions in the troposphere, the signal delay slightly vary, causing jumping position while standing still.

You only get 0m if you have enabled a stand still filter, which iOS uses by default. There should also a possibility in Android to enable such a filter (E.g by setting distance threshold to a value higher than 0).

AlexWien
  • 28,470
  • 6
  • 53
  • 83
2

In the OnLocation method check the location accuracy if it's not suitable the next call to OnLocation will generally be more accurate. More accuracy requires more work. You've seen the google map display a circle around the location and possibly watched it decrease in size. The radius of the circle is based on the location accuracy witch is a property of Location.

The below method works great. I have extensively tested it while driving, biking, walking the dog, and on the Harley. It filters out going in Mcd's and having the location come up in Texas where the Mcd's wifi provider is based and those pesky off by 100m locations.

@Override
public void onLocationChanged(Location location) {


    if (!location.hasAccuracy()) {
            return;
        }
        if (location.getAccuracy() > myDesiredAccuracy) {
            return;
        }

//blah what your app does...

    isCompleted=true;

    System.out.println("onLocationChanged 1");

      // Called when a new location is found by the GPS location provider.
      if(isBetterLocation(location, loc)){
        //  Toast.makeText(getBaseContext(), "yes", Toast.LENGTH_LONG).show();
          System.out.println("onLocationChanged 2");
          gotLocation(location);
      }
      System.out.println("onLocationChanged 3");
      clearListener();
      setUserPoint();
}

Note: Sometimes you get into a dead spot where you just can't get good GPS reception. These are caused by being inside a building, power lines, line of sight, cut freeways, unmapped wifi in buildings, other devices emitting radio signals that interfere with the GPS satellite reception. Basically anything that can interfere with radio reception can interfere with GPS.

danny117
  • 5,581
  • 1
  • 26
  • 35
  • hi @danny117 what accuracy setting would you set for tracking a runner? I am building a running app and would like to know. – KvnH Aug 19 '15 at 10:06
  • 1
    I would do 5 seconds 40 meters with the google location provider. Reads like send me locations every 5 seconds but only when the distance is more than 40 meters. – danny117 Aug 19 '15 at 14:54