Home | History | Annotate | Download | only in location
      1 page.title=Obtaining the Current Location
      2 parent.title=Making Your App Location Aware
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 previous.title=Using the Location Manager
      7 previous.link=locationmanager.html
      8 next.title=Displaying the Location Address
      9 next.link=geocoding.html
     10 
     11 
     12 @jd:body
     13 
     14 
     15 <!-- This is the training bar -->
     16 <div id="tb-wrapper">
     17 <div id="tb">
     18 
     19 <h2>This lesson teaches you to</h2>
     20 <ol>
     21   <li><a href="currentlocation.html#TaskSetupLocationListener">Set Up the Location Listener</a></li>
     22   <li><a href="currentlocation.html#TaskHandleLocationUpdates">Handle Multiple Sources of Location Updates</a></li>
     23   <li><a href="currentlocation.html#TaskGetLastKnownLocation">Use getLastKnownLocation() Wisely</a></li>
     24   <li><a href="currentlocation.html#TaskTerminateUpdates">Terminate Location Updates</a></li>
     25 </ol>
     26 
     27 <h2>You should also read</h2>
     28 
     29 <ul>
     30   <li><a href="{@docRoot}guide/topics/location/index.html">Location and Maps</a></li>
     31 </ul>
     32 
     33 <h2>Try it out</h2>
     34 
     35 <div class="download-box">
     36 <a href="http://developer.android.com/shareables/training/LocationAware.zip" class="button">Download
     37   the sample app</a>
     38 <p class="filename">LocationAware.zip</p>
     39 </div>
     40 
     41 </div>
     42 </div>
     43 
     44 <p>After setting up your application to work with {@link android.location.LocationManager}, you can begin to obtain location updates.</p>
     45 
     46 <h2 id="TaskSetupLocationListener">Set Up the Location Listener</h2>
     47 
     48 <p>The {@link android.location.LocationManager} class exposes a number of methods for applications to receive location updates.  In its simplest form, you register an event listener, identify the location manager from which you'd like to receive location updates, and specify the minimum time and distance intervals at which to receive location updates.  The {@link android.location.LocationListener#onLocationChanged(android.location.Location) onLocationChanged()} callback will be invoked with the frequency that correlates with time and distance intervals.</p>
     49 
     50 <p>
     51 In the sample code snippet below, the location listener is set up to receive notifications at least every 10 seconds and if the device moves by more than 10 meters.  The other callback methods notify the application any status change coming from the location provider.
     52 </p>
     53 
     54 <pre>
     55 private final LocationListener listener = new LocationListener() {
     56 
     57     &#064;Override
     58     public void onLocationChanged(Location location) {
     59         // A new location update is received.  Do something useful with it.  In this case,
     60         // we're sending the update to a handler which then updates the UI with the new
     61         // location.
     62         Message.obtain(mHandler,
     63                 UPDATE_LATLNG,
     64                 location.getLatitude() + ", " +
     65                 location.getLongitude()).sendToTarget();
     66 
     67             ...
     68         }
     69     ...
     70 };
     71 
     72 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
     73         10000,          // 10-second interval.
     74         10,             // 10 meters.
     75         listener);
     76 </pre>
     77 
     78 <h2 id="TaskHandleLocationUpdates">Handle Multiple Sources of Location Updates</h2>
     79 
     80 <p>Generally speaking, a location provider with greater accuracy (GPS) requires a longer fix time than one with lower accuracy (network-based).  If you want to display location data as quickly as possible and update it as more accurate data becomes available, a common practice is to register a location listener with both GPS and network providers.  In the {@link android.location.LocationListener#onLocationChanged(android.location.Location) onLocationChanged()} callback, you'll receive location updates from multiple location providers that may have different timestamps and varying levels of accuracy.  You'll need to incorporate logic to disambiguate the location providers and discard updates that are stale and less accurate.  The code snippet below demonstrates a sample implementation of this logic.</p>
     81 
     82 <pre>
     83 private static final int TWO_MINUTES = 1000 * 60 * 2;
     84 
     85 /** Determines whether one Location reading is better than the current Location fix
     86   * @param location  The new Location that you want to evaluate
     87   * @param currentBestLocation  The current Location fix, to which you want to compare the new one
     88   */
     89 protected boolean isBetterLocation(Location location, Location currentBestLocation) {
     90     if (currentBestLocation == null) {
     91         // A new location is always better than no location
     92         return true;
     93     }
     94 
     95     // Check whether the new location fix is newer or older
     96     long timeDelta = location.getTime() - currentBestLocation.getTime();
     97     boolean isSignificantlyNewer = timeDelta &gt; TWO_MINUTES;
     98     boolean isSignificantlyOlder = timeDelta &lt; -TWO_MINUTES;
     99     boolean isNewer = timeDelta > 0;
    100 
    101     // If it's been more than two minutes since the current location, use the new location
    102     // because the user has likely moved
    103     if (isSignificantlyNewer) {
    104         return true;
    105     // If the new location is more than two minutes older, it must be worse
    106     } else if (isSignificantlyOlder) {
    107         return false;
    108     }
    109 
    110     // Check whether the new location fix is more or less accurate
    111     int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    112     boolean isLessAccurate = accuracyDelta &gt; 0;
    113     boolean isMoreAccurate = accuracyDelta &lt; 0;
    114     boolean isSignificantlyLessAccurate = accuracyDelta &gt; 200;
    115 
    116     // Check if the old and new location are from the same provider
    117     boolean isFromSameProvider = isSameProvider(location.getProvider(),
    118             currentBestLocation.getProvider());
    119 
    120     // Determine location quality using a combination of timeliness and accuracy
    121     if (isMoreAccurate) {
    122         return true;
    123     } else if (isNewer &amp;&amp; !isLessAccurate) {
    124         return true;
    125     } else if (isNewer &amp;&amp; !isSignificantlyLessAccurate &amp;&amp; isFromSameProvider) {
    126         return true;
    127     }
    128     return false;
    129 }
    130 
    131 /** Checks whether two providers are the same */
    132 private boolean isSameProvider(String provider1, String provider2) {
    133     if (provider1 == null) {
    134       return provider2 == null;
    135     }
    136     return provider1.equals(provider2);
    137 }
    138 </pre>
    139 
    140 <h2 id="TaskGetLastKnownLocation">Use getLastKnownLocation() Wisely</h2>
    141 
    142 <p>The setup time for getting a reasonable location fix may not be acceptable for certain applications.  You should consider calling the {@link android.location.LocationManager#getLastKnownLocation(java.lang.String) getLastKnownLocation()} method which simply queries Android for the last location update previously received by any location providers.  Keep in mind that the returned location may be stale.  You should check the timestamp and accuracy of the returned location and decide whether it is useful for your application.  If you elect to discard the location update returned from {@link android.location.LocationManager#getLastKnownLocation(java.lang.String) getLastKnownLocation()} and wait for fresh updates from the location provider(s), you should consider displaying an appropriate message before location data is received.</p>
    143 
    144 <h2 id="TaskTerminateUpdates">Terminate Location Updates</h2>
    145 
    146 <p>When you are done with using location data, you should terminate location update to reduce
    147 unnecessary consumption of power and network bandwidth.  For example, if the user navigates away
    148 from an activity where location updates are displayed, you should stop location update by calling
    149 {@link android.location.LocationManager#removeUpdates(android.location.LocationListener)
    150 removeUpdates()} in {@link android.app.Activity#onStop()}.  ({@link android.app.Activity#onStop()}
    151 is called when the activity is no longer visible.  If you want to learn more about activity
    152 lifecycle, read up on the <a
    153 href="{@docRoot}training/basics/activity-lifecycle/stopping.html">Stopping and Restarting an
    154 Activity</a> lesson.</p>
    155 
    156 <pre>
    157 protected void onStop() {
    158     super.onStop();
    159     mLocationManager.removeUpdates(listener);
    160 }
    161 </pre>
    162 
    163 <p class="note"><strong>Note:</strong> For applications that need to continuously receive and process location updates like a near-real time mapping application, it is best to incorporate the location update logic in a background service and make use of the system notification bar to make the user aware that location data is being used.</p>