Home | History | Annotate | Download | only in location
      1 page.title=Receiving Location Updates
      2 trainingnavtop=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>
    182 protected 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
    242 public void onConnected(Bundle connectionHint) {
    243     ...
    244     if (mRequestingLocationUpdates) {
    245         startLocationUpdates();
    246     }
    247 }
    248 
    249 protected 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>
    274 public 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
    312 protected void onPause() {
    313     super.onPause();
    314     stopLocationUpdates();
    315 }
    316 
    317 protected 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
    330 public 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>
    351 public 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
    368 public void onCreate(Bundle savedInstanceState) {
    369     ...
    370     updateValuesFromBundle(savedInstanceState);
    371 }
    372 
    373 private 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