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