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="#get-last-location">Get the Last Known Location</a></li> 11 <li><a href="#updates">Request Location Updates</a></li> 12 <li><a href="#callback">Define the Location Update Callback</a></li> 13 <li><a href="#stop-updates">Stop Location Updates</a></li> 14 <li><a href="#save-state">Save the State of the Activity</a></li> 15 </ol> 16 17 <h2>You should also read</h2> 18 <ul> 19 <li> 20 <a href="{@docRoot}google/play-services/setup.html">Setting up Google Play 21 Services</a> 22 </li> 23 <li> 24 <a href="retrieve-current.html">Getting the Last Known Location</a> 25 </li> 26 </ul> 27 28 <h2>Try it out</h2> 29 30 <ul> 31 <li> 32 <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates" class="external-link">LocationUpdates</a> 33 </li> 34 </ul> 35 </div> 36</div> 37 38<p>If your app can continuously track location, it can deliver more relevant 39 information to the user. For example, if your app helps the user find their 40 way while walking or driving, or if your app tracks the location of assets, it 41 needs to get the location of the device at regular intervals. As well as the 42 geographical location (latitude and longitude), you may want to give the user 43 further information such as the bearing (horizontal direction of travel), 44 altitude, or velocity of the device. This information, and more, is available 45 in the {@link android.location.Location} object that your app can retrieve 46 from the 47 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused 48 location provider</a>.</p> 49 50<p>While you can get a device's location with 51 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>, 52 as illustrated in the lesson on 53 <a href="retrieve-current.html">Getting the Last Known Location</a>, 54 a more direct approach is to request periodic updates from the fused location 55 provider. In response, the API updates your app periodically with the best 56 available location, based on the currently-available location providers such 57 as WiFi and GPS (Global Positioning System). The accuracy of the location is 58 determined by the providers, the location permissions you've requested, and 59 the options you set in the location request.</p> 60 61<p>This lesson shows you how to request regular updates about a device's 62 location using the 63 <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> 64 method in the fused location provider. 65 66<h2 id="get-last-location">Get the Last Known Location</h2> 67 68<p>The last known location of the device provides a handy base from which to 69 start, ensuring that the app has a known location before starting the 70 periodic location updates. The lesson on 71 <a href="retrieve-current.html">Getting the Last Known Location</a> shows you 72 how to get the last known location by calling 73 <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>. 74 The snippets in the following sections assume that your app has already 75 retrieved the last known location and stored it as a 76 {@link android.location.Location} object in the global variable 77 {@code mCurrentLocation}.</p> 78 79<p>Apps that use location services must request location permissions. In this 80 lesson you require fine location detection, so that your app can get as 81 precise a location as possible from the available location providers. Request 82 this permission with the 83 {@code uses-permission} element in your app manifest, as shown in the 84 following example:</p> 85 86<pre> 87<manifest xmlns:android="http://schemas.android.com/apk/res/android" 88 package="com.google.android.gms.location.sample.locationupdates" > 89 90 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 91</manifest> 92</pre> 93 94<h2 id="updates">Request Location Updates</h2> 95 96<p>Before requesting location updates, your app must connect to location 97 services and make a location request. The lesson on 98 <a href="change-location-settings.html">Changing Location Settings</a> 99 shows you how to do this. Once a location request is in place you can start 100 the regular updates by calling 101 <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>. 102 Do this in the 103 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a> 104 callback provided by Google API Client, which is called when the client is 105 ready.</p> 106 107<p>Depending on the form of the request, the fused location provider either 108 invokes the 109 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener.onLocationChanged()}</a> 110 callback method and passes it a {@link android.location.Location} object, or 111 issues a 112 <a href="{@docRoot}reference/android/app/PendingIntent.html">{@code PendingIntent}</a> 113 that contains the location in its extended data. The accuracy and frequency of 114 the updates are affected by the location permissions you've requested and the 115 options you set in the location request object.</p> 116 117<p>This lesson shows you how to get the update using the 118 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a> 119 callback approach. Call 120 <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>, 121 passing it your instance of the 122 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>, 123 the 124 <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a> 125 object, 126 and a <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>. 127 Define a {@code startLocationUpdates()} method, called from the 128 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a> 129 callback, as shown in the following code sample:</p> 130 131<pre> 132@Override 133public void onConnected(Bundle connectionHint) { 134 ... 135 if (mRequestingLocationUpdates) { 136 startLocationUpdates(); 137 } 138} 139 140protected void startLocationUpdates() { 141 LocationServices.FusedLocationApi.requestLocationUpdates( 142 mGoogleApiClient, mLocationRequest, this); 143} 144</pre> 145 146<p>Notice that the above code snippet refers to a boolean flag, 147 {@code mRequestingLocationUpdates}, used to track whether the user has 148 turned location updates on or off. For more about retaining the value of this 149 flag across instances of the activity, see 150 <a href="#save-state">Save the State of the Activity</a>. 151 152<h2 id="callback">Define the Location Update Callback</h2> 153 154<p>The fused location provider invokes the 155 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html#onLocationChanged(android.location.Location)">{@code LocationListener.onLocationChanged()}</a> 156 callback method. The incoming argument is a {@link android.location.Location} 157 object containing the location's latitude and longitude. The following snippet 158 shows how to implement the 159 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a> 160 interface and define the method, then get the timestamp of the location update 161 and display the latitude, longitude and timestamp on your app's user 162 interface:</p> 163 164<pre> 165public class MainActivity extends ActionBarActivity implements 166 ConnectionCallbacks, OnConnectionFailedListener, LocationListener { 167 ... 168 @Override 169 public void onLocationChanged(Location location) { 170 mCurrentLocation = location; 171 mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); 172 updateUI(); 173 } 174 175 private void updateUI() { 176 mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude())); 177 mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude())); 178 mLastUpdateTimeTextView.setText(mLastUpdateTime); 179 } 180} 181</pre> 182 183<h2 id="stop-updates">Stop Location Updates</h2> 184 185<p>Consider whether you want to stop the location updates when the activity is 186 no longer in focus, such as when the user switches to another app or to a 187 different activity in the same app. This can be handy to reduce power 188 consumption, provided the app doesn't need to collect information even when 189 it's running in the background. This section shows how you can stop the 190 updates in the activity's 191 {@link android.app.Activity#onPause onPause()} method.</p> 192 193<p>To stop location updates, call 194 <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>, 195 passing it your instance of the 196 <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a> 197 object and a 198 <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>, 199 as shown in the following code sample:</p> 200 201<pre> 202@Override 203protected void onPause() { 204 super.onPause(); 205 stopLocationUpdates(); 206} 207 208protected void stopLocationUpdates() { 209 LocationServices.FusedLocationApi.removeLocationUpdates( 210 mGoogleApiClient, this); 211} 212</pre> 213 214<p>Use a boolean, {@code mRequestingLocationUpdates}, to track 215 whether location updates are currently turned on. In the activity's 216 {@link android.app.Activity#onResume onResume()} method, check 217 whether location updates are currently active, and activate them if not:</p> 218 219<pre> 220@Override 221public void onResume() { 222 super.onResume(); 223 if (mGoogleApiClient.isConnected() && !mRequestingLocationUpdates) { 224 startLocationUpdates(); 225 } 226} 227</pre> 228 229<h2 id="save-state">Save the State of the Activity</h2> 230 231<p>A change to the device's configuration, such as a change in screen 232 orientation or language, can cause the current activity to be destroyed. Your 233 app must therefore store any information it needs to recreate the activity. 234 One way to do this is via an instance state stored in a 235 {@link android.os.Bundle} object.</p> 236 237<p>The following code sample shows how to use the activity's 238 <a href="{@docRoot}reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)">{@code onSaveInstanceState()}</a> 239 callback to save the instance state:</p> 240 241<pre> 242public void onSaveInstanceState(Bundle savedInstanceState) { 243 savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, 244 mRequestingLocationUpdates); 245 savedInstanceState.putParcelable(LOCATION_KEY, mCurrentLocation); 246 savedInstanceState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime); 247 super.onSaveInstanceState(savedInstanceState); 248} 249</pre> 250 251<p>Define an {@code updateValuesFromBundle()} method to restore 252 the saved values from the previous instance of the activity, if they're 253 available. Call the method from the activity's 254 {@link android.app.Activity#onCreate onCreate()} method, as shown in the 255 following code sample:</p> 256 257<pre> 258@Override 259public void onCreate(Bundle savedInstanceState) { 260 ... 261 updateValuesFromBundle(savedInstanceState); 262} 263 264private void updateValuesFromBundle(Bundle savedInstanceState) { 265 if (savedInstanceState != null) { 266 // Update the value of mRequestingLocationUpdates from the Bundle, and 267 // make sure that the Start Updates and Stop Updates buttons are 268 // correctly enabled or disabled. 269 if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) { 270 mRequestingLocationUpdates = savedInstanceState.getBoolean( 271 REQUESTING_LOCATION_UPDATES_KEY); 272 setButtonsEnabledState(); 273 } 274 275 // Update the value of mCurrentLocation from the Bundle and update the 276 // UI to show the correct latitude and longitude. 277 if (savedInstanceState.keySet().contains(LOCATION_KEY)) { 278 // Since LOCATION_KEY was found in the Bundle, we can be sure that 279 // mCurrentLocationis not null. 280 mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY); 281 } 282 283 // Update the value of mLastUpdateTime from the Bundle and update the UI. 284 if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) { 285 mLastUpdateTime = savedInstanceState.getString( 286 LAST_UPDATED_TIME_STRING_KEY); 287 } 288 updateUI(); 289 } 290} 291</pre> 292 293<p>For more about saving instance state, see the 294 <a href="{@docRoot}reference/android/app/Activity.html#ConfigurationChanges">Android 295 Activity</a> class reference.</p> 296 297<p class="note"><strong>Note:</strong> For a more persistent storage, you can 298 store the user's preferences in your app's 299 {@link android.content.SharedPreferences}. Set the shared preference in 300 your activity's {@link android.app.Activity#onPause onPause()} method, and 301 retrieve the preference in {@link android.app.Activity#onResume onResume()}. 302 For more information about saving preferences, read 303 <a href="{@docRoot}training/basics/data-storage/shared-preferences.html">Saving 304 Key-Value Sets</a>.</p> 305 306<p>The next lesson, 307 <a href="display-address.html">Displaying a Location Address</a>, shows 308 you how to display the street address for a given location.</p> 309