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<ProgressBar 89android:id="@+id/address_progress" 90android:layout_width="wrap_content" 91android:layout_height="wrap_content" 92android:layout_centerHorizontal="true" 93android:indeterminate="true" 94android:visibility="gone" /> 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 @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<Location, Void, String> { 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 * @params params One or more Location objects 139 * @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 @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<Address> 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 && addresses.size() > 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 "%s, %s, %s", 183 // If there's a street address, add it 184 address.getMaxAddressLineIndex() > 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<Location, Void, String> { 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 @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 * @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 >= 257 Build.VERSION_CODES.GINGERBREAD 258 && 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