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 <ProgressBar 89 android:id="@+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" /> 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 @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> 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<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> 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 * @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