| page.title=Receiving Location Updates |
| trainingnavtop=true |
| @jd:body |
| |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| |
| <h2>This lesson teaches you how to</h2> |
| <ol> |
| <li><a href="#get-last-location">Get the Last Known Location</a></li> |
| <li><a href="#updates">Request Location Updates</a></li> |
| <li><a href="#callback">Define the Location Update Callback</a></li> |
| <li><a href="#stop-updates">Stop Location Updates</a></li> |
| <li><a href="#save-state">Save the State of the Activity</a></li> |
| </ol> |
| |
| <h2>You should also read</h2> |
| <ul> |
| <li> |
| <a href="{@docRoot}google/play-services/setup.html">Setting up Google Play |
| Services</a> |
| </li> |
| <li> |
| <a href="retrieve-current.html">Getting the Last Known Location</a> |
| </li> |
| </ul> |
| |
| <h2>Try it out</h2> |
| |
| <ul> |
| <li> |
| <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates" class="external-link">LocationUpdates</a> |
| </li> |
| </ul> |
| </div> |
| </div> |
| |
| <p>If your app can continuously track location, it can deliver more relevant |
| information to the user. For example, if your app helps the user find their |
| way while walking or driving, or if your app tracks the location of assets, it |
| needs to get the location of the device at regular intervals. As well as the |
| geographical location (latitude and longitude), you may want to give the user |
| further information such as the bearing (horizontal direction of travel), |
| altitude, or velocity of the device. This information, and more, is available |
| in the {@link android.location.Location} object that your app can retrieve |
| from the |
| <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused |
| location provider</a>.</p> |
| |
| <p>While you can get a device's location with |
| <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>, |
| as illustrated in the lesson on |
| <a href="retrieve-current.html">Getting the Last Known Location</a>, |
| a more direct approach is to request periodic updates from the fused location |
| provider. In response, the API updates your app periodically with the best |
| available location, based on the currently-available location providers such |
| as WiFi and GPS (Global Positioning System). The accuracy of the location is |
| determined by the providers, the location permissions you've requested, and |
| the options you set in the location request.</p> |
| |
| <p>This lesson shows you how to request regular updates about a device's |
| location using the |
| <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> |
| method in the fused location provider. |
| |
| <h2 id="get-last-location">Get the Last Known Location</h2> |
| |
| <p>The last known location of the device provides a handy base from which to |
| start, ensuring that the app has a known location before starting the |
| periodic location updates. The lesson on |
| <a href="retrieve-current.html">Getting the Last Known Location</a> shows you |
| how to get the last known location by calling |
| <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>. |
| The snippets in the following sections assume that your app has already |
| retrieved the last known location and stored it as a |
| {@link android.location.Location} object in the global variable |
| {@code mCurrentLocation}.</p> |
| |
| <p>Apps that use location services must request location permissions. In this |
| lesson you require fine location detection, so that your app can get as |
| precise a location as possible from the available location providers. Request |
| this permission with the |
| {@code uses-permission} element in your app manifest, as shown in the |
| following example:</p> |
| |
| <pre> |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| package="com.google.android.gms.location.sample.locationupdates" > |
| |
| <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> |
| </manifest> |
| </pre> |
| |
| <h2 id="updates">Request Location Updates</h2> |
| |
| <p>Before requesting location updates, your app must connect to location |
| services and make a location request. The lesson on |
| <a href="change-location-settings.html">Changing Location Settings</a> |
| shows you how to do this. Once a location request is in place you can start |
| the regular updates by calling |
| <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>. |
| Do this in the |
| <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a> |
| callback provided by Google API Client, which is called when the client is |
| ready.</p> |
| |
| <p>Depending on the form of the request, the fused location provider either |
| invokes the |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener.onLocationChanged()}</a> |
| callback method and passes it a {@link android.location.Location} object, or |
| issues a |
| <a href="{@docRoot}reference/android/app/PendingIntent.html">{@code PendingIntent}</a> |
| that contains the location in its extended data. The accuracy and frequency of |
| the updates are affected by the location permissions you've requested and the |
| options you set in the location request object.</p> |
| |
| <p>This lesson shows you how to get the update using the |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a> |
| callback approach. Call |
| <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>, |
| passing it your instance of the |
| <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>, |
| the |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a> |
| object, |
| and a <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>. |
| Define a {@code startLocationUpdates()} method, called from the |
| <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a> |
| callback, as shown in the following code sample:</p> |
| |
| <pre> |
| @Override |
| public void onConnected(Bundle connectionHint) { |
| ... |
| if (mRequestingLocationUpdates) { |
| startLocationUpdates(); |
| } |
| } |
| |
| protected void startLocationUpdates() { |
| LocationServices.FusedLocationApi.requestLocationUpdates( |
| mGoogleApiClient, mLocationRequest, this); |
| } |
| </pre> |
| |
| <p>Notice that the above code snippet refers to a boolean flag, |
| {@code mRequestingLocationUpdates}, used to track whether the user has |
| turned location updates on or off. For more about retaining the value of this |
| flag across instances of the activity, see |
| <a href="#save-state">Save the State of the Activity</a>. |
| |
| <h2 id="callback">Define the Location Update Callback</h2> |
| |
| <p>The fused location provider invokes the |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html#onLocationChanged(android.location.Location)">{@code LocationListener.onLocationChanged()}</a> |
| callback method. The incoming argument is a {@link android.location.Location} |
| object containing the location's latitude and longitude. The following snippet |
| shows how to implement the |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a> |
| interface and define the method, then get the timestamp of the location update |
| and display the latitude, longitude and timestamp on your app's user |
| interface:</p> |
| |
| <pre> |
| public class MainActivity extends ActionBarActivity implements |
| ConnectionCallbacks, OnConnectionFailedListener, LocationListener { |
| ... |
| @Override |
| public void onLocationChanged(Location location) { |
| mCurrentLocation = location; |
| mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); |
| updateUI(); |
| } |
| |
| private void updateUI() { |
| mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude())); |
| mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude())); |
| mLastUpdateTimeTextView.setText(mLastUpdateTime); |
| } |
| } |
| </pre> |
| |
| <h2 id="stop-updates">Stop Location Updates</h2> |
| |
| <p>Consider whether you want to stop the location updates when the activity is |
| no longer in focus, such as when the user switches to another app or to a |
| different activity in the same app. This can be handy to reduce power |
| consumption, provided the app doesn't need to collect information even when |
| it's running in the background. This section shows how you can stop the |
| updates in the activity's |
| {@link android.app.Activity#onPause onPause()} method.</p> |
| |
| <p>To stop location updates, call |
| <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>, |
| passing it your instance of the |
| <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a> |
| object and a |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>, |
| as shown in the following code sample:</p> |
| |
| <pre> |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| stopLocationUpdates(); |
| } |
| |
| protected void stopLocationUpdates() { |
| LocationServices.FusedLocationApi.removeLocationUpdates( |
| mGoogleApiClient, this); |
| } |
| </pre> |
| |
| <p>Use a boolean, {@code mRequestingLocationUpdates}, to track |
| whether location updates are currently turned on. In the activity's |
| {@link android.app.Activity#onResume onResume()} method, check |
| whether location updates are currently active, and activate them if not:</p> |
| |
| <pre> |
| @Override |
| public void onResume() { |
| super.onResume(); |
| if (mGoogleApiClient.isConnected() && !mRequestingLocationUpdates) { |
| startLocationUpdates(); |
| } |
| } |
| </pre> |
| |
| <h2 id="save-state">Save the State of the Activity</h2> |
| |
| <p>A change to the device's configuration, such as a change in screen |
| orientation or language, can cause the current activity to be destroyed. Your |
| app must therefore store any information it needs to recreate the activity. |
| One way to do this is via an instance state stored in a |
| {@link android.os.Bundle} object.</p> |
| |
| <p>The following code sample shows how to use the activity's |
| <a href="{@docRoot}reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)">{@code onSaveInstanceState()}</a> |
| callback to save the instance state:</p> |
| |
| <pre> |
| public void onSaveInstanceState(Bundle savedInstanceState) { |
| savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, |
| mRequestingLocationUpdates); |
| savedInstanceState.putParcelable(LOCATION_KEY, mCurrentLocation); |
| savedInstanceState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime); |
| super.onSaveInstanceState(savedInstanceState); |
| } |
| </pre> |
| |
| <p>Define an {@code updateValuesFromBundle()} method to restore |
| the saved values from the previous instance of the activity, if they're |
| available. Call the method from the activity's |
| {@link android.app.Activity#onCreate onCreate()} method, as shown in the |
| following code sample:</p> |
| |
| <pre> |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| ... |
| updateValuesFromBundle(savedInstanceState); |
| } |
| |
| private void updateValuesFromBundle(Bundle savedInstanceState) { |
| if (savedInstanceState != null) { |
| // Update the value of mRequestingLocationUpdates from the Bundle, and |
| // make sure that the Start Updates and Stop Updates buttons are |
| // correctly enabled or disabled. |
| if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) { |
| mRequestingLocationUpdates = savedInstanceState.getBoolean( |
| REQUESTING_LOCATION_UPDATES_KEY); |
| setButtonsEnabledState(); |
| } |
| |
| // Update the value of mCurrentLocation from the Bundle and update the |
| // UI to show the correct latitude and longitude. |
| if (savedInstanceState.keySet().contains(LOCATION_KEY)) { |
| // Since LOCATION_KEY was found in the Bundle, we can be sure that |
| // mCurrentLocationis not null. |
| mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY); |
| } |
| |
| // Update the value of mLastUpdateTime from the Bundle and update the UI. |
| if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) { |
| mLastUpdateTime = savedInstanceState.getString( |
| LAST_UPDATED_TIME_STRING_KEY); |
| } |
| updateUI(); |
| } |
| } |
| </pre> |
| |
| <p>For more about saving instance state, see the |
| <a href="{@docRoot}reference/android/app/Activity.html#ConfigurationChanges">Android |
| Activity</a> class reference.</p> |
| |
| <p class="note"><strong>Note:</strong> For a more persistent storage, you can |
| store the user's preferences in your app's |
| {@link android.content.SharedPreferences}. Set the shared preference in |
| your activity's {@link android.app.Activity#onPause onPause()} method, and |
| retrieve the preference in {@link android.app.Activity#onResume onResume()}. |
| For more information about saving preferences, read |
| <a href="{@docRoot}training/basics/data-storage/shared-preferences.html">Saving |
| Key-Value Sets</a>.</p> |
| |
| <p>The next lesson, |
| <a href="display-address.html">Displaying a Location Address</a>, shows |
| you how to display the street address for a given location.</p> |