Merge "docs: Adds new geocoding sample to Location API training. Uses GoogleApiClient to connect to Play services. Uses the latest Fused Location Provider API." into lmp-docs

This commit is contained in:
Sarah Maddox
2015-01-26 20:12:21 +00:00
committed by Android (Google) Code Review

View File

@@ -1,28 +1,27 @@
page.title=Displaying a Location Address page.title=Displaying a Location Address
trainingnavtop=true trainingnavtop=true
@jd:body @jd:body
<div id="tb-wrapper"> <div id="tb-wrapper">
<div id="tb"> <div id="tb">
<h2>This lesson teaches you to</h2> <h2>This lesson teaches you how to</h2>
<ol> <ol>
<li><a href="#DefineTask">Define the Address Lookup Task</a></li> <li><a href="#connect">Get a Geographic Location</a></li>
<li><a href="#DisplayResults">Define a Method to Display the Results</a></li> <li><a href="#fetch-address">Define an Intent Service to Fetch the
<li><a href="#RunTask">Run the Lookup Task</a></li> Address</a></li>
<li><a href="#start-intent">Start the Intent Service</a></li>
<li><a href="#result-receiver">Receive the Geocoding Results</a></li>
</ol> </ol>
<h2>You should also read</h2> <h2>You should also read</h2>
<ul> <ul>
<li> <li>
<a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a> <a href="{@docRoot}google/play-services/setup.html">Setting up Google
Play Services</a>
</li> </li>
<li> <li>
<a href="retrieve-current.html">Retrieving the Current Location</a> <a href="retrieve-current.html">Getting the Last Known Location</a>
</li> </li>
<li> <li>
<a href="receive-location-updates.html">Receiving Location Updates</a> <a href="receive-location-updates.html">Receiving Location Updates</a>
@@ -30,251 +29,440 @@ trainingnavtop=true
</ul> </ul>
<h2>Try it out</h2> <h2>Try it out</h2>
<div class="download-box"> <ul>
<a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download <li>
the sample app</a> <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationAddress" class="external-link">LocationAddress</a>
<p class="filename">LocationUpdates.zip</p> </li>
</div> </ul>
</div> </div>
</div> </div>
<p> <p>The lessons <a href="retrieve-current.html">Getting the Last Known
The lessons <a href="retrieve-current.html">Retrieving the Current Location</a> and Location</a> and <a href="receive-location-updates.html">Receiving Location
<a href="receive-location-updates.html">Receiving Location Updates</a> describe how to get the Updates</a> describe how to get the user's location in the form of a
user's current location in the form of a {@link android.location.Location} object that {@link android.location.Location} object that contains latitude and longitude
contains latitude and longitude coordinates. Although latitude and longitude are useful for coordinates. Although latitude and longitude are useful for calculating
calculating distance or displaying a map position, in many cases the address of the location is distance or displaying a map position, in many cases the address of the
more useful. location is more useful. For example, if you want to let your users know where
</p> they are or what is close by, a street address is more meaningful than the
<p> geographic coordinates (latitude/longitude) of the location.</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>Using the {@link android.location.Geocoder} class in the Android framework
</p> location APIs, you can convert an address to the corresponding geographic
<p class="note"> coordinates. This process is called <em>geocoding</em>. Alternatively, you can
<strong>Note:</strong> Address lookup requires a backend service that is not included in the convert a geographic location to an address. The address lookup feature is
core Android framework. If this backend service is not available, also known as <em>reverse geocoding</em>.</p>
{@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()} returns an empty
list. The helper method {@link android.location.Geocoder#isPresent isPresent()}, available <p>This lesson shows you how to use the
in API level 9 and later, checks to see if the backend service is available. {@link android.location.Geocoder#getFromLocation getFromLocation()} method to
</p> convert a geographic location to an address. The method returns an estimated
<p> street address corresponding to a given latitude and longitude.</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 <h2 id="connect">Get a Geographic Location</h2>
variable {@code mLocation}.
</p> <p>The last known location of the device is a useful starting point for the
<!-- address lookup feature. The lesson on
Define the address lookup task <a href="retrieve-current.html">Getting the Last Known Location</a> shows you
--> how to use the
<h2 id="DefineTask">Define the Address Lookup Task</h2> <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>
<p> method provided by the
To get an address for a given latitude and longitude, call <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
{@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a location provider</a> to find the latest location of the device.</p>
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 <p>To access the fused location provider, you need to create an instance of the
doInBackground()} method of an {@link android.os.AsyncTask}. Google Play services API client. To learn how to connect your client, see
</p> <a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
<p> to Google Play Services</a>.</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 <p>In order for the fused location provider to retrieve a precise street
to {@code android:visibility="gone"}, to make it invisible and remove it from the layout address, set the location permission in your app manifest to
hierarchy. When you start the address lookup, you set its visibility to "visible". {@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
</p>
<p>
The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to
your layout file:
</p>
<pre> <pre>
&lt;ProgressBar &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:id="&#64;+id/address_progress" package="com.google.android.gms.location.sample.locationupdates" &gt;
android:layout_width="wrap_content"
android:layout_height="wrap_content" &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
android:layout_centerHorizontal="true" &lt;/manifest&gt;
android:indeterminate="true"
android:visibility="gone" /&gt;
</pre> </pre>
<p>
To create the background task, define a subclass of {@link android.os.AsyncTask} that calls <h2 id="fetch-address">Define an Intent Service to Fetch the Address</h2>
{@link android.location.Geocoder#getFromLocation getFromLocation()} and returns an address.
Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned <p>The {@link android.location.Geocoder#getFromLocation getFromLocation()}
address, and a {@link android.widget.ProgressBar} object that allows you to control the method provided by the {@link android.location.Geocoder} class accepts a
indeterminate activity indicator. For example: latitude and longitude, and returns a list of addresses. The method is
</p> synchronous, and may take a long time to do its work, so you should not call
it from the main, user interface (UI) thread of your app.</p>
<p>The {@link android.app.IntentService IntentService} class provides a
structure for running a task on a background thread. Using this class, you can
handle a long-running operation without affecting your UI's responsiveness.
Note that the {@link android.os.AsyncTask AsyncTask} class also allows you to
perform background operations, but it's designed for short operations. An
{@link android.os.AsyncTask AsyncTask} shouldn't keep a reference to the UI if
the activity is recreated, for example when the device is rotated. In
contrast, an {@link android.app.IntentService IntentService} doesn't need to
be cancelled when the activity is rebuilt.</p>
<p>Define a {@code FetchAddressIntentService} class that extends
{@link android.app.IntentService}. This class is your address lookup service.
The intent service handles an intent asynchronously on a worker thread, and
stops itself when it runs out of work. The intent extras provide the data
needed by the service, including a {@link android.location.Location} object
for conversion to an address, and a {@link android.os.ResultReceiver} object
to handle the results of the address lookup. The service uses a {@link
android.location.Geocoder} to fetch the address for the location, and sends
the results to the {@link android.os.ResultReceiver}.</p>
<h3>Define the Intent Service in your App Manifest</h3>
<p>Add an entry to your app manifest defining the intent service:</p>
<pre> <pre>
public class MainActivity extends FragmentActivity { &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.gms.location.sample.locationaddress" &gt;
&lt;application
... ...
private TextView mAddress; &lt;service
private ProgressBar mActivityIndicator; android:name=".FetchAddressIntentService"
android:exported="false"/&gt;
&lt;/application&gt;
... ...
&lt;/manifest&gt;
</pre>
<p class="note"><strong>Note:</strong> The {@code &lt;service&gt;} element in
the manifest doesn't need to include an intent filter, because your main
activity creates an explicit intent by specifying the name of the class to use
for the intent.</p>
<h3>Create a Geocoder</h3>
<p>The process of converting a geographic location to an address is called
<em>reverse geocoding</em>. To perform the main work of the intent service,
that is, your reverse geocoding request, implement
{@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
{@code FetchAddressIntentService} class. Create a
{@link android.location.Geocoder} object to handle the reverse geocoding.</p>
<p>A locale represents a specific geographical or linguistic region. Locale
objects are used to adjust the presentation of information, such as numbers or
dates, to suit the conventions in the region represented by the locale. Pass a
<a href="{@docRoot}reference/java/util/Locale.html">{@code Locale}</a> object
to the {@link android.location.Geocoder} object, to ensure that the resulting
address is localized to the user's geographic region.</p>
<pre>
&#64;Override &#64;Override
protected void onCreate(Bundle savedInstanceState) { protected void onHandleIntent(Intent intent) {
super.onCreate(savedInstanceState); Geocoder geocoder = new Geocoder(this, Locale.getDefault());
... ...
mAddress = (TextView) findViewById(R.id.address);
mActivityIndicator =
(ProgressBar) findViewById(R.id.address_progress);
} }
... </pre>
/**
* A subclass of AsyncTask that calls getFromLocation() in the <h3 id="retrieve-street-address">Retrieve the street address data</h3>
* background. The class definition has these generic types:
* Location - A {@link android.location.Location} object containing <p>The next step is to retrieve the street address from the geocoder, handle
* the current location. any errors that may occur, and send the results back to the activity that
* Void - indicates that progress units are not used requested the address. To report the results of the geocoding
* String - An address passed to onPostExecute() process, you need two numeric constants that indicate success or failure.
*/ Define a {@code Constants} class to contain the values, as shown in this code
private class GetAddressTask extends snippet:</p>
AsyncTask&lt;Location, Void, String&gt; {
Context mContext; <pre>
public GetAddressTask(Context context) { public final class Constants {
super(); public static final int SUCCESS_RESULT = 0;
mContext = context; public static final int FAILURE_RESULT = 1;
public static final String PACKAGE_NAME =
"com.google.android.gms.location.sample.locationaddress";
public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
public static final String RESULT_DATA_KEY = PACKAGE_NAME +
".RESULT_DATA_KEY";
public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME +
".LOCATION_DATA_EXTRA";
} }
... </pre>
/**
* Get a Geocoder instance, get the latitude and longitude <p>To get a street address corresponding to a geographical location, call
* look up the address, and return it {@link android.location.Geocoder#getFromLocation getFromLocation()},
* passing it the latitude and longitude from the location object, and the
* &#64;params params One or more Location objects maximum number of addresses you want returned. In this case, you want just one
* &#64;return A string containing the address of the current address. The geocoder returns an array of addresses. If no addresses were
* location, or an empty string if no address can be found, found to match the given location, it returns an empty list. If there is no
* or an error message backend geocoding service available, the geocoder returns null.</p>
*/
<p>Check for the following errors as shown in the code sample below. If an error
occurs, place the corresponding error message in the {@code errorMessage}
variable, so you can send it back to the requesting activity:</p>
<ul>
<li><strong>No location data provided</strong> - The intent extras do not
include the {@link android.location.Location} object required for reverse
geocoding.</li>
<li><strong>Invalid latitude or longitude used</strong> - The latitude
and/or longitude values provided in the {@link android.location.Location}
object are invalid.</li>
<li><strong>No geocoder available</strong> - The background geocoding service
is not available, due to a network error or IO exception.</li>
<li><strong>Sorry, no address found</strong> - The geocoder could not find an
address for the given latitude/longitude.</li>
</ul>
<p>To get the individual lines of an address object, use the
{@link android.location.Address#getAddressLine getAddressLine()}
method provided by the {@link android.location.Address} class. Then join the
lines into a list of address fragments ready to return to the activity that
requested the address.</p>
<p>To send the results back to the requesting activity, call the
{@code deliverResultToReceiver()} method (defined in
<a href="#return-address">Return the address to the requestor</a>). The
results consist of the previously-mentioned numeric success/failure code and
a string. In the case of a successful reverse geocoding, the string contains
the address. In the case of a failure, the string contains the error message,
as shown in the code sample below:</p>
<pre>
&#64;Override &#64;Override
protected String doInBackground(Location... params) { protected void onHandleIntent(Intent intent) {
Geocoder geocoder = String errorMessage = "";
new Geocoder(mContext, Locale.getDefault());
// Get the current location from the input parameter list // Get the location passed to this service through an extra.
Location loc = params[0]; Location location = intent.getParcelableExtra(
// Create a list to contain the result address Constants.LOCATION_DATA_EXTRA);
...
List&lt;Address&gt; addresses = null; List&lt;Address&gt; addresses = null;
try { try {
/* addresses = geocoder.getFromLocation(
* Return 1 address. location.getLatitude(),
*/ location.getLongitude(),
addresses = geocoder.getFromLocation(loc.getLatitude(), // In this sample, get just a single address.
loc.getLongitude(), 1); 1);
} catch (IOException e1) { } catch (IOException ioException) {
Log.e("LocationSampleActivity", // Catch network or other I/O problems.
"IO Exception in getFromLocation()"); errorMessage = getString(R.string.service_not_available);
e1.printStackTrace(); Log.e(TAG, errorMessage, ioException);
return ("IO Exception trying to get address"); } catch (IllegalArgumentException illegalArgumentException) {
} catch (IllegalArgumentException e2) { // Catch invalid latitude or longitude values.
// Error message to post in the log errorMessage = getString(R.string.invalid_lat_long_used);
String errorString = "Illegal arguments " + Log.e(TAG, errorMessage + ". " +
Double.toString(loc.getLatitude()) + "Latitude = " + location.getLatitude() +
" , " + ", Longitude = " +
Double.toString(loc.getLongitude()) + location.getLongitude(), illegalArgumentException);
" passed to address service";
Log.e("LocationSampleActivity", errorString);
e2.printStackTrace();
return errorString;
} }
// If the reverse geocode returned an address
if (addresses != null &amp;&amp; addresses.size() &gt; 0) { // Handle case where no address was found.
// Get the first address if (addresses == null || addresses.size() == 0) {
Address address = addresses.get(0); if (errorMessage.isEmpty()) {
/* errorMessage = getString(R.string.no_address_found);
* Format the first line of address (if available), Log.e(TAG, errorMessage);
* city, and country name. }
*/ deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
String addressText = String.format(
"&#037;s, &#037;s, &#037;s",
// If there's a street address, add it
address.getMaxAddressLineIndex() &gt; 0 ?
address.getAddressLine(0) : "",
// Locality is usually a city
address.getLocality(),
// The country of the address
address.getCountryName());
// Return the text
return addressText;
} else { } else {
return "No address found"; Address address = addresses.get(0);
ArrayList&lt;String&gt; addressFragments = new ArrayList&lt;String&gt;();
// Fetch the address lines using {@code getAddressLine},
// join them, and send them to the thread.
for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
addressFragments.add(address.getAddressLine(i));
} }
Log.i(TAG, getString(R.string.address_found));
deliverResultToReceiver(Constants.SUCCESS_RESULT,
TextUtils.join(System.getProperty("line.separator"),
addressFragments));
} }
...
}
...
} }
</pre> </pre>
<p>
The next section shows you how to display the address in the user interface. <h3 id="return-address">Return the address to the requestor</h3>
</p>
<!-- Define a method to display the address --> <p>The final thing the intent service must do is send the address back to a
<h2 id="DisplayResults">Define a Method to Display the Results</h2> {@link android.os.ResultReceiver} in the activity that started the service.
<p> The {@link android.os.ResultReceiver} class allows you to send a
{@link android.os.AsyncTask#doInBackground doInBackground()} returns the result of the address numeric result code as well as a message containing the result data. The
lookup as a {@link java.lang.String}. This value is passed to numeric code is useful for reporting the success or failure of the geocoding
{@link android.os.AsyncTask#onPostExecute onPostExecute()}, where you do further processing request. In the case of a successful reverse geocoding, the message contains
on the results. Since {@link android.os.AsyncTask#onPostExecute onPostExecute()} the address. In the case of a failure, the message contains some text
runs on the UI thread, it can update the user interface; for example, it can turn off the describing the reason for failure.</p>
activity indicator and display the results to the user:
<p>You have already retrieved the address from the geocoder, trapped any errors
that may occur, and called the {@code deliverResultToReceiver()} method. Now
you need to define the {@code deliverResultToReceiver()} method that sends
a result code and message bundle to the result receiver.</p>
<p>For the result code, use the value that you've passed to the
{@code deliverResultToReceiver()} method in the {@code resultCode} parameter.
To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
constant from your {@code Constants} class (defined in
<a href="#retrieve-street-address">Retrieve the street address data</a>) and
the value in the {@code message} parameter passed to the
{@code deliverResultToReceiver()} method, as shown in the following sample:
</p> </p>
<pre> <pre>
private class GetAddressTask extends public class FetchAddressIntentService extends IntentService {
AsyncTask&lt;Location, Void, String&gt; { protected ResultReceiver mReceiver;
...
private void deliverResultToReceiver(int resultCode, String message) {
Bundle bundle = new Bundle();
bundle.putString(Constants.RESULT_DATA_KEY, message);
mReceiver.send(resultCode, bundle);
}
}
</pre>
<h2 id="start-intent">Start the Intent Service</h2>
<p>The intent service, as defined in the previous section, runs in the
background and is responsible for fetching the address corresponding to a
given geographic location. When you start the service, the Android framework
instantiates and starts the service if it isn't already running, and creates a
process if needed. If the service is already running then it remains running.
Because the service extends {@link android.app.IntentService IntentService},
it shuts down automatically when all intents have been processed.</p>
<p>Start the service from your app's main activity,
and create an {@link android.content.Intent} to pass data to the service. You
need an <em>explicit</em> intent, because you want only your service
to respond to the intent. For more information, see
<a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
Types</a>.</p>
<p>To create an explicit intent, specify the name of the
class to use for the service: {@code FetchAddressIntentService.class}.
Pass two pieces of information in the intent extras:</p>
<ul>
<li>A {@link android.os.ResultReceiver} to handle the results of the address
lookup.</li>
<li>A {@link android.location.Location} object containing the latitude and
longitude that you want to convert to an address.</li>
</ul>
<p>The following code sample shows you how to start the intent service:</p>
<pre>
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
protected Location mLastLocation;
private AddressResultReceiver mResultReceiver;
...
protected void startIntentService() {
Intent intent = new Intent(this, FetchAddressIntentService.class);
intent.putExtra(Constants.RECEIVER, mResultReceiver);
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
startService(intent);
}
}
</pre>
<p>Call the above {@code startIntentService()} method when the
user takes an action that requires a geocoding address lookup. For example,
the user may press a <em>Fetch address</em> button on your app's UI. Before
starting the intent service, you need to check that the connection to Google
Play services is present. The following code snippet shows the call to the
{@code startIntentService()} method in the button handler:</p>
<pre>
public void fetchAddressButtonHandler(View view) {
// Only start the service to fetch the address if GoogleApiClient is
// connected.
if (mGoogleApiClient.isConnected() && mLastLocation != null) {
startIntentService();
}
// If GoogleApiClient isn't connected, process the user's request by
// setting mAddressRequested to true. Later, when GoogleApiClient connects,
// launch the service to fetch the address. As far as the user is
// concerned, pressing the Fetch Address button
// immediately kicks off the process of getting the address.
mAddressRequested = true;
updateUIWidgets();
}
</pre>
<p>You must also start the intent service when the connection to Google Play
services is established, if the user has already clicked the button on your
app's UI. The following code snippet shows the call to the
{@code startIntentService()} method in the
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
callback provided by the Google API Client:</p>
<pre>
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
... ...
/**
* 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.
*/
&#64;Override &#64;Override
protected void onPostExecute(String address) { public void onConnected(Bundle connectionHint) {
// Set activity indicator visibility to "gone" // Gets the best and most recent location currently available,
mActivityIndicator.setVisibility(View.GONE); // which may be null in rare cases when a location is not available.
// Display the results of the lookup. mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mAddress.setText(address); mGoogleApiClient);
if (mLastLocation != null) {
// Determine whether a Geocoder is available.
if (!Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available,
Toast.LENGTH_LONG).show();
return;
}
if (mAddressRequested) {
startIntentService();
}
}
} }
...
} }
</pre> </pre>
<p>
The final step is to run the address lookup. <h2 id="result-receiver">Receive the Geocoding Results</h2>
</p>
<!-- Get and display the address --> <p>The intent service has handled the geocoding request, and uses a
<h2 id="RunTask">Run the Lookup Task</h2> {@link android.os.ResultReceiver} to return the results to the activity that
<p> made the request. In the activity that makes the request, define an
To get the address, call {@link android.os.AsyncTask#execute execute()}. For example, the {@code AddressResultReceiver} that extends {@link android.os.ResultReceiver}
following snippet starts the address lookup when the user clicks the "Get Address" button: to handle the response from {@code FetchAddressIntentService}.</p>
</p>
<p>The result includes a numeric result code (<code>resultCode</code>) as well
as a message containing the result data (<code>resultData</code>). If the
reverse geocoding process was successful, the <code>resultData</code> contains
the address. In the case of a failure, the <code>resultData</code> contains
text describing the reason for failure. For details of the possible errors,
see <a href="#return-address">Return the address to the requestor</a>.</p>
<p>Override the
{@link android.os.ResultReceiver#onReceiveResult onReceiveResult()} method
to handle the results delivered to the result receiver, as shown in the
following code sample:</p>
<pre> <pre>
public class MainActivity extends FragmentActivity { public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
... ...
/** class AddressResultReceiver extends ResultReceiver {
* The "Get Address" button in the UI is defined with public AddressResultReceiver(Handler handler) {
* android:onClick="getAddress". The method is invoked whenever the super(handler);
* user clicks the button. }
*
* &#64;param v The view object associated with this method, &#64;Override
* in this case a Button. protected void onReceiveResult(int resultCode, Bundle resultData) {
*/
public void getAddress(View v) { // Display the address string
// Ensure that a Geocoder services is available // or an error message sent from the intent service.
if (Build.VERSION.SDK_INT &gt;= mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
Build.VERSION_CODES.GINGERBREAD displayAddressOutput();
&amp;&amp;
Geocoder.isPresent()) { // Show a toast message if an address was found.
// Show the activity indicator if (resultCode == Constants.SUCCESS_RESULT) {
mActivityIndicator.setVisibility(View.VISIBLE); showToast(getString(R.string.address_found));
/* }
* 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> </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>