Home | History | Annotate | Download | only in location
      1 page.title=Obtaining User Location
      2 parent.title=Location and Maps
      3 parent.link=index.html
      4 @jd:body
      5 
      6 <div id="qv-wrapper">
      7 <div id="qv">
      8 
      9   <h2>Quickview</h2>
     10   <ul>
     11     <li>The Network Location Provider provides good location data without using GPS</li>
     12     <li>Obtaining user location can consume a lot of battery, so be careful how
     13 long you listen for updates</li>
     14   </ul>
     15   <h2>In this document</h2>
     16   <ol>
     17     <li><a href="#Challenges">Challenges in Determining User Location</a></li>
     18     <li><a href="#Updates">Requesting Location Updates</a>
     19       <ol>
     20         <li><a href="#Permission">Requesting User Permissions</a></li>
     21       </ol>
     22     </li>
     23     <li><a href="#BestPerformance">Defining a Model for the Best Performance</a>
     24       <ol>
     25         <li><a href="#Flow">Flow for obtaining user location</a></li>
     26         <li><a href="#StartListening">Deciding when to start listening for updates</a></li>
     27         <li><a href="#FastFix">Getting a fast fix with the last known location</a></li>
     28         <li><a href="#StopListening">Deciding when to stop listening for updates</a></li>
     29         <li><a href="#BestEstimate">Maintaining a current best estimate</a></li>
     30         <li><a href="#Adjusting">Adjusting the model to save battery and data exchange</a></li>
     31       </ol>
     32     </li>
     33     <li><a href="#MockData">Providing Mock Location Data</a></li>
     34   </ol>
     35   <h2>Key classes</h2>
     36   <ol>
     37     <li>{@link android.location.LocationManager}</li>
     38     <li>{@link android.location.LocationListener}</li>
     39   </ol>
     40 </div>
     41 </div>
     42 
     43   <p>Knowing where the user is allows your application to be smarter and deliver
     44 better information to the user. When developing a location-aware application for Android, you can
     45 utilize GPS and Android's Network Location Provider to acquire the user location. Although
     46 GPS is most accurate, it only works outdoors, it quickly consumes battery power, and doesn't return
     47 the location as quickly as users want. Android's Network Location Provider determines user location
     48 using cell tower and Wi-Fi signals, providing location information in a way that
     49 works indoors and outdoors, responds faster, and uses less battery power. To obtain the user
     50 location in your application, you can use both GPS and the Network Location Provider, or just
     51 one.</p>
     52 
     53 
     54 <h2 id="Challenges">Challenges in Determining User Location</h2>
     55 
     56 <p>Obtaining user location from a mobile device can be complicated. There are several reasons
     57 why a location reading (regardless of the source) can contain errors and be inaccurate.
     58 Some sources of error in the user location include:</p>
     59 
     60 <ul>
     61   <li><b>Multitude of location sources</b>
     62     <p>GPS, Cell-ID, and Wi-Fi can each provide a clue to users location. Determining which to use
     63 and trust is a matter of trade-offs in accuracy, speed, and battery-efficiency.</p>
     64   </li>
     65   <li><b>User movement</b>
     66     <p>Because the user location changes, you must account for movement by re-estimating user
     67 location every so often.</p>
     68   </li>
     69   <li><b>Varying accuracy</b>
     70     <p>Location estimates coming from each location source are not consistent in their
     71 accuracy. A location obtained 10 seconds ago from one source might be more accurate than the newest
     72 location from another or same source.</p>
     73   </li>
     74 </ul>
     75 
     76   <p>These problems can make it difficult to obtain a reliable user location reading. This
     77 document provides information to help you meet these challenges to obtain a reliable location
     78 reading. It also provides ideas that you can use in your
     79 application to provide the user with an accurate and responsive geo-location experience.</p>
     80 
     81 
     82 <h2 id="Updates">Requesting Location Updates</h2>
     83 
     84   <p>Before addressing some of the location errors described above, here is an introduction to
     85 how you can obtain user location on Android.</p>
     86 
     87   <p>Getting user location in Android works by means of callback. You indicate that you'd
     88 like to receive location updates from the {@link android.location.LocationManager} ("Location
     89 Manager") by calling {@link android.location.LocationManager#requestLocationUpdates
     90 requestLocationUpdates()}, passing it a
     91 {@link android.location.LocationListener}. Your {@link android.location.LocationListener} must
     92 implement several callback methods that the Location Manager calls when the user location
     93 changes or when the status of the service changes.</p>
     94 
     95 <p>For example, the following code shows how to define a {@link android.location.LocationListener}
     96 and request location updates:
     97   </p>
     98 
     99 <pre>
    100 // Acquire a reference to the system Location Manager
    101 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    102 
    103 // Define a listener that responds to location updates
    104 LocationListener locationListener = new LocationListener() {
    105     public void onLocationChanged(Location location) {
    106       // Called when a new location is found by the network location provider.
    107       makeUseOfNewLocation(location);
    108     }
    109 
    110     public void onStatusChanged(String provider, int status, Bundle extras) {}
    111 
    112     public void onProviderEnabled(String provider) {}
    113 
    114     public void onProviderDisabled(String provider) {}
    115   };
    116 
    117 // Register the listener with the Location Manager to receive location updates
    118 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
    119 </pre>
    120 
    121   <p>The first parameter in {@link
    122 android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} is the type of
    123 location provider to use (in this case, the Network Location Provider for cell tower and Wi-Fi
    124 based location). You can control the frequency at which your listener receives updates
    125 with the second and third parameter&mdash;the second is the minimum time interval between
    126 notifications and the third is the minimum change in distance between notifications&mdash;setting
    127 both to zero requests location notifications as frequently as possible. The last parameter is your
    128 {@link android.location.LocationListener}, which receives callbacks for location updates.</p>
    129 
    130 <p>To request location updates from the GPS provider,
    131 substitute <code>GPS_PROVIDER</code> for <code>NETWORK_PROVIDER</code>. You can also request
    132 location updates from both the GPS and the Network Location Provider by calling {@link
    133 android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} twice&mdash;once
    134 for <code>NETWORK_PROVIDER</code> and once for <code>GPS_PROVIDER</code>.</p>
    135 
    136 
    137 <h3 id="Permission">Requesting User Permissions</h3>
    138 
    139 <p>In order to receive location updates from <code>NETWORK_PROVIDER</code> or
    140 <code>GPS_PROVIDER</code>, you must request user permission by declaring either the {@code
    141 ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permission, respectively, in your Android
    142 manifest file. For example:</p>
    143 
    144 <pre>
    145 &lt;manifest ... &gt;
    146     &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
    147     ...
    148 &lt;/manifest&gt;
    149 </pre>
    150 
    151 <p>Without these permissions, your application will fail at runtime when requesting
    152 location updates.</p>
    153 
    154 <p class="note"><strong>Note:</strong> If you are using both <code>NETWORK_PROVIDER</code> and
    155 <code>GPS_PROVIDER</code>, then you need to request only the {@code ACCESS_FINE_LOCATION}
    156 permission, because it includes permission for both providers. (Permission for {@code
    157 ACCESS_COARSE_LOCATION} includes permission only for <code>NETWORK_PROVIDER</code>.)</p>
    158 
    159 
    160 <h2 id="BestPerformance">Defining a Model for the Best Performance</h2>
    161 
    162   <p>Location-based applications are now commonplace, but due to the less than optimal
    163 accuracy, user movement, the multitude of methods to obtain the location, and the desire to conserve
    164 battery, getting user location is complicated. To overcome the obstacles of obtaining a good user
    165 location while preserving battery power, you must define a consistent model that specifies how your
    166 application obtains the user location. This model includes when you start and stop listening for
    167 updates and when to use cached location data.</p>
    168 
    169 
    170   <h3 id="Flow">Flow for obtaining user location</h3>
    171 
    172   <p>Here's the typical flow of procedures for obtaining the user location:</p>
    173 
    174   <ol>
    175     <li>Start application.</li>
    176     <li>Sometime later, start listening for updates from desired location providers.</li>
    177     <li>Maintain a "current best estimate" of location by filtering out new, but less accurate
    178 fixes.</li>
    179     <li>Stop listening for location updates.</li>
    180     <li>Take advantage of the last best location estimate.</li>
    181   </ol>
    182 
    183   <p>Figure 1 demonstrates this model in a timeline that visualizes the period in which an
    184 application is listening for location updates and the events that occur during that time.</p>
    185 
    186 <img src="{@docRoot}images/location/getting-location.png" alt="" />
    187 <p class="img-caption"><strong>Figure 1.</strong> A timeline representing the window in which an
    188 application listens for location updates.</p>
    189     
    190   <p>This model of a window&mdash;during which location updates are received&mdash;frames many of
    191 the decisions you need to make when adding location-based services to your application.</p>
    192 
    193 
    194   <h3 id="StartListening">Deciding when to start listening for updates</h3>
    195 
    196   <p>You might want to start listening for location updates as soon as your application starts, or
    197 only after users activate a certain feature. Be aware that long windows of listening for location
    198 fixes can consume a lot of battery power, but short periods might not allow for sufficient
    199 accuracy.</p>
    200 
    201   <p>As demonstrated above, you can begin listening for updates by calling {@link
    202 android.location.LocationManager#requestLocationUpdates requestLocationUpdates()}:</p>
    203 
    204 <pre>
    205 LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
    206 // Or, use GPS location data:
    207 // LocationProvider locationProvider = LocationManager.GPS_PROVIDER;
    208 
    209 locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
    210 </pre>
    211 
    212 
    213   <h3 id="FastFix">Getting a fast fix with the last known location</h3>
    214   
    215   <p>The time it takes for your location listener to receive the first location fix is often too
    216 long for users wait. Until a more accurate location is provided to your location listener, you
    217 should utilize a cached location by calling {@link
    218 android.location.LocationManager#getLastKnownLocation}:</p>
    219 <pre>
    220 LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
    221 // Or use LocationManager.GPS_PROVIDER
    222 
    223 Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
    224 </pre>
    225 
    226 
    227   <h3 id="StopListening">Deciding when to stop listening for updates</h3>
    228   
    229   <p>The logic of deciding when new fixes are no longer necessary might range from very simple to
    230 very complex depending on your application. A short gap between when the location is acquired and
    231 when the location is used, improves the accuracy of the estimate. Always beware that listening for a
    232 long time consumes a lot of battery power, so as soon as you have the information you need, you
    233 should stop
    234 listening for updates by calling {@link android.location.LocationManager#removeUpdates}:</p>
    235 <pre>
    236 // Remove the listener you previously added
    237 locationManager.removeUpdates(locationListener);
    238 </pre>
    239 
    240 
    241   <h3 id="BestEstimate">Maintaining a current best estimate</h3>
    242 
    243   <p>You might expect that the most recent location fix is the most accurate.
    244 However, because the accuracy of a location fix varies, the most recent fix is not always the best.
    245 You should include logic for choosing location fixes based on several criteria. The criteria also
    246 varies depending on the use-cases of the application and field testing.</p>
    247 
    248   <p>Here are a few steps you can take to validate the accuracy of a location fix:</p>
    249   <ul>
    250     <li>Check if the location retrieved is significantly newer than the previous estimate.</li>
    251     <li>Check if the accuracy claimed by the location is better or worse than the previous
    252 estimate.</li>
    253     <li>Check which provider the new location is from and determine if you trust it more.</li>
    254   </ul>
    255   
    256   <p>An elaborate example of this logic can look something like this:</p>
    257 
    258 <pre>
    259 private static final int TWO_MINUTES = 1000 * 60 * 2;
    260 
    261 /** Determines whether one Location reading is better than the current Location fix
    262   * @param location  The new Location that you want to evaluate
    263   * @param currentBestLocation  The current Location fix, to which you want to compare the new one
    264   */
    265 protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    266     if (currentBestLocation == null) {
    267         // A new location is always better than no location
    268         return true;
    269     }
    270 
    271     // Check whether the new location fix is newer or older
    272     long timeDelta = location.getTime() - currentBestLocation.getTime();
    273     boolean isSignificantlyNewer = timeDelta &gt; TWO_MINUTES;
    274     boolean isSignificantlyOlder = timeDelta &lt; -TWO_MINUTES;
    275     boolean isNewer = timeDelta > 0;
    276 
    277     // If it's been more than two minutes since the current location, use the new location
    278     // because the user has likely moved
    279     if (isSignificantlyNewer) {
    280         return true;
    281     // If the new location is more than two minutes older, it must be worse
    282     } else if (isSignificantlyOlder) {
    283         return false;
    284     }
    285 
    286     // Check whether the new location fix is more or less accurate
    287     int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    288     boolean isLessAccurate = accuracyDelta &gt; 0;
    289     boolean isMoreAccurate = accuracyDelta &lt; 0;
    290     boolean isSignificantlyLessAccurate = accuracyDelta &gt; 200;
    291 
    292     // Check if the old and new location are from the same provider
    293     boolean isFromSameProvider = isSameProvider(location.getProvider(),
    294             currentBestLocation.getProvider());
    295 
    296     // Determine location quality using a combination of timeliness and accuracy
    297     if (isMoreAccurate) {
    298         return true;
    299     } else if (isNewer &amp;&amp; !isLessAccurate) {
    300         return true;
    301     } else if (isNewer &amp;&amp; !isSignificantlyLessAccurate &amp;&amp; isFromSameProvider) {
    302         return true;
    303     }
    304     return false;
    305 }
    306 
    307 /** Checks whether two providers are the same */
    308 private boolean isSameProvider(String provider1, String provider2) {
    309     if (provider1 == null) {
    310       return provider2 == null;
    311     }
    312     return provider1.equals(provider2);
    313 }
    314 </pre>
    315 
    316 
    317   <h3 id="Adjusting">Adjusting the model to save battery and data exchange</h3>
    318 
    319   <p>As you test your application, you might find that your model for providing good location and
    320 good performance needs some adjustment. Here are some things you might change to find a good
    321 balance between the two.</p>
    322 
    323   <h4>Reduce the size of the window</h4>
    324   
    325   <p>A smaller window in which you listen for location updates means less interaction with GPS and
    326 network location services, thus, preserving battery life. But it also allows for fewer locations
    327 from which to choose a best estimate.</p>
    328 
    329   <h4>Set the location providers to return updates less frequently</h4>
    330   
    331   <p>Reducing the rate at which new updates appear during the window can also improve battery
    332 efficiency, but at the cost of accuracy. The value of the trade-off depends on how your
    333 application is used. You can reduce the rate of updates by increasing the parameters in {@link
    334 android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} that specify the
    335 interval time and minimum distance change.</p>
    336 
    337   <h4>Restrict a set of providers</h4>
    338   
    339   <p>Depending on the environment where your application is used or the desired level of accuracy,
    340 you might choose to use only the Network Location Provider or only GPS, instead of both. Interacting
    341 with only one of the services reduces battery usage at a potential cost of accuracy.</p>
    342 
    343 
    344   <h2>Common application cases</h2>
    345   
    346   <p>There are many reasons you might want to obtain the user location in your application. Below
    347 are a couple scenarios in which you can use the user location to enrich your application. Each
    348 scenario also describes good practices for when you should start and stop listening for the
    349 location, in order to get a good reading and help preserve battery life.</p>
    350 
    351 
    352   <h3>Tagging user-created content with a location</h3>
    353   
    354   <p>You might be creating an application where user-created content is tagged with a location.
    355 Think of users sharing their local experiences, posting a review for a restaurant, or recording some
    356 content that can be augmented with their current location. A model of how this
    357 interaction might happen, with respect to the location services, is visualized in figure 2.</p>
    358 
    359   <img src="{@docRoot}images/location/content-tagging.png" alt="" />
    360 <p class="img-caption"><strong>Figure 2.</strong> A timeline representing the window in which
    361 the user location is obtained and listening stops when the user consumes the current location.</p>
    362   
    363   <p>This lines up with the previous model of how user location is obtained in code (figure 1). For
    364 best location accuracy, you might choose to start listening for location updates when users begin
    365 creating
    366 the content or even when the application starts, then stop listening for updates when content is
    367 ready to be posted or recorded. You might need to consider how long a typical task of creating the
    368 content takes and judge if this duration allows for efficient collection of a location estimate.</p>
    369 
    370 
    371   <h3>Helping the user decide on where to go</h3>
    372   
    373   <p>You might be creating an application that attempts to provide users with a set
    374 of options about where to go. For example, you're looking to provide a list of nearby restaurants,
    375 stores, and entertainment and the order of recommendations changes depending on the user
    376 location.</p>
    377 
    378   <p>To accommodate such a flow, you might choose to:</p>
    379   <ul>
    380     <li>Rearrange recommendations when a new best estimate is obtained</li>
    381     <li>Stop listening for updates if the order of recommendations has stabilized</li>
    382   </ul>
    383 
    384   <p>This kind of model is visualized in figure 3.</p>
    385   
    386   <img src="{@docRoot}images/location/where-to-go.png" alt="" />
    387 <p class="img-caption"><strong>Figure 3.</strong> A timeline representing the window in which a
    388 dynamic set of data is updated each time the user location updates.</p>
    389 
    390 
    391 
    392 
    393 <h2 id="MockData">Providing Mock Location Data</h2>
    394 
    395 <p>As you develop your application, you'll certainly need to test how well your model for obtaining
    396 user location works. This is most easily done using a real Android-powered device. If, however, you
    397 don't have a device, you can still test your location-based features by mocking location data in
    398 the Android emulator. There are three different ways to send your application mock location
    399 data: using Eclipse, DDMS, or the "geo" command in the emulator console.</p>
    400 
    401 <p class="note"><strong>Note:</strong> Providing mock location data is injected as GPS location
    402 data, so you must request location updates from <code>GPS_PROVIDER</code> in order for mock location
    403 data to work.</p>
    404 
    405 <h3 id="MockEclipse">Using Eclipse</h3>
    406 
    407 <p>Select <b>Window</b> &gt; <b>Show View</b> &gt; <b>Other</b> &gt; <b>Emulator Control</b>.</p>
    408 
    409 <p>In the Emulator Control panel, enter GPS coordinates under Location Controls as individual
    410 lat/long coordinates, with a GPX file for route playback, or a KML file for multiple place marks.
    411 (Be sure that you have a device selected in the Devices panel&mdash;available from <b>Window</b>
    412 &gt; <b>Show View</b> &gt; <b>Other</b> &gt; <b>Devices</b>.)</p>
    413 
    414 
    415 <h3 id="MockDdms">Using DDMS</h3>
    416 
    417 <p>With the DDMS tool, you can simulate location data a few different ways:</p>
    418 <ul>
    419     <li>Manually send individual longitude/latitude coordinates to the device.</li>
    420     <li>Use a GPX file describing a route for playback to the device.</li>
    421     <li>Use a KML file describing individual place marks for sequenced playback to the device.</li>
    422 </ul>
    423 
    424 <p>For more information on using DDMS to spoof location data, see
    425 <a href="{@docRoot}guide/developing/debugging/ddms.html">Using DDMS</a>.
    426 
    427 
    428 <h3 id="MockGeo">Using the "geo" command in the emulator console</h3>
    429 
    430 <p>To send mock location data from the command line:</p>
    431 
    432 <ol>
    433   <li>Launch your application in the Android emulator and open a terminal/console in your SDK's
    434 <code>/tools</code> directory.</li>
    435   <li>Connect to the emulator console:
    436 <pre>telnet localhost <em>&lt;console-port&gt;</em></pre></li>
    437   <li>Send the location data:</p>
    438     <ul><li><code>geo fix</code> to send a fixed geo-location.
    439     <p>This command accepts a longitude and latitude in decimal degrees, and
    440     an optional altitude in meters. For example:</p>
    441     <pre>geo fix -121.45356 46.51119 4392</pre>
    442       </li>
    443       <li><code>geo nmea</code> to send an NMEA 0183 sentence.
    444     <p>This command accepts a single NMEA sentence of type '$GPGGA' (fix data) or '$GPRMC' (transit
    445   data).
    446     For example:</p>
    447     <pre>geo nmea $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62</pre>
    448       </li>
    449     </ul>
    450   </li>
    451 </ol>
    452 
    453 <p>For information about how to connect to the emulator console, see
    454 <a href="{@docRoot}guide/developing/devices/emulator.html#console">Using the Emulator Console</a>.</p>
    455