| 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="#connect">Connect to Location Services</a></li> |
| <li><a href="#location-request">Set Up a Location Request</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="connect">Connect to Location Services</h2> |
| |
| <p>Location services for apps are provided through Google Play services and the |
| fused location provider. In order to use these services, you connect your app |
| using the Google API Client and then request location updates. For details on |
| connecting with the |
| <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>, |
| follow the instructions in |
| <a href="retrieve-current.html">Getting the Last Known Location</a>, including |
| requesting the current location.</p> |
| |
| <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="location-request">Set Up a Location Request</h2> |
| |
| <p>To store parameters for requests to the fused location provider, create a |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a>. |
| The parameters determine the levels of accuracy requested. For details of all |
| the options available in the location request, see the |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a> |
| class reference. This lesson sets the update interval, fastest update |
| interval, and priority, as described below:</p> |
| |
| <dl> |
| <dt> |
| Update interval |
| </dt> |
| <dd> |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">{@code setInterval()}</a> |
| - This method sets the rate in milliseconds at which your app prefers to |
| receive location updates. Note that the location updates may be faster than |
| this rate if another app is receiving updates at a faster rate, or slower |
| than this rate, or there may be no updates at all (if the device has no |
| connectivity, for example). |
| </dd> |
| <dt> |
| Fastest update interval |
| </dt> |
| <dd> |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">{@code setFastestInterval()}</a> |
| - This method sets the <strong>fastest</strong> rate in milliseconds at which |
| your app can handle location updates. You need to set this rate because |
| other apps also affect the rate at which updates are sent. The Google Play |
| services location APIs send out updates at the fastest rate that any app |
| has requested with |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">{@code setInterval()}</a>. |
| If this rate is faster |
| than your app can handle, you may encounter problems with UI flicker or data |
| overflow. To prevent this, call |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">{@code setFastestInterval()}</a> |
| to set an upper limit to the update rate. |
| </dd> |
| <dt>Priority</dt> |
| <dd> |
| <p> |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setPriority(int)">{@code setPriority()}</a> |
| - This method sets the priority of the request, which gives the Google Play |
| services location services a strong hint about which location sources to use. |
| The following values are supported:</p> |
| <ul> |
| <li> |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_BALANCED_POWER_ACCURACY">{@code PRIORITY_BALANCED_POWER_ACCURACY}</a> |
| - Use this setting to request location precision to within a city |
| block, which is an accuracy of approximately 100 meters. This is |
| considered a coarse level of accuracy, and is likely to consume less |
| power. With this setting, the location services are likely to use WiFi |
| and cell tower positioning. Note, however, that the choice of location |
| provider depends on many other factors, such as which sources are |
| available.</li> |
| <li> |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_HIGH_ACCURACY">{@code PRIORITY_HIGH_ACCURACY}</a> |
| - Use this setting to request the most precise location possible. With |
| this setting, the location services are more likely to use GPS |
| (Global Positioning System) to determine the location.</li> |
| <li><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_LOW_POWER">{@code PRIORITY_LOW_POWER}</a> |
| - Use this setting to request city-level precision, which is |
| an accuracy of approximately 10 kilometers. This is considered a |
| coarse level of accuracy, and is likely to consume less power.</li> |
| <li><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_NO_POWER">{@code PRIORITY_NO_POWER}</a> |
| - Use this setting if you need negligible impact on power consumption, |
| but want to receive location updates when available. With this |
| setting, your app does not trigger any location updates, but |
| receives locations triggered by other apps.</li> |
| </ul> |
| </dd> |
| </dl> |
| |
| <p>Create the location request and set the parameters as shown in this |
| code sample:</p> |
| |
| <pre> |
| protected void createLocationRequest() { |
| LocationRequest mLocationRequest = new LocationRequest(); |
| mLocationRequest.setInterval(10000); |
| mLocationRequest.setFastestInterval(5000); |
| mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); |
| } |
| </pre> |
| |
| <p>The priority of |
| <a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_HIGH_ACCURACY">{@code PRIORITY_HIGH_ACCURACY}</a>, |
| combined with the |
| {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} |
| permission setting that you've defined in the app manifest, and a fast update |
| interval of 5000 milliseconds (5 seconds), causes the fused location |
| provider to return location updates that are accurate to within a few feet. |
| This approach is appropriate for mapping apps that display the location in |
| real time.</p> |
| |
| <p class="note"><strong>Performance hint:</strong> If your app accesses the |
| network or does other long-running work after receiving a location update, |
| adjust the fastest interval to a slower value. This adjustment prevents your |
| app from receiving updates it can't use. Once the long-running work is done, |
| set the fastest interval back to a fast value.</p> |
| |
| <h2 id="updates">Request Location Updates</h2> |
| |
| <p>Now that you've set up a location request containing your app's requirements |
| for the location updates, 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> |