Home | History | Annotate | Download | only in location
      1 page.title=Receiving Location Updates
      2 trainingnavtop=true
      3 @jd:body
      4 <div id="tb-wrapper">
      5 <div id="tb">
      6 
      7 <h2>This lesson teaches you to</h2>
      8 <ol>
      9     <li><a href="#Permissions">Request Location Permission</a></li>
     10     <li><a href="#PlayServices">Check for Google Play Services</a></li>
     11     <li><a href="#DefineCallbacks">Define Location Services Callbacks</a></li>
     12     <li><a href="#UpdateParameters">Specify Update Parameters</a></li>
     13     <li><a href="#StartUpdates">Start Location Updates</a></li>
     14     <li><a href="#StopUpdates">Stop Location Updates</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">Setup Google Play Services SDK</a>
     21     </li>
     22     <li>
     23         <a href="retrieve-current.html">Retrieving the Current Location</a>
     24     </li>
     25  </ul>
     26 
     27 <h2>Try it out</h2>
     28 
     29 <div class="download-box">
     30   <a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download the sample</a>
     31   <p class="filename">LocationUpdates.zip</p>
     32 </div>
     33 
     34 </div>
     35 </div>
     36 
     37 <p>
     38     If your app does navigation or tracking, you probably want to get the user's
     39     location at regular intervals. While you can do this with
     40 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">LocationClient.getLastLocation()</a></code>,
     41     a more direct approach is to request periodic updates from Location Services. In
     42     response, Location Services automatically updates your app with the best available location,
     43     based on the currently-available location providers such as WiFi and GPS.
     44 </p>
     45 <p>
     46     To get periodic location updates from Location Services, you send a request using a location
     47     client. Depending on the form of the request, Location Services either invokes a callback
     48     method and passes in a {@link android.location.Location} object, or issues an
     49     {@link android.content.Intent} that contains the location in its extended data. The accuracy and
     50     frequency of the updates are affected by the location permissions you've requested and the
     51     parameters you pass to Location Services with the request.
     52 </p>
     53 <!-- Request permission -->
     54 <h2 id="Permissions">Specify App Permissions</h2>
     55 <p>
     56     Apps that use Location Services must request location permissions. Android has two location
     57     permissions, {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}
     58     and {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. The
     59     permission you choose affects the accuracy of the location updates you receive.
     60     For example, If you request only coarse location permission, Location Services obfuscates the
     61     updated location to an accuracy that's roughly equivalent to a city block.
     62 </p>
     63 <p>
     64     Requesting {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} implies
     65     a request for {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}.
     66 </p>
     67 <p>
     68     For example, to add the coarse location permission to your manifest, insert the following as a
     69     child element of
     70     the
     71 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
     72     element:
     73 </p>
     74 <pre>
     75 &lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/&gt;
     76 </pre>
     77 <!-- Check for Google Play services -->
     78 <h2 id="PlayServices">Check for Google Play Services</h2>
     79 <p>
     80     Location Services is part of the Google Play services APK. Since it's hard to anticipate the
     81     state of the user's device, you should always check that the APK is installed before you attempt
     82     to connect to Location Services. To check that the APK is installed, call
     83 <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#isGooglePlayServicesAvailable(android.content.Context)">GooglePlayServicesUtil.isGooglePlayServicesAvailable()</a></code>,
     84     which returns one of the
     85     integer result codes listed in the API reference documentation. If you encounter an error,
     86     call
     87 <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)">GooglePlayServicesUtil.getErrorDialog()</a></code>
     88     to retrieve localized dialog that prompts users to take the correct action, then display
     89     the dialog in a {@link android.support.v4.app.DialogFragment}. The dialog may allow the
     90     user to correct the problem, in which case Google Play services may send a result back to your
     91     activity. To handle this result, override the method
     92     {@link android.support.v4.app.FragmentActivity#onActivityResult onActivityResult()}
     93 
     94 </p>
     95 <p class="note">
     96     <strong>Note:</strong> To make your app compatible with
     97     platform version 1.6 and later, the activity that displays the
     98     {@link android.support.v4.app.DialogFragment} must subclass
     99     {@link android.support.v4.app.FragmentActivity} instead of {@link android.app.Activity}. Using
    100     {@link android.support.v4.app.FragmentActivity} also allows you to call
    101     {@link android.support.v4.app.FragmentActivity#getSupportFragmentManager
    102     getSupportFragmentManager()} to display the {@link android.support.v4.app.DialogFragment}.
    103 </p>
    104 <p>
    105     Since you usually need to check for Google Play services in more than one place in your code,
    106     define a method that encapsulates the check, then call the method before each connection
    107     attempt. The following snippet contains all of the code required to check for Google
    108     Play services:
    109 </p>
    110 <pre>
    111 public class MainActivity extends FragmentActivity {
    112     ...
    113     // Global constants
    114     /*
    115      * Define a request code to send to Google Play services
    116      * This code is returned in Activity.onActivityResult
    117      */
    118     private final static int
    119             CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
    120     ...
    121     // Define a DialogFragment that displays the error dialog
    122     public static class ErrorDialogFragment extends DialogFragment {
    123         // Global field to contain the error dialog
    124         private Dialog mDialog;
    125         // Default constructor. Sets the dialog field to null
    126         public ErrorDialogFragment() {
    127             super();
    128             mDialog = null;
    129         }
    130         // Set the dialog to display
    131         public void setDialog(Dialog dialog) {
    132             mDialog = dialog;
    133         }
    134         // Return a Dialog to the DialogFragment.
    135         &#64;Override
    136         public Dialog onCreateDialog(Bundle savedInstanceState) {
    137             return mDialog;
    138         }
    139     }
    140     ...
    141     /*
    142      * Handle results returned to the FragmentActivity
    143      * by Google Play services
    144      */
    145     &#64;Override
    146     protected void onActivityResult(
    147             int requestCode, int resultCode, Intent data) {
    148         // Decide what to do based on the original request code
    149         switch (requestCode) {
    150             ...
    151             case CONNECTION_FAILURE_RESOLUTION_REQUEST :
    152             /*
    153              * If the result code is Activity.RESULT_OK, try
    154              * to connect again
    155              */
    156                 switch (resultCode) {
    157                     case Activity.RESULT_OK :
    158                     /*
    159                      * Try the request again
    160                      */
    161                     ...
    162                     break;
    163                 }
    164             ...
    165         }
    166         ...
    167     }
    168     ...
    169     private boolean servicesConnected() {
    170         // Check that Google Play services is available
    171         int resultCode =
    172                 GooglePlayServicesUtil.
    173                         isGooglePlayServicesAvailable(this);
    174         // If Google Play services is available
    175         if (ConnectionResult.SUCCESS == resultCode) {
    176             // In debug mode, log the status
    177             Log.d("Location Updates",
    178                     "Google Play services is available.");
    179             // Continue
    180             return true;
    181         // Google Play services was not available for some reason
    182         } else {
    183             // Get the error code
    184             int errorCode = connectionResult.getErrorCode();
    185             // Get the error dialog from Google Play services
    186             Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
    187                     errorCode,
    188                     this,
    189                     CONNECTION_FAILURE_RESOLUTION_REQUEST);
    190             // If Google Play services can provide an error dialog
    191             if (errorDialog != null) {
    192                 // Create a new DialogFragment for the error dialog
    193                 ErrorDialogFragment errorFragment =
    194                         new ErrorDialogFragment();
    195                 // Set the dialog in the DialogFragment
    196                 errorFragment.setDialog(errorDialog);
    197                 // Show the error dialog in the DialogFragment
    198                 errorFragment.show(
    199                         getSupportFragmentManager(),
    200                         "Location Updates");
    201             }
    202         }
    203     }
    204     ...
    205 }
    206 </pre>
    207 <p>
    208     Snippets in the following sections call this method to verify that Google Play services is
    209     available.
    210 </p>
    211 <!--
    212     Define Location Services Callbacks
    213  -->
    214 <h2 id="DefineCallbacks">Define Location Services Callbacks</h2>
    215 <p>
    216     Before you request location updates, you must first implement the interfaces that Location
    217     Services uses to communicate connection status to your app:
    218 </p>
    219 <dl>
    220     <dt>
    221 <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html">ConnectionCallbacks</a></code>
    222     </dt>
    223     <dd>
    224         Specifies methods that Location Services calls when a location client is connected or
    225         disconnected.
    226     </dd>
    227     <dt>
    228 <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html">OnConnectionFailedListener</a></code>
    229     </dt>
    230     <dd>
    231         Specifies a method that Location Services calls if an error occurs while attempting to
    232         connect the location client. This method uses the previously-defined {@code showErrorDialog}
    233         method to display an error dialog that attempts to fix the problem using Google Play
    234         services.
    235     </dd>
    236 </dl>
    237 <p>
    238     The following snippet shows how to specify the interfaces and define the methods:
    239 </p>
    240 <pre>
    241 public class MainActivity extends FragmentActivity implements
    242         GooglePlayServicesClient.ConnectionCallbacks,
    243         GooglePlayServicesClient.OnConnectionFailedListener {
    244     ...
    245     /*
    246      * Called by Location Services when the request to connect the
    247      * client finishes successfully. At this point, you can
    248      * request the current location or start periodic updates
    249      */
    250     &#64;Override
    251     public void onConnected(Bundle dataBundle) {
    252         // Display the connection status
    253         Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
    254     }
    255     ...
    256     /*
    257      * Called by Location Services if the connection to the
    258      * location client drops because of an error.
    259      */
    260     &#64;Override
    261     public void onDisconnected() {
    262         // Display the connection status
    263         Toast.makeText(this, "Disconnected. Please re-connect.",
    264                 Toast.LENGTH_SHORT).show();
    265     }
    266     ...
    267     /*
    268      * Called by Location Services if the attempt to
    269      * Location Services fails.
    270      */
    271     &#64;Override
    272     public void onConnectionFailed(ConnectionResult connectionResult) {
    273         /*
    274          * Google Play services can resolve some errors it detects.
    275          * If the error has a resolution, try sending an Intent to
    276          * start a Google Play services activity that can resolve
    277          * error.
    278          */
    279         if (connectionResult.hasResolution()) {
    280             try {
    281                 // Start an Activity that tries to resolve the error
    282                 connectionResult.startResolutionForResult(
    283                         this,
    284                         CONNECTION_FAILURE_RESOLUTION_REQUEST);
    285                 /*
    286                 * Thrown if Google Play services canceled the original
    287                 * PendingIntent
    288                 */
    289             } catch (IntentSender.SendIntentException e) {
    290                 // Log the error
    291                 e.printStackTrace();
    292             }
    293         } else {
    294             /*
    295              * If no resolution is available, display a dialog to the
    296              * user with the error.
    297              */
    298             showErrorDialog(connectionResult.getErrorCode());
    299         }
    300     }
    301     ...
    302 }
    303 </pre>
    304 <h3>Define the location update callback</h3>
    305 <p>
    306     Location Services sends location updates to your app either as an {@link android.content.Intent}
    307     or as an argument passed to a callback method you define. This lesson shows you how to get the
    308     update using a callback method, because that pattern works best for most use cases. If you want
    309     to receive updates in the form of an {@link android.content.Intent}, read the lesson
    310     <a href="activity-recognition.html">Recognizing the User's Current Activity</a>, which
    311     presents a similar pattern.
    312 </p>
    313 <p>
    314     The callback method that Location Services invokes to send a location update to your app is
    315     specified in the
    316 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">LocationListener</a></code>
    317     interface, in the method
    318 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html#onLocationChanged(android.location.Location)">onLocationChanged()</a></code>.
    319     The incoming argument is a {@link android.location.Location} object containing the location's
    320     latitude and longitude. The following snippet shows how to specify the interface and define
    321     the method:
    322 </p>
    323 <pre>
    324 public class MainActivity extends FragmentActivity implements
    325         GooglePlayServicesClient.ConnectionCallbacks,
    326         GooglePlayServicesClient.OnConnectionFailedListener,
    327         LocationListener {
    328     ...
    329     // Define the callback method that receives location updates
    330     &#64;Override
    331     public void onLocationChanged(Location location) {
    332         // Report to the UI that the location was updated
    333         String msg = "Updated Location: " +
    334                 Double.toString(location.getLatitude()) + "," +
    335                 Double.toString(location.getLongitude());
    336         Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    337     }
    338     ...
    339 }
    340 </pre>
    341 <p>
    342     Now that you have the callbacks prepared, you can set up the request for location updates.
    343     The first step is to specify the parameters that control the updates.
    344 </p>
    345 <!-- Specify update parameters -->
    346 <h2 id="UpdateParameters">Specify Update Parameters</h2>
    347 <p>
    348     Location Services allows you to control the interval between updates and the location accuracy
    349     you want, by setting the values in a
    350 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">LocationRequest</a></code>
    351     object and then sending this object as part of your request to start updates.
    352 </p>
    353 <p>
    354     First, set the following interval parameters:
    355 </p>
    356 <dl>
    357     <dt>
    358         Update interval
    359     </dt>
    360     <dd>
    361         Set by
    362 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">LocationRequest.setInterval()</a></code>.
    363         This method sets the rate in milliseconds at which your app prefers to receive location
    364         updates. If no other apps are receiving updates from Location Services, your app will
    365         receive updates at this rate.
    366     </dd>
    367     <dt>
    368         Fastest update interval
    369     </dt>
    370     <dd>
    371         Set by
    372 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">LocationRequest.setFastestInterval()</a></code>.
    373         This method sets the <b>fastest</b> rate in milliseconds at which your app can handle
    374         location updates. You need to set this rate because other apps also affect the rate
    375         at which updates are sent. Location Services sends out updates at the fastest rate that any
    376         app requested by calling
    377 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">LocationRequest.setInterval()</a></code>.
    378         If this rate is faster than your app can handle, you may encounter problems with UI flicker
    379         or data overflow. To prevent this, call
    380 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">LocationRequest.setFastestInterval()</a></code>
    381         to set an upper limit to the update rate.
    382         <p>
    383             Calling
    384 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">LocationRequest.setFastestInterval()</a></code>
    385             also helps to save power. When you request a preferred update rate by calling
    386 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">LocationRequest.setInterval()</a></code>,
    387             and a maximum rate by calling
    388 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setFastestInterval(long)">LocationRequest.setFastestInterval()</a></code>,
    389             then your app gets the same update rate as the fastest rate in the system. If other
    390             apps have requested a faster rate, you get the benefit of a faster rate. If no other
    391             apps have a faster rate request outstanding, your app receives updates at the rate you specified
    392         with
    393 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">LocationRequest.setInterval()</a></code>.
    394         </p>
    395     </dd>
    396 </dl>
    397 <p>
    398     Next, set the accuracy parameter. In a foreground app, you need constant location updates with
    399     high accuracy, so use the setting
    400 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_HIGH_ACCURACY">LocationRequest.PRIORITY_HIGH_ACCURACY</a></code>.
    401 </p>
    402 <p>
    403     The following snippet shows how to set the update interval and accuracy in
    404     {@link android.support.v4.app.FragmentActivity#onCreate onCreate()}:
    405 </p>
    406 <pre>
    407 public class MainActivity extends FragmentActivity implements
    408         GooglePlayServicesClient.ConnectionCallbacks,
    409         GooglePlayServicesClient.OnConnectionFailedListener,
    410         LocationListener {
    411     ...
    412     // Global constants
    413     ...
    414     // Milliseconds per second
    415     private static final int MILLISECONDS_PER_SECOND = 1000;
    416     // Update frequency in seconds
    417     public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
    418     // Update frequency in milliseconds
    419     private static final long UPDATE_INTERVAL =
    420             MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
    421     // The fastest update frequency, in seconds
    422     private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
    423     // A fast frequency ceiling in milliseconds
    424     private static final long FASTEST_INTERVAL =
    425             MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
    426     ...
    427     // Define an object that holds accuracy and frequency parameters
    428     LocationRequest mLocationRequest;
    429     ...
    430     &#64;Override
    431     protected void onCreate(Bundle savedInstanceState) {
    432         super.onCreate(savedInstanceState);
    433         // Create the LocationRequest object
    434         mLocationRequest = LocationRequest.create();
    435         // Use high accuracy
    436         mLocationRequest.setPriority(
    437                 LocationRequest.PRIORITY_HIGH_ACCURACY);
    438         // Set the update interval to 5 seconds
    439         mLocationRequest.setInterval(UPDATE_INTERVAL);
    440         // Set the fastest update interval to 1 second
    441         mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
    442         ...
    443     }
    444     ...
    445 }
    446 </pre>
    447 <p class="note">
    448    <strong>Note:</strong> If your app accesses the network or does other long-running work after
    449    receiving a location update, adjust the fastest interval to a slower value. This prevents your
    450    app from receiving updates it can't use. Once the long-running work is done, set the fastest
    451    interval back to a fast value.
    452 </p>
    453 <!-- Start Location Updates -->
    454 <h2 id="StartUpdates">Start Location Updates</h2>
    455 <p>
    456     To send the request for location updates, create a location client in
    457     {@link android.support.v4.app.FragmentActivity#onCreate onCreate()}, then connect it and make
    458     the request by calling
    459 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#requestLocationUpdates(com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">requestLocationUpdates()</a></code>.
    460     Since your client must be connected for your app to receive updates, you should
    461     connect the client in
    462     {@link android.support.v4.app.FragmentActivity#onStart onStart()}. This ensures that you always
    463     have a valid, connected client while your app is visible. Since you need a connection before you
    464     can request updates, make the update request in
    465 <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">ConnectionCallbacks.onConnected()</a></code>
    466 </p>
    467 <p>
    468     Remember that the user may want to turn off location updates for various reasons. You should
    469     provide a way for the user to do this, and you should ensure that you don't start updates in
    470     {@link android.support.v4.app.FragmentActivity#onStart onStart()} if updates were previously
    471     turned off. To track the user's preference, store it in your app's
    472     {@link android.content.SharedPreferences} in
    473     {@link android.support.v4.app.FragmentActivity#onPause onPause()} and retrieve it in
    474     {@link android.support.v4.app.FragmentActivity#onResume onResume()}.
    475 </p>
    476 <p>
    477     The following snippet shows how to set up the client in
    478     {@link android.support.v4.app.FragmentActivity#onCreate onCreate()}, and how to connect it
    479     and request updates in {@link android.support.v4.app.FragmentActivity#onStart onStart()}:
    480 </p>
    481 <pre>
    482 public class MainActivity extends FragmentActivity implements
    483         GooglePlayServicesClient.ConnectionCallbacks,
    484         GooglePlayServicesClient.OnConnectionFailedListener,
    485         LocationListener {
    486     ...
    487     // Global variables
    488     ...
    489     LocationClient mLocationClient;
    490     boolean mUpdatesRequested;
    491     ...
    492     &#64;Override
    493     protected void onCreate(Bundle savedInstanceState) {
    494         ...
    495         // Open the shared preferences
    496         mPrefs = getSharedPreferences("SharedPreferences",
    497                 Context.MODE_PRIVATE);
    498         // Get a SharedPreferences editor
    499         mEditor = mPrefs.edit();
    500         /*
    501          * Create a new location client, using the enclosing class to
    502          * handle callbacks.
    503          */
    504         mLocationClient = new LocationClient(this, this, this);
    505         // Start with updates turned off
    506         mUpdatesRequested = false;
    507         ...
    508     }
    509     ...
    510     &#64;Override
    511     protected void onPause() {
    512         // Save the current setting for updates
    513         mEditor.putBoolean("KEY_UPDATES_ON", mUpdatesRequested);
    514         mEditor.commit();
    515         super.onPause();
    516     }
    517     ...
    518     &#64;Override
    519     protected void onStart() {
    520         ...
    521         mLocationClient.connect();
    522     }
    523     ...
    524     &#64;Override
    525     protected void onResume() {
    526         /*
    527          * Get any previous setting for location updates
    528          * Gets "false" if an error occurs
    529          */
    530         if (mPrefs.contains("KEY_UPDATES_ON")) {
    531             mUpdatesRequested =
    532                     mPrefs.getBoolean("KEY_UPDATES_ON", false);
    533 
    534         // Otherwise, turn off location updates
    535         } else {
    536             mEditor.putBoolean("KEY_UPDATES_ON", false);
    537             mEditor.commit();
    538         }
    539     }
    540     ...
    541     /*
    542      * Called by Location Services when the request to connect the
    543      * client finishes successfully. At this point, you can
    544      * request the current location or start periodic updates
    545      */
    546     &#64;Override
    547     public void onConnected(Bundle dataBundle) {
    548         // Display the connection status
    549         Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
    550         // If already requested, start periodic updates
    551         if (mUpdatesRequested) {
    552             mLocationClient.requestLocationUpdates(mLocationRequest, this);
    553         }
    554     }
    555     ...
    556 }
    557 </pre>
    558 <p>
    559     For more information about saving preferences, read
    560 <a href="{@docRoot}training/basics/data-storage/shared-preferences.html">Saving Key-Value Sets</a>.
    561 </p>
    562 <!--
    563     Stop Location Updates
    564  -->
    565 <h2 id="StopUpdates">Stop Location Updates</h2>
    566 <p>
    567     To stop location updates, save the state of the update flag in
    568     {@link android.support.v4.app.FragmentActivity#onPause onPause()}, and stop updates in
    569     {@link android.support.v4.app.FragmentActivity#onStop onStop()} by calling
    570 <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#removeLocationUpdates(com.google.android.gms.location.LocationListener)">removeLocationUpdates(LocationListener)</a></code>.
    571     For example:
    572 </p>
    573 <pre>
    574 public class MainActivity extends FragmentActivity implements
    575         GooglePlayServicesClient.ConnectionCallbacks,
    576         GooglePlayServicesClient.OnConnectionFailedListener,
    577         LocationListener {
    578     ...
    579     /*
    580      * Called when the Activity is no longer visible at all.
    581      * Stop updates and disconnect.
    582      */
    583     &#64;Override
    584     protected void onStop() {
    585         // If the client is connected
    586         if (mLocationClient.isConnected()) {
    587             /*
    588              * Remove location updates for a listener.
    589              * The current Activity is the listener, so
    590              * the argument is "this".
    591              */
    592             removeLocationUpdates(this);
    593         }
    594         /*
    595          * After disconnect() is called, the client is
    596          * considered "dead".
    597          */
    598         mLocationClient.disconnect();
    599         super.onStop();
    600     }
    601     ...
    602 }
    603 </pre>
    604 <p>
    605     You now have the basic structure of an app that requests and receives periodic location updates.
    606     You can combine the features described in this lesson with the geofencing, activity recognition,
    607     or reverse geocoding features described in other lessons in this class.
    608 </p>
    609 <p>
    610     The next lesson, <a href="display-address.html">Displaying a Location Address</a>, shows you how
    611     to use the current location to display the current street address.
    612 </p>
    613