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