| page.title=Displaying a Location Address |
| |
| trainingnavtop=true |
| |
| @jd:body |
| |
| |
| |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| |
| <h2>This lesson teaches you to</h2> |
| <ol> |
| <li><a href="#DefineTask">Define the Address Lookup Task</a></li> |
| <li><a href="#DisplayResults">Define a Method to Display the Results</a></li> |
| <li><a href="#RunTask">Run the Lookup Task</a></li> |
| </ol> |
| |
| <h2>You should also read</h2> |
| <ul> |
| <li> |
| <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a> |
| </li> |
| <li> |
| <a href="retrieve-current.html">Retrieving the Current Location</a> |
| </li> |
| <li> |
| <a href="receive-location-updates.html">Receiving Location Updates</a> |
| </li> |
| </ul> |
| <h2>Try it out</h2> |
| |
| <div class="download-box"> |
| <a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download |
| the sample app</a> |
| <p class="filename">LocationUpdates.zip</p> |
| </div> |
| |
| </div> |
| </div> |
| |
| <p> |
| The lessons <a href="retrieve-current.html">Retrieving the Current Location</a> and |
| <a href="receive-location-updates.html">Receiving Location Updates</a> describe how to get the |
| user's current location in the form of a {@link android.location.Location} object that |
| contains latitude and longitude coordinates. Although latitude and longitude are useful for |
| calculating distance or displaying a map position, in many cases the address of the location is |
| more useful. |
| </p> |
| <p> |
| The Android platform API provides a feature that returns an estimated street addresses for |
| latitude and longitude values. This lesson shows you how to use this address lookup feature. |
| </p> |
| <p class="note"> |
| <strong>Note:</strong> Address lookup requires a backend service that is not included in the |
| core Android framework. If this backend service is not available, |
| {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()} returns an empty |
| list. The helper method {@link android.location.Geocoder#isPresent isPresent()}, available |
| in API level 9 and later, checks to see if the backend service is available. |
| </p> |
| <p> |
| The snippets in the following sections assume that your app has already retrieved the |
| current location and stored it as a {@link android.location.Location} object in the global |
| variable {@code mLocation}. |
| </p> |
| <!-- |
| Define the address lookup task |
| --> |
| <h2 id="DefineTask">Define the Address Lookup Task</h2> |
| <p> |
| To get an address for a given latitude and longitude, call |
| {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a |
| list of addresses. The method is synchronous, and may take a long time to do its work, so you |
| should call the method from the {@link android.os.AsyncTask#doInBackground |
| doInBackground()} method of an {@link android.os.AsyncTask}. |
| </p> |
| <p> |
| While your app is getting the address, display an indeterminate activity |
| indicator to show that your app is working in the background. Set the indicator's initial state |
| to {@code android:visibility="gone"}, to make it invisible and remove it from the layout |
| hierarchy. When you start the address lookup, you set its visibility to "visible". |
| </p> |
| <p> |
| The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to |
| your layout file: |
| </p> |
| <pre> |
| <ProgressBar |
| android:id="@+id/address_progress" |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:layout_centerHorizontal="true" |
| android:indeterminate="true" |
| android:visibility="gone" /> |
| </pre> |
| <p> |
| To create the background task, define a subclass of {@link android.os.AsyncTask} that calls |
| {@link android.location.Geocoder#getFromLocation getFromLocation()} and returns an address. |
| Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned |
| address, and a {@link android.widget.ProgressBar} object that allows you to control the |
| indeterminate activity indicator. For example: |
| </p> |
| <pre> |
| public class MainActivity extends FragmentActivity { |
| ... |
| private TextView mAddress; |
| private ProgressBar mActivityIndicator; |
| ... |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| ... |
| mAddress = (TextView) findViewById(R.id.address); |
| mActivityIndicator = |
| (ProgressBar) findViewById(R.id.address_progress); |
| } |
| ... |
| /** |
| * A subclass of AsyncTask that calls getFromLocation() in the |
| * background. The class definition has these generic types: |
| * Location - A {@link android.location.Location} object containing |
| * the current location. |
| * Void - indicates that progress units are not used |
| * String - An address passed to onPostExecute() |
| */ |
| private class GetAddressTask extends |
| AsyncTask<Location, Void, String> { |
| Context mContext; |
| public GetAddressTask(Context context) { |
| super(); |
| mContext = context; |
| } |
| ... |
| /** |
| * Get a Geocoder instance, get the latitude and longitude |
| * look up the address, and return it |
| * |
| * @params params One or more Location objects |
| * @return A string containing the address of the current |
| * location, or an empty string if no address can be found, |
| * or an error message |
| */ |
| @Override |
| protected String doInBackground(Location... params) { |
| Geocoder geocoder = |
| new Geocoder(mContext, Locale.getDefault()); |
| // Get the current location from the input parameter list |
| Location loc = params[0]; |
| // Create a list to contain the result address |
| List<Address> addresses = null; |
| try { |
| /* |
| * Return 1 address. |
| */ |
| addresses = geocoder.getFromLocation(loc.getLatitude(), |
| loc.getLongitude(), 1); |
| } catch (IOException e1) { |
| Log.e("LocationSampleActivity", |
| "IO Exception in getFromLocation()"); |
| e1.printStackTrace(); |
| return ("IO Exception trying to get address"); |
| } catch (IllegalArgumentException e2) { |
| // Error message to post in the log |
| String errorString = "Illegal arguments " + |
| Double.toString(loc.getLatitude()) + |
| " , " + |
| Double.toString(loc.getLongitude()) + |
| " passed to address service"; |
| Log.e("LocationSampleActivity", errorString); |
| e2.printStackTrace(); |
| return errorString; |
| } |
| // If the reverse geocode returned an address |
| if (addresses != null && addresses.size() > 0) { |
| // Get the first address |
| Address address = addresses.get(0); |
| /* |
| * Format the first line of address (if available), |
| * city, and country name. |
| */ |
| String addressText = String.format( |
| "%s, %s, %s", |
| // If there's a street address, add it |
| address.getMaxAddressLineIndex() > 0 ? |
| address.getAddressLine(0) : "", |
| // Locality is usually a city |
| address.getLocality(), |
| // The country of the address |
| address.getCountryName()); |
| // Return the text |
| return addressText; |
| } else { |
| return "No address found"; |
| } |
| } |
| ... |
| } |
| ... |
| } |
| </pre> |
| <p> |
| The next section shows you how to display the address in the user interface. |
| </p> |
| <!-- Define a method to display the address --> |
| <h2 id="DisplayResults">Define a Method to Display the Results</h2> |
| <p> |
| {@link android.os.AsyncTask#doInBackground doInBackground()} returns the result of the address |
| lookup as a {@link java.lang.String}. This value is passed to |
| {@link android.os.AsyncTask#onPostExecute onPostExecute()}, where you do further processing |
| on the results. Since {@link android.os.AsyncTask#onPostExecute onPostExecute()} |
| runs on the UI thread, it can update the user interface; for example, it can turn off the |
| activity indicator and display the results to the user: |
| </p> |
| <pre> |
| private class GetAddressTask extends |
| AsyncTask<Location, Void, String> { |
| ... |
| /** |
| * A method that's called once doInBackground() completes. Turn |
| * off the indeterminate activity indicator and set |
| * the text of the UI element that shows the address. If the |
| * lookup failed, display the error message. |
| */ |
| @Override |
| protected void onPostExecute(String address) { |
| // Set activity indicator visibility to "gone" |
| mActivityIndicator.setVisibility(View.GONE); |
| // Display the results of the lookup. |
| mAddress.setText(address); |
| } |
| ... |
| } |
| </pre> |
| <p> |
| The final step is to run the address lookup. |
| </p> |
| <!-- Get and display the address --> |
| <h2 id="RunTask">Run the Lookup Task</h2> |
| <p> |
| To get the address, call {@link android.os.AsyncTask#execute execute()}. For example, the |
| following snippet starts the address lookup when the user clicks the "Get Address" button: |
| </p> |
| <pre> |
| public class MainActivity extends FragmentActivity { |
| ... |
| /** |
| * The "Get Address" button in the UI is defined with |
| * android:onClick="getAddress". The method is invoked whenever the |
| * user clicks the button. |
| * |
| * @param v The view object associated with this method, |
| * in this case a Button. |
| */ |
| public void getAddress(View v) { |
| // Ensure that a Geocoder services is available |
| if (Build.VERSION.SDK_INT >= |
| Build.VERSION_CODES.GINGERBREAD |
| && |
| Geocoder.isPresent()) { |
| // Show the activity indicator |
| mActivityIndicator.setVisibility(View.VISIBLE); |
| /* |
| * Reverse geocoding is long-running and synchronous. |
| * Run it on a background thread. |
| * Pass the current location to the background task. |
| * When the task finishes, |
| * onPostExecute() displays the address. |
| */ |
| (new GetAddressTask(this)).execute(mLocation); |
| } |
| ... |
| } |
| ... |
| } |
| </pre> |
| <p> |
| The next lesson, <a href="geofencing.html">Creating and Monitoring Geofences</a>, demonstrates |
| how to define locations of interest called <b>geofences</b> and how to use geofence monitoring |
| to detect the user's proximity to a location of interest. |
| </p> |