title: Android: get current location from best available provider
body: <p>I have some Android code that needs to get the best available location QUICKLY, from GPS, network or whatever is available. Accuracy is less important than speed. </p>
  
  <p>Getting the best available location is surely a really standard task. Yet I can't find any code to demonstrate it. The Android location code expects you to specify criteria, register for updates, and wait - which is fine if you have detailed criteria and don't mind waiting around. </p>
  
  <p>But my app needs to work a bit more like the Maps app does when it first locates you - work from any available provider, and just check the location isn't wildly out of date or null.</p>
  
  <p>I've attempted to roll my own code to do this, but am having problems. (It's inside an IntentService where an upload happens, if that makes any difference. I've included all the code for info.) What's wrong with this code?</p>
  
  <pre><code>@Override
  protected void onHandleIntent(Intent arg0) {
      testProviders();
      doUpload();
  }
  private boolean doUpload() {
         int j = 0;
         // check if we have accurate location data yet - wait up to 30 seconds
         while (j &lt; 30) {
             if ((latString == "") || (lonString == "")) {
                 Log.d(LOG_TAG, "latlng null");
                 Thread.sleep(1000);
                 j++;
         } else {
                  Log.d(LOG_TAG, "found lat " + latString + " and lon " + lonString);
              break;
         }
         //do the upload here anyway, with or without location data
         //[code removed for brevity]
  }
  public boolean testProviders() {
      Log.e(LOG_TAG, "testProviders");
      String location_context = Context.LOCATION_SERVICE;
      locationmanager = (LocationManager) getSystemService(location_context);
      List&lt;String&gt; providers = locationmanager.getProviders(true);
      for (String provider : providers) {
          Log.e(LOG_TAG, "registering provider " + provider);
          listener = new LocationListener() {
              public void onLocationChanged(Location location) {
                  // keep checking the location - until we have
                  // what we need
                  //if (!checkLoc(location)) {
                  Log.e(LOG_TAG, "onLocationChanged");
                  locationDetermined = checkLoc(location);
                  //}
              }
              public void onProviderDisabled(String provider) {
              }
              public void onProviderEnabled(String provider) {
              }
              public void onStatusChanged(String provider, int status,
                      Bundle extras) {
              }
          };
          locationmanager.requestLocationUpdates(provider, 0,
                  0, listener);
      }
      Log.e(LOG_TAG, "getting updates");
      return true;
  }
  private boolean checkLoc(Location location) {
      float tempAccuracy = location.getAccuracy();
      int locAccuracy = (int) tempAccuracy;
      Log.d(LOG_TAG, "locAccuracy = " + locAccuracy);
      if ((locAccuracy != 0) &amp;&amp; (locAccuracy &lt; LOCATION_ACCURACY)) {
          latitude = location.getLatitude();
          longitude = location.getLongitude();
          latString = latitude.toString();
          lonString = longitude.toString();
          return true;
      }
      return false;
  }
  public void removeListeners() {
      // Log.e(LOG_TAG, "removeListeners");
      if ((locationmanager != null) &amp;&amp; (listener != null)) {
          locationmanager.removeUpdates(listener);
      }
      locationmanager = null;
      // Log.d(LOG_TAG, "Removed " + listener.toString());
  }
  @Override
  public void onDestroy() {
      super.onDestroy();
      removeListeners();
  }
  </code></pre>
  
  <p>Unfortunately, this finds the network provider, but only ever outputs <code>latlng null</code> 30 times - it never seems to get a location at all. I never even get a log statement of <code>locationChanged</code>.</p>
  
  <p>It's funny, because from ddms I can see output like:</p>
  
  <pre><code>NetworkLocationProvider: onCellLocationChanged [305,8580]
  NetworkLocationProvider: getNetworkLocation(): returning cache location with accuracy 75.0
  </code></pre>
  
  <p>seeming to suggest that the network provider does have some location info after all, I'm just not getting at it.</p>
  
  <p>Can anyone help? I think working example code would be a useful resource for the Android/StackOverflow community.</p>