Home | History | Annotate | Download | only in location
      1 page.title=Displaying a Location Address
      2 
      3 trainingnavtop=true
      4 
      5 @jd:body
      6 
      7 
      8 
      9 <div id="tb-wrapper">
     10 <div id="tb">
     11 
     12 <h2>This lesson teaches you to</h2>
     13 <ol>
     14   <li><a href="#DefineTask">Define the Address Lookup Task</a></li>
     15   <li><a href="#DisplayResults">Define a Method to Display the Results</a></li>
     16   <li><a href="#RunTask">Run the Lookup Task</a></li>
     17 </ol>
     18 
     19 <h2>You should also read</h2>
     20 <ul>
     21     <li>
     22         <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>
     23     </li>
     24     <li>
     25         <a href="retrieve-current.html">Retrieving the Current Location</a>
     26     </li>
     27     <li>
     28         <a href="receive-location-updates.html">Receiving Location Updates</a>
     29     </li>
     30 </ul>
     31 <h2>Try it out</h2>
     32 
     33 <div class="download-box">
     34 <a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download
     35   the sample app</a>
     36 <p class="filename">LocationUpdates.zip</p>
     37 </div>
     38 
     39 </div>
     40 </div>
     41 
     42 <p>
     43     The lessons <a href="retrieve-current.html">Retrieving the Current Location</a> and
     44     <a href="receive-location-updates.html">Receiving Location Updates</a> describe how to get the
     45     user's current location in the form of a {@link android.location.Location} object that
     46     contains latitude and longitude coordinates. Although latitude and longitude are useful for
     47     calculating distance or displaying a map position, in many cases the address of the location is
     48     more useful.
     49 </p>
     50 <p>
     51     The Android platform API provides a feature that returns an estimated street addresses for
     52     latitude and longitude values. This lesson shows you how to use this address lookup feature.
     53 </p>
     54 <p class="note">
     55     <strong>Note:</strong> Address lookup requires a backend service that is not included in the
     56     core Android framework. If this backend service is not available,
     57     {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()} returns an empty
     58     list. The helper method {@link android.location.Geocoder#isPresent isPresent()}, available
     59     in API level 9 and later, checks to see if the backend service is available.
     60 </p>
     61 <p>
     62     The snippets in the following sections assume that your app has already retrieved the
     63     current location and stored it as a {@link android.location.Location} object in the global
     64     variable {@code mLocation}.
     65 </p>
     66 <!--
     67     Define the address lookup task
     68 -->
     69 <h2 id="DefineTask">Define the Address Lookup Task</h2>
     70 <p>
     71 To get an address for a given latitude and longitude, call
     72 {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a
     73 list of addresses. The method is synchronous, and may take a long time to do its work, so you
     74 should call the method from the {@link android.os.AsyncTask#doInBackground
     75 doInBackground()} method of an {@link android.os.AsyncTask}.
     76 </p>
     77 <p>
     78 While your app is getting the address, display an indeterminate activity
     79 indicator to show that your app is working in the background. Set the indicator's initial state
     80 to {@code android:visibility="gone"}, to make it invisible and remove it from the layout
     81 hierarchy. When you start the address lookup, you set its visibility to "visible".
     82 </p>
     83 <p>
     84 The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to
     85 your layout file:
     86 </p>
     87 <pre>
     88 &lt;ProgressBar
     89 android:id="&#64;+id/address_progress"
     90 android:layout_width="wrap_content"
     91 android:layout_height="wrap_content"
     92 android:layout_centerHorizontal="true"
     93 android:indeterminate="true"
     94 android:visibility="gone" /&gt;
     95 </pre>
     96 <p>
     97 To create the background task, define a subclass of {@link android.os.AsyncTask} that calls
     98 {@link android.location.Geocoder#getFromLocation getFromLocation()} and returns an address.
     99 Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned
    100 address, and a {@link android.widget.ProgressBar} object that allows you to control the
    101 indeterminate activity indicator. For example:
    102 </p>
    103 <pre>
    104 public class MainActivity extends FragmentActivity {
    105     ...
    106     private TextView mAddress;
    107     private ProgressBar mActivityIndicator;
    108     ...
    109     &#64;Override
    110     protected void onCreate(Bundle savedInstanceState) {
    111     super.onCreate(savedInstanceState);
    112     ...
    113     mAddress = (TextView) findViewById(R.id.address);
    114     mActivityIndicator =
    115             (ProgressBar) findViewById(R.id.address_progress);
    116     }
    117     ...
    118     /**
    119     * A subclass of AsyncTask that calls getFromLocation() in the
    120     * background. The class definition has these generic types:
    121     * Location - A {@link android.location.Location} object containing
    122     * the current location.
    123     * Void     - indicates that progress units are not used
    124     * String   - An address passed to onPostExecute()
    125     */
    126     private class GetAddressTask extends
    127             AsyncTask&lt;Location, Void, String&gt; {
    128         Context mContext;
    129         public GetAddressTask(Context context) {
    130             super();
    131             mContext = context;
    132         }
    133         ...
    134         /**
    135          * Get a Geocoder instance, get the latitude and longitude
    136          * look up the address, and return it
    137          *
    138          * &#64;params params One or more Location objects
    139          * &#64;return A string containing the address of the current
    140          * location, or an empty string if no address can be found,
    141          * or an error message
    142          */
    143         &#64;Override
    144         protected String doInBackground(Location... params) {
    145             Geocoder geocoder =
    146                     new Geocoder(mContext, Locale.getDefault());
    147             // Get the current location from the input parameter list
    148             Location loc = params[0];
    149             // Create a list to contain the result address
    150             List&lt;Address&gt; addresses = null;
    151             try {
    152                 /*
    153                  * Return 1 address.
    154                  */
    155                 addresses = geocoder.getFromLocation(loc.getLatitude(),
    156                         loc.getLongitude(), 1);
    157             } catch (IOException e1) {
    158             Log.e("LocationSampleActivity",
    159                     "IO Exception in getFromLocation()");
    160             e1.printStackTrace();
    161             return ("IO Exception trying to get address");
    162             } catch (IllegalArgumentException e2) {
    163             // Error message to post in the log
    164             String errorString = "Illegal arguments " +
    165                     Double.toString(loc.getLatitude()) +
    166                     " , " +
    167                     Double.toString(loc.getLongitude()) +
    168                     " passed to address service";
    169             Log.e("LocationSampleActivity", errorString);
    170             e2.printStackTrace();
    171             return errorString;
    172             }
    173             // If the reverse geocode returned an address
    174             if (addresses != null &amp;&amp; addresses.size() &gt; 0) {
    175                 // Get the first address
    176                 Address address = addresses.get(0);
    177                 /*
    178                  * Format the first line of address (if available),
    179                  * city, and country name.
    180                  */
    181                 String addressText = String.format(
    182                         "&#037;s, &#037;s, &#037;s",
    183                         // If there's a street address, add it
    184                         address.getMaxAddressLineIndex() &gt; 0 ?
    185                                 address.getAddressLine(0) : "",
    186                         // Locality is usually a city
    187                         address.getLocality(),
    188                         // The country of the address
    189                         address.getCountryName());
    190                 // Return the text
    191                 return addressText;
    192             } else {
    193                 return "No address found";
    194             }
    195         }
    196         ...
    197     }
    198     ...
    199 }
    200 </pre>
    201 <p>
    202 The next section shows you how to display the address in the user interface.
    203 </p>
    204 <!-- Define a method to display the address -->
    205 <h2 id="DisplayResults">Define a Method to Display the Results</h2>
    206 <p>
    207     {@link android.os.AsyncTask#doInBackground doInBackground()} returns the result of the address
    208     lookup as a {@link java.lang.String}. This value is passed to
    209     {@link android.os.AsyncTask#onPostExecute onPostExecute()}, where you do further processing
    210     on the results. Since {@link android.os.AsyncTask#onPostExecute onPostExecute()}
    211     runs on the UI thread, it can update the user interface; for example, it can turn off the
    212     activity indicator and display the results to the user:
    213 </p>
    214 <pre>
    215     private class GetAddressTask extends
    216             AsyncTask&lt;Location, Void, String&gt; {
    217         ...
    218         /**
    219          * A method that's called once doInBackground() completes. Turn
    220          * off the indeterminate activity indicator and set
    221          * the text of the UI element that shows the address. If the
    222          * lookup failed, display the error message.
    223          */
    224         &#64;Override
    225         protected void onPostExecute(String address) {
    226             // Set activity indicator visibility to "gone"
    227             mActivityIndicator.setVisibility(View.GONE);
    228             // Display the results of the lookup.
    229             mAddress.setText(address);
    230         }
    231         ...
    232     }
    233 </pre>
    234 <p>
    235     The final step is to run the address lookup.
    236 </p>
    237 <!-- Get and display the address -->
    238 <h2 id="RunTask">Run the Lookup Task</h2>
    239 <p>
    240     To get the address, call {@link android.os.AsyncTask#execute execute()}. For example, the
    241     following snippet starts the address lookup when the user clicks the "Get Address" button:
    242 </p>
    243 <pre>
    244 public class MainActivity extends FragmentActivity {
    245     ...
    246     /**
    247      * The "Get Address" button in the UI is defined with
    248      * android:onClick="getAddress". The method is invoked whenever the
    249      * user clicks the button.
    250      *
    251      * &#64;param v The view object associated with this method,
    252      * in this case a Button.
    253      */
    254     public void getAddress(View v) {
    255         // Ensure that a Geocoder services is available
    256         if (Build.VERSION.SDK_INT &gt;=
    257                 Build.VERSION_CODES.GINGERBREAD
    258                             &amp;&amp;
    259                 Geocoder.isPresent()) {
    260             // Show the activity indicator
    261             mActivityIndicator.setVisibility(View.VISIBLE);
    262             /*
    263              * Reverse geocoding is long-running and synchronous.
    264              * Run it on a background thread.
    265              * Pass the current location to the background task.
    266              * When the task finishes,
    267              * onPostExecute() displays the address.
    268              */
    269             (new GetAddressTask(this)).execute(mLocation);
    270         }
    271         ...
    272     }
    273     ...
    274 }
    275 </pre>
    276 <p>
    277     The next lesson, <a href="geofencing.html">Creating and Monitoring Geofences</a>, demonstrates
    278     how to define locations of interest called <b>geofences</b> and how to use geofence monitoring
    279     to detect the user's proximity to a location of interest.
    280 </p>
    281