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&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
98    package="com.google.android.gms.location.sample.locationupdates" &gt;
99
100  &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
101&lt;/manifest&gt;
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&#64;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    &#64;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&#64;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&#64;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&#64;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