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="#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
    133 public void onConnected(Bundle connectionHint) {
    134     ...
    135     if (mRequestingLocationUpdates) {
    136         startLocationUpdates();
    137     }
    138 }
    139 
    140 protected 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>
    165 public 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
    203 protected void onPause() {
    204     super.onPause();
    205     stopLocationUpdates();
    206 }
    207 
    208 protected 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
    221 public 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>
    242 public 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
    259 public void onCreate(Bundle savedInstanceState) {
    260     ...
    261     updateValuesFromBundle(savedInstanceState);
    262 }
    263 
    264 private 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