It is notoriously difficult for GPS chips to get a good fix in built-up areas. 'Seeing the sky' is a bit loose a formulation: ideally a unit has to be able to see five or more satellites and for accuracy purposes they must not be all exactly overhead. Furthermore buildings bounce back the signals adding to confusion. On a clear mountain top is best, maybe the top of Canary Wharf tower. That's why there have been different approaches to improve GPS accuracy, e.g. triangulation from cell-towers. Skyhook Wireless claim to have a library that improves accuracy, apparently newer versions of AndNav use it. Other applications assume that you are always on a road and will place you on the nearest one.
I just published a little application that gives you a view of the satellite constellation used to derive your location. You can get it here: http://andappstore.com/AndroidPhoneApplications/apps/38257 <http://andappstore.com/AndroidPhoneApplications/apps/38257>That does not itself improve accuracy, but at least you can get an idea why your accuracy is shite.. Ludwig 2009/2/11 Anna PS <[email protected]> > > Hi, > > I'm writing a mapping application. In simple terms, it sends some info > about the user's current location to a server when the user clicks on > a button. > > I need the location to be absolutely correct, and when I first started > to implement LocationListener, I found that it often wasn't. So I've > used location.getAccuracy() to check the GPS accuracy, and warn the > user - without submitting the data - if the location isn't accurate > enough. > > The code is below. > > I've been trying the app outside and find that the accuracy is often > 32m, 64m or even higher, even after 20 or 30 seconds. This is in > central London, in full view of the sky, on a clear day! I need it to > be below 10m. > > At the same time, if I open the Maps application while standing in the > same spot, it shows my GPS location as a blue spot on the map - > suggesting the listener in Maps has perfect accuracy. > > So what is the problem? Have I implemented the listener/check in the > wrong way (which feels like the likely explanation), or is it that GPS > in Android isn't good enough to write mapping applications? Does > anyone else have experience of this? > > Best, > Anna > > -------------------------------------------------- > > //cut-down version of code > > public class GPSTest extends Activity { > > /** Called when the activity is first created. */ > private static final String LOG_TAG = "GPSTest"; > > private Double latitude = 0.0; > private Double longitude = 0.0; > private String latString = ""; > private String longString = ""; > > //Location items > LocationManager locationmanager; > LocationListener listener; > Location location; > private float gpsAccuracy; > private long locationTime; > private long currentTime; > private long timeDifference; > > //Textview and button > private TextView tvErrorMessage; > private View submitButton; > > private String responseString; > > private ProgressDialog pd; > final Handler mHandler = new Handler(); > final Runnable mUpdateResults = new Runnable() { > public void run() { > pd.dismiss(); > updateResultsInUi(); > } > }; > > private static int globalStatus = 0; > private static final int GPS_NOT_FOUND = 1; > private static final int GPS_OK = 2; > > @Override > public void onCreate(Bundle savedInstanceState) { > super.onCreate(savedInstanceState); > Log.d(LOG_TAG, "onCreate"); > setContentView(R.layout.main); > > // Set up the button listeners > findViews(); > setListeners(); > > // Register with GPS, throw an error if there's a failure > if (!testProviders()) { > tvErrorMessage > .setText("Can't get location - check > that GPS is turned on in > Settings"); > } > } > > @Override > public void onRestart() { > super.onRestart(); > Log.d(LOG_TAG, "onRestart"); > // Register with GPS, throw an error if there's a failure > if (!testProviders()) { > tvErrorMessage > .setText("Can't get location - check > that GPS is turned on in > Settings"); > } > } > > // > ********************************************************************** > // findViews/setListeners: set up the button listeners > // > ********************************************************************** > > private void findViews() { > Log.d(LOG_TAG, "findViews"); > submitButton = (Button) findViewById(R.id.submit_button); > tvErrorMessage = (TextView) findViewById(R.id.tv_error); > > } > > private void setListeners() { > Log.d(LOG_TAG, "setListeners"); > submitButton.setOnClickListener(new OnClickListener() { > public void onClick(View v) { > uploadToServer(); > } > } > }); > } > > > // > ********************************************************************** > // testProviders: Register for location updates, warn if not found > // > ********************************************************************** > public boolean testProviders() { > Log.d(LOG_TAG, "testProviders"); > String location_context = Context.LOCATION_SERVICE; > locationmanager = (LocationManager) getSystemService > (location_context); > listener = new LocationListener() { > public void onLocationChanged(Location location) { > } > > public void onProviderDisabled(String provider) { > } > > public void onProviderEnabled(String provider) { > } > > public void onStatusChanged(String provider, int > status, > Bundle extras) { > } > }; > > locationmanager.requestLocationUpdates("gps", 0, 0, > listener); > > location = locationmanager.getLastKnownLocation("gps"); > > if (location != null) { > latitude = location.getLatitude(); > longitude = location.getLongitude(); > latString = latitude.toString(); > longString = longitude.toString(); > Log.d(LOG_TAG, "Location found: latitude" + > latString > + " and longitude " + longString); > return true; > > } else { > Log.d(LOG_TAG, "Location not found"); > return false; > } > > } > > > // > ********************************************************************** > // uploadToServer: uploads details, handled via a background thread > // Also checks the age and accuracy of the GPS data first > // > ********************************************************************** > private void uploadToServer() { > Log.d(LOG_TAG, "uploadToServer"); > pd = ProgressDialog > .show( > this, > "Uploading, please wait...", > "Uploading GPS location. > This can take several seconds. Please > be patient!", > true, false); > Thread t = new Thread() { > public void run() { > doUploadinBackground(); > mHandler.post(mUpdateResults); > } > }; > t.start(); > } > > private boolean doUploadinBackground() { > Log.d(LOG_TAG, "doUploadinBackground"); > DefaultHttpClient httpclient = new DefaultHttpClient(); > HttpPost httppost = new HttpPost(<##uri##>); > > // get GPS info - make sure it's sufficiently accurate > if (location != null) { > // Check that the location is up-to-date and > reasonably accurate > locationTime = location.getTime(); > currentTime = System.currentTimeMillis(); > timeDifference = (currentTime - locationTime) / > 1000; > > gpsAccuracy = location.getAccuracy(); > int count = 0; > > // Wait for accurate GPS data, up to a maximum of 5 > seconds before > // throwing an error > while (((timeDifference > 30) || (gpsAccuracy > > 10.0)) > && (count < 10)) { > location = > locationmanager.getLastKnownLocation("gps"); > locationTime = location.getTime(); > currentTime = System.currentTimeMillis(); > timeDifference = (currentTime - > locationTime) / 1000; > gpsAccuracy = location.getAccuracy(); > Log.d(LOG_TAG, "getting up to date GPS data, > time diff = " > + timeDifference + " & > accuracy = " + gpsAccuracy > + " & count = " + count); > try { > Thread.currentThread(); > Thread.sleep(500); > } catch (InterruptedException ie) { > } > count++; > } > > // No accurate GPS data? Exit here and warn the user > if ((timeDifference > 10) || (gpsAccuracy > 20.0)) { > globalStatus = GPS_NOT_FOUND; > return false; > } > > // OK, we're here, so we have an up-to-date, > accurate location: > // commit all the GPS info > latitude = location.getLatitude(); > longitude = location.getLongitude(); > latString = latitude.toString(); > longString = longitude.toString(); > Log.d(LOG_TAG, "Location found: latitude" + > latString > + " and longitude " + longString); > Log.d(LOG_TAG, "locationTime = " + locationTime > + ", currentTime = " + currentTime > + ", time difference in seconds " + > timeDifference); > globalStatus = GPS_OK; > return true; > > } else { > Log.d(LOG_TAG, "Location not found"); > return false; > } > > } > > private void updateResultsInUi() { > // Update the UI > if (globalStatus == GPS_NOT_FOUND) { > tvErrorMessage > .setText("ERROR - couldn't get > up-to-date/accurate GPS location. > Accuracy was " > + gpsAccuracy > + " meters, > locationTime was " > + locationTime > + " and currentTime > was " > + currentTime > + " so > timeDifference was " > + timeDifference > + ". Please check > that you can see the sky!"); > } else { > tvErrorMessage > .setText("SUCCESS - accuracy was " > + gpsAccuracy > + " meters, > locationTime was " > + locationTime > + " and currentTime > was " > + currentTime > + " so > timeDifference was " > + timeDifference > + ". Please check > that you can see the sky!"); > } > } > > // > ********************************************************************** > // onPause: unregister the LocationListener > // > ********************************************************************** > > @Override > public void onPause() { > Log.d(LOG_TAG, "onPause"); > // Unregister the LocationListener > locationmanager.removeUpdates(listener); > super.onPause(); > } > > } > > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en -~----------~----~----~----~------~----~------~--~---

