page.title=Displaying the Location Address parent.title=Making Your App Location Aware parent.link=index.html trainingnavtop=true previous.title=Obtaining the Current Location previous.link=currentlocation.html @jd:body
LocationAware.zip
As shown in previous lessons, location updates are received in the form of latitude and longitude coordinates. While this format is useful for calculating distance or displaying a pushpin on a map, the decimal numbers make no sense to most end users. If you need to display a location to user, it is much more preferable to display the address instead.
Reverse-geocoding is the process of translating latitude longitude coordinates to a human-readable address. The {@link android.location.Geocoder} API is available for this purpose. Note that behind the scene, the API is dependent on a web service. If such service is unavailable on the device, the API will throw a "Service not Available exception" or return an empty list of addresses. A helper method called {@link android.location.Geocoder#isPresent()} was added in Android 2.3 (API level 9) to check for the existence of the service.
The following code snippet demonstrates the use of the {@link android.location.Geocoder} API to perform reverse-geocoding. Since the {@link android.location.Geocoder#getFromLocation(double, double, int) getFromLocation()} method is synchronous, you should not invoke it from the UI thread, hence an {@link android.os.AsyncTask} is used in the snippet.
private final LocationListener listener = new LocationListener() { public void onLocationChanged(Location location) { // Bypass reverse-geocoding if the Geocoder service is not available on the // device. The isPresent() convenient method is only available on Gingerbread or above. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && Geocoder.isPresent()) { // Since the geocoding API is synchronous and may take a while. You don't want to lock // up the UI thread. Invoking reverse geocoding in an AsyncTask. (new ReverseGeocodingTask(this)).execute(new Location[] {location}); } } ... }; // AsyncTask encapsulating the reverse-geocoding API. Since the geocoder API is blocked, // we do not want to invoke it from the UI thread. private class ReverseGeocodingTask extends AsyncTask<Location, Void, Void> { Context mContext; public ReverseGeocodingTask(Context context) { super(); mContext = context; } @Override protected Void doInBackground(Location... params) { Geocoder geocoder = new Geocoder(mContext, Locale.getDefault()); Location loc = params[0]; List<Address> addresses = null; try { // Call the synchronous getFromLocation() method by passing in the lat/long values. addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1); } catch (IOException e) { e.printStackTrace(); // Update UI field with the exception. Message.obtain(mHandler, UPDATE_ADDRESS, e.toString()).sendToTarget(); } if (addresses != null &s;&s; addresses.size() > 0) { Address address = addresses.get(0); // Format the first line of address (if available), city, and country name. String addressText = String.format("%s, %s, %s", address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "", address.getLocality(), address.getCountryName()); // Update the UI via a message handler. Message.obtain(mHandler, UPDATE_ADDRESS, addressText).sendToTarget(); } return null; } }