• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Displaying a Location Address
2
3trainingnavtop=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>
71To get an address for a given latitude and longitude, call
72{@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a
73list of addresses. The method is synchronous, and may take a long time to do its work, so you
74should call the method from the {@link android.os.AsyncTask#doInBackground
75doInBackground()} method of an {@link android.os.AsyncTask}.
76</p>
77<p>
78While your app is getting the address, display an indeterminate activity
79indicator to show that your app is working in the background. Set the indicator's initial state
80to {@code android:visibility="gone"}, to make it invisible and remove it from the layout
81hierarchy. When you start the address lookup, you set its visibility to "visible".
82</p>
83<p>
84The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to
85your layout file:
86</p>
87<pre>
88&lt;ProgressBar
89android:id="&#64;+id/address_progress"
90android:layout_width="wrap_content"
91android:layout_height="wrap_content"
92android:layout_centerHorizontal="true"
93android:indeterminate="true"
94android:visibility="gone" /&gt;
95</pre>
96<p>
97To 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.
99Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned
100address, and a {@link android.widget.ProgressBar} object that allows you to control the
101indeterminate activity indicator. For example:
102</p>
103<pre>
104public 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>
202The 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>
244public 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