1page.title=Receiving Location Updates 2trainingnavtop=true 3@jd:body 4 5<div id="tb-wrapper"> 6 <div id="tb"> 7 8 <h2>This lesson teaches you how to</h2> 9 <ol> 10 <li><a href="#connect">Connect to Location Services</a></li> 11 <li><a href="#location-request">Set Up a Location Request</a></li> 12 <li><a href="#updates">Request Location Updates</a></li> 13 <li><a href="#callback">Define the Location Update Callback</a></li> 14 <li><a href="#stop-updates">Stop Location Updates</a></li> 15 <li><a href="#save-state">Save the State of the Activity</a></li> 16 </ol> 17 18 <h2>You should also read</h2> 19 <ul> 20 <li> 21 <a href="{@docRoot}google/play-services/setup.html">Setting up Google Play 22 Services</a> 23 </li> 24 <li> 25 <a href="retrieve-current.html">Getting the Last Known Location</a> 26 </li> 27 </ul> 28 29 <h2>Try it out</h2> 30 31 <ul> 32 <li> 33 <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates" class="external-link">LocationUpdates</a> 34 </li> 35 </ul> 36 </div> 37</div> 38 39<p>If your app can continuously track location, it can deliver more relevant 40 information to the user. For example, if your app helps the user find their 41 way while walking or driving, or if your app tracks the location of assets, it 42 needs to get the location of the device at regular intervals. As well as the 43 geographical location (latitude and longitude), you may want to give the user 44 further information such as the bearing (horizontal direction of travel), 45 altitude, or velocity of the device. This information, and more, is available 46 in the {@link android.location.Location} object that your app can retrieve 47 from the 48 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused 49 location provider</a>.</p> 50 51<p>While you can get a device's location with 52 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>, 53 as illustrated in the lesson on 54 <a href="retrieve-current.html">Getting the Last Known Location</a>, 55 a more direct approach is to request periodic updates from the fused location 56 provider. In response, the API updates your app periodically with the best 57 available location, based on the currently-available location providers such 58 as WiFi and GPS (Global Positioning System). The accuracy of the location is 59 determined by the providers, the location permissions you've requested, and 60 the options you set in the location request.</p> 61 62<p>This lesson shows you how to request regular updates about a device's 63 location using the 64 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">{@code requestLocationUpdates()}</a> 65 method in the fused location provider. 66 67<h2 id="connect">Connect to Location Services</h2> 68 69<p>Location services for apps are provided through Google Play services and the 70 fused location provider. In order to use these services, you connect your app 71 using the Google API Client and then request location updates. For details on 72 connecting with the 73 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>, 74 follow the instructions in 75 <a href="retrieve-current.html">Getting the Last Known Location</a>, including 76 requesting the current location.</p> 77 78<p>The last known location of the device provides a handy base from which to 79 start, ensuring that the app has a known location before starting the 80 periodic location updates. The lesson on 81 <a href="retrieve-current.html">Getting the Last Known Location</a> shows you 82 how to get the last known location by calling 83 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>. 84 The snippets in the following sections assume that your app has already 85 retrieved the last known location and stored it as a 86 {@link android.location.Location} object in the global variable 87 {@code mCurrentLocation}.</p> 88 89<p>Apps that use location services must request location permissions. In this 90 lesson you require fine location detection, so that your app can get as 91 precise a location as possible from the available location providers. Request 92 this permission with the 93 {@code uses-permission} element in your app manifest, as shown in the 94 following example:</p> 95 96<pre> 97<manifest xmlns:android="http://schemas.android.com/apk/res/android" 98 package="com.google.android.gms.location.sample.locationupdates" > 99 100 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 101</manifest> 102</pre> 103 104<h2 id="location-request">Set Up a Location Request</h2> 105 106<p>To store parameters for requests to the fused location provider, create a 107 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a>. 108 The parameters determine the levels of accuracy requested. For details of all 109 the options available in the location request, see the 110 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a> 111 class reference. This lesson sets the update interval, fastest update 112 interval, and priority, as described below:</p> 113 114<dl> 115 <dt> 116 Update interval 117 </dt> 118 <dd> 119 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">{@code setInterval()}</a> 120 - This method sets the rate in milliseconds at which your app prefers to 121 receive location updates. Note that the location updates may be faster than 122 this rate if another app is receiving updates at a faster rate, or slower 123 than this rate, or there may be no updates at all (if the device has no 124 connectivity, for example). 125 </dd> 126 <dt> 127 Fastest update interval 128 </dt> 129 <dd> 130 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">{@code setFastestInterval()}</a> 131 - This method sets the <strong>fastest</strong> rate in milliseconds at which 132 your app can handle location updates. You need to set this rate because 133 other apps also affect the rate at which updates are sent. The Google Play 134 services location APIs send out updates at the fastest rate that any app 135 has requested with 136 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">{@code setInterval()}</a>. 137 If this rate is faster 138 than your app can handle, you may encounter problems with UI flicker or data 139 overflow. To prevent this, call 140 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">{@code setFastestInterval()}</a> 141 to set an upper limit to the update rate. 142 </dd> 143 <dt>Priority</dt> 144 <dd> 145 <p> 146 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setPriority(int)">{@code setPriority()}</a> 147 - This method sets the priority of the request, which gives the Google Play 148 services location services a strong hint about which location sources to use. 149 The following values are supported:</p> 150 <ul> 151 <li> 152 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_BALANCED_POWER_ACCURACY">{@code PRIORITY_BALANCED_POWER_ACCURACY}</a> 153 - Use this setting to request location precision to within a city 154 block, which is an accuracy of approximately 100 meters. This is 155 considered a coarse level of accuracy, and is likely to consume less 156 power. With this setting, the location services are likely to use WiFi 157 and cell tower positioning. Note, however, that the choice of location 158 provider depends on many other factors, such as which sources are 159 available.</li> 160 <li> 161 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_HIGH_ACCURACY">{@code PRIORITY_HIGH_ACCURACY}</a> 162 - Use this setting to request the most precise location possible. With 163 this setting, the location services are more likely to use GPS 164 (Global Positioning System) to determine the location.</li> 165 <li><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_LOW_POWER">{@code PRIORITY_LOW_POWER}</a> 166 - Use this setting to request city-level precision, which is 167 an accuracy of approximately 10 kilometers. This is considered a 168 coarse level of accuracy, and is likely to consume less power.</li> 169 <li><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_NO_POWER">{@code PRIORITY_NO_POWER}</a> 170 - Use this setting if you need negligible impact on power consumption, 171 but want to receive location updates when available. With this 172 setting, your app does not trigger any location updates, but 173 receives locations triggered by other apps.</li> 174 </ul> 175 </dd> 176</dl> 177 178<p>Create the location request and set the parameters as shown in this 179 code sample:</p> 180 181<pre> 182protected void createLocationRequest() { 183 LocationRequest mLocationRequest = new LocationRequest(); 184 mLocationRequest.setInterval(10000); 185 mLocationRequest.setFastestInterval(5000); 186 mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 187} 188</pre> 189 190<p>The priority of 191 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_HIGH_ACCURACY">{@code PRIORITY_HIGH_ACCURACY}</a>, 192 combined with the 193 {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 194 permission setting that you've defined in the app manifest, and a fast update 195 interval of 5000 milliseconds (5 seconds), causes the fused location 196 provider to return location updates that are accurate to within a few feet. 197 This approach is appropriate for mapping apps that display the location in 198 real time.</p> 199 200<p class="note"><strong>Performance hint:</strong> If your app accesses the 201 network or does other long-running work after receiving a location update, 202 adjust the fastest interval to a slower value. This adjustment prevents your 203 app from receiving updates it can't use. Once the long-running work is done, 204 set the fastest interval back to a fast value.</p> 205 206<h2 id="updates">Request Location Updates</h2> 207 208<p>Now that you've set up a location request containing your app's requirements 209 for the location updates, you can start the regular updates by calling 210 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">{@code requestLocationUpdates()}</a>. 211 Do this in the 212 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a> 213 callback provided by Google API Client, which is called when the client is 214 ready.</p> 215 216<p>Depending on the form of the request, the fused location provider either 217 invokes the 218 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener.onLocationChanged()}</a> 219 callback method and passes it a {@link android.location.Location} object, or 220 issues a 221 <a href="{@docRoot}reference/android/app/PendingIntent.html">{@code PendingIntent}</a> 222 that contains the location in its extended data. The accuracy and frequency of 223 the updates are affected by the location permissions you've requested and the 224 options you set in the location request object.</p> 225 226<p>This lesson shows you how to get the update using the 227 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a> 228 callback approach. Call 229 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">{@code requestLocationUpdates()}</a>, 230 passing it your instance of the 231 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>, 232 the 233 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a> 234 object, 235 and a <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>. 236 Define a {@code startLocationUpdates()} method, called from the 237 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a> 238 callback, as shown in the following code sample:</p> 239 240<pre> 241@Override 242public void onConnected(Bundle connectionHint) { 243 ... 244 if (mRequestingLocationUpdates) { 245 startLocationUpdates(); 246 } 247} 248 249protected void startLocationUpdates() { 250 LocationServices.FusedLocationApi.requestLocationUpdates( 251 mGoogleApiClient, mLocationRequest, this); 252} 253</pre> 254 255<p>Notice that the above code snippet refers to a boolean flag, 256 {@code mRequestingLocationUpdates}, used to track whether the user has 257 turned location updates on or off. For more about retaining the value of this 258 flag across instances of the activity, see 259 <a href="#save-state">Save the State of the Activity</a>. 260 261<h2 id="callback">Define the Location Update Callback</h2> 262 263<p>The fused location provider invokes the 264 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html#onLocationChanged(android.location.Location)">{@code LocationListener.onLocationChanged()}</a> 265 callback method. The incoming argument is a {@link android.location.Location} 266 object containing the location's latitude and longitude. The following snippet 267 shows how to implement the 268 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a> 269 interface and define the method, then get the timestamp of the location update 270 and display the latitude, longitude and timestamp on your app's user 271 interface:</p> 272 273<pre> 274public class MainActivity extends ActionBarActivity implements 275 ConnectionCallbacks, OnConnectionFailedListener, LocationListener { 276 ... 277 @Override 278 public void onLocationChanged(Location location) { 279 mCurrentLocation = location; 280 mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); 281 updateUI(); 282 } 283 284 private void updateUI() { 285 mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude())); 286 mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude())); 287 mLastUpdateTimeTextView.setText(mLastUpdateTime); 288 } 289} 290</pre> 291 292<h2 id="stop-updates">Stop Location Updates</h2> 293 294<p>Consider whether you want to stop the location updates when the activity is 295 no longer in focus, such as when the user switches to another app or to a 296 different activity in the same app. This can be handy to reduce power 297 consumption, provided the app doesn't need to collect information even when 298 it's running in the background. This section shows how you can stop the 299 updates in the activity's 300 {@link android.app.Activity#onPause onPause()} method.</p> 301 302<p>To stop location updates, call 303 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#removeLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationListener)">{@code removeLocationUpdates()}</a>, 304 passing it your instance of the 305 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a> 306 object and a 307 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>, 308 as shown in the following code sample:</p> 309 310<pre> 311@Override 312protected void onPause() { 313 super.onPause(); 314 stopLocationUpdates(); 315} 316 317protected void stopLocationUpdates() { 318 LocationServices.FusedLocationApi.removeLocationUpdates( 319 mGoogleApiClient, this); 320} 321</pre> 322 323<p>Use a boolean, {@code mRequestingLocationUpdates}, to track 324 whether location updates are currently turned on. In the activity's 325 {@link android.app.Activity#onResume onResume()} method, check 326 whether location updates are currently active, and activate them if not:</p> 327 328<pre> 329@Override 330public void onResume() { 331 super.onResume(); 332 if (mGoogleApiClient.isConnected() && !mRequestingLocationUpdates) { 333 startLocationUpdates(); 334 } 335} 336</pre> 337 338<h2 id="save-state">Save the State of the Activity</h2> 339 340<p>A change to the device's configuration, such as a change in screen 341 orientation or language, can cause the current activity to be destroyed. Your 342 app must therefore store any information it needs to recreate the activity. 343 One way to do this is via an instance state stored in a 344 {@link android.os.Bundle} object.</p> 345 346<p>The following code sample shows how to use the activity's 347 <a href="{@docRoot}reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)">{@code onSaveInstanceState()}</a> 348 callback to save the instance state:</p> 349 350<pre> 351public void onSaveInstanceState(Bundle savedInstanceState) { 352 savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, 353 mRequestingLocationUpdates); 354 savedInstanceState.putParcelable(LOCATION_KEY, mCurrentLocation); 355 savedInstanceState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime); 356 super.onSaveInstanceState(savedInstanceState); 357} 358</pre> 359 360<p>Define an {@code updateValuesFromBundle()} method to restore 361 the saved values from the previous instance of the activity, if they're 362 available. Call the method from the activity's 363 {@link android.app.Activity#onCreate onCreate()} method, as shown in the 364 following code sample:</p> 365 366<pre> 367@Override 368public void onCreate(Bundle savedInstanceState) { 369 ... 370 updateValuesFromBundle(savedInstanceState); 371} 372 373private void updateValuesFromBundle(Bundle savedInstanceState) { 374 if (savedInstanceState != null) { 375 // Update the value of mRequestingLocationUpdates from the Bundle, and 376 // make sure that the Start Updates and Stop Updates buttons are 377 // correctly enabled or disabled. 378 if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) { 379 mRequestingLocationUpdates = savedInstanceState.getBoolean( 380 REQUESTING_LOCATION_UPDATES_KEY); 381 setButtonsEnabledState(); 382 } 383 384 // Update the value of mCurrentLocation from the Bundle and update the 385 // UI to show the correct latitude and longitude. 386 if (savedInstanceState.keySet().contains(LOCATION_KEY)) { 387 // Since LOCATION_KEY was found in the Bundle, we can be sure that 388 // mCurrentLocationis not null. 389 mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY); 390 } 391 392 // Update the value of mLastUpdateTime from the Bundle and update the UI. 393 if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) { 394 mLastUpdateTime = savedInstanceState.getString( 395 LAST_UPDATED_TIME_STRING_KEY); 396 } 397 updateUI(); 398 } 399} 400</pre> 401 402<p>For more about saving instance state, see the 403 <a href="{@docRoot}reference/android/app/Activity.html#ConfigurationChanges">Android 404 Activity</a> class reference.</p> 405 406<p class="note"><strong>Note:</strong> For a more persistent storage, you can 407 store the user's preferences in your app's 408 {@link android.content.SharedPreferences}. Set the shared preference in 409 your activity's {@link android.app.Activity#onPause onPause()} method, and 410 retrieve the preference in {@link android.app.Activity#onResume onResume()}. 411 For more information about saving preferences, read 412 <a href="{@docRoot}training/basics/data-storage/shared-preferences.html">Saving 413 Key-Value Sets</a>.</p> 414 415<p>The next lesson, 416 <a href="display-address.html">Displaying a Location Address</a>, shows 417 you how to display the street address for a given location.</p> 418