• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Location Strategies
2excludeFromSuggestions=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
50better information to the user. When developing a location-aware application for Android, you can
51utilize GPS and Android's Network Location Provider to acquire the user location. Although
52GPS is most accurate, it only works outdoors, it quickly consumes battery power, and doesn't return
53the location as quickly as users want. Android's Network Location Provider determines user location
54using cell tower and Wi-Fi signals, providing location information in a way that
55works indoors and outdoors, responds faster, and uses less battery power. To obtain the user
56location in your application, you can use both GPS and the Network Location Provider, or just
57one.</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
63why a location reading (regardless of the source) can contain errors and be inaccurate.
64Some 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
69and 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
73location 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
77accuracy. A location obtained 10 seconds ago from one source might be more accurate than the newest
78location 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
83document provides information to help you meet these challenges to obtain a reliable location
84reading. It also provides ideas that you can use in your
85application 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
91how 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
94like to receive location updates from the {@link android.location.LocationManager} ("Location
95Manager") by calling {@link android.location.LocationManager#requestLocationUpdates
96requestLocationUpdates()}, passing it a
97{@link android.location.LocationListener}. Your {@link android.location.LocationListener} must
98implement several callback methods that the Location Manager calls when the user location
99changes 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}
102and request location updates:
103  </p>
104
105<pre>
106// Acquire a reference to the system Location Manager
107LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
108
109// Define a listener that responds to location updates
110LocationListener 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
124locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
125</pre>
126
127  <p>The first parameter in {@link
128android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} is the type of
129location provider to use (in this case, the Network Location Provider for cell tower and Wi-Fi
130based location). You can control the frequency at which your listener receives updates
131with the second and third parameter&mdash;the second is the minimum time interval between
132notifications and the third is the minimum change in distance between notifications&mdash;setting
133both 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
137android.location.LocationManager#GPS_PROVIDER} instead of {@link
138android.location.LocationManager#NETWORK_PROVIDER}. You can also request
139location updates from both the GPS and the Network Location Provider by calling
140{@link android.location.LocationManager#requestLocationUpdates
141requestLocationUpdates()} twice&mdash;once for {@link
142android.location.LocationManager#NETWORK_PROVIDER} and once for {@link
143android.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&lt;manifest ... &gt;
191    &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
192    ...
193    &lt;!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --&gt;
194    &lt;uses-feature android:name="android.hardware.location.gps" /&gt;
195    ...
196&lt;/manifest&gt;
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
202accuracy, user movement, the multitude of methods to obtain the location, and the desire to conserve
203battery, getting user location is complicated. To overcome the obstacles of obtaining a good user
204location while preserving battery power, you must define a consistent model that specifies how your
205application obtains the user location. This model includes when you start and stop listening for
206updates 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
217fixes.</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
223application 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
227application listens for location updates.</p>
228
229  <p>This model of a window&mdash;during which location updates are received&mdash;frames many of
230the 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
236only after users activate a certain feature. Be aware that long windows of listening for location
237fixes can consume a lot of battery power, but short periods might not allow for sufficient
238accuracy.</p>
239
240  <p>As demonstrated above, you can begin listening for updates by calling {@link
241android.location.LocationManager#requestLocationUpdates requestLocationUpdates()}:</p>
242
243<pre>
244String locationProvider = LocationManager.NETWORK_PROVIDER;
245// Or, use GPS location data:
246// String locationProvider = LocationManager.GPS_PROVIDER;
247
248locationManager.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
255long for users wait. Until a more accurate location is provided to your location listener, you
256should utilize a cached location by calling {@link
257android.location.LocationManager#getLastKnownLocation}:</p>
258<pre>
259String locationProvider = LocationManager.NETWORK_PROVIDER;
260// Or use LocationManager.GPS_PROVIDER
261
262Location 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
269very complex depending on your application. A short gap between when the location is acquired and
270when the location is used, improves the accuracy of the estimate. Always beware that listening for a
271long time consumes a lot of battery power, so as soon as you have the information you need, you
272should stop
273listening for updates by calling {@link android.location.LocationManager#removeUpdates}:</p>
274<pre>
275// Remove the listener you previously added
276locationManager.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.
283However, because the accuracy of a location fix varies, the most recent fix is not always the best.
284You should include logic for choosing location fixes based on several criteria. The criteria also
285varies 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
291estimate.</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>
298private 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  */
304protected 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 &gt; TWO_MINUTES;
313    boolean isSignificantlyOlder = timeDelta &lt; -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 &gt; 0;
328    boolean isMoreAccurate = accuracyDelta &lt; 0;
329    boolean isSignificantlyLessAccurate = accuracyDelta &gt; 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 &amp;&amp; !isLessAccurate) {
339        return true;
340    } else if (isNewer &amp;&amp; !isSignificantlyLessAccurate &amp;&amp; isFromSameProvider) {
341        return true;
342    }
343    return false;
344}
345
346/** Checks whether two providers are the same */
347private 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
359good performance needs some adjustment. Here are some things you might change to find a good
360balance 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
365network location services, thus, preserving battery life. But it also allows for fewer locations
366from 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
371efficiency, but at the cost of accuracy. The value of the trade-off depends on how your
372application is used. You can reduce the rate of updates by increasing the parameters in {@link
373android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} that specify the
374interval 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,
379you might choose to use only the Network Location Provider or only GPS, instead of both. Interacting
380with 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
386are a couple scenarios in which you can use the user location to enrich your application. Each
387scenario also describes good practices for when you should start and stop listening for the
388location, 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.
394Think of users sharing their local experiences, posting a review for a restaurant, or recording some
395content that can be augmented with their current location. A model of how this
396interaction 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
400the 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
403best location accuracy, you might choose to start listening for location updates when users begin
404creating
405the content or even when the application starts, then stop listening for updates when content is
406ready to be posted or recorded. You might need to consider how long a typical task of creating the
407content 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
413of options about where to go. For example, you're looking to provide a list of nearby restaurants,
414stores, and entertainment and the order of recommendations changes depending on the user
415location.</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
427dynamic 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
435user location works. This is most easily done using a real Android-powered device. If, however, you
436don't have a device, you can still test your location-based features by mocking location data in
437the Android emulator. There are three different ways to send your application mock location
438data: 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
441as GPS location data, so you must request location updates from {@link
442android.location.LocationManager#GPS_PROVIDER} in order for mock location data
443to work.</p>
444
445<h3 id="MockAVD">Using Android Studio</h3>
446
447<p>Select <b>Tools</b> &gt; <b>Android</b> &gt; <b>AVD Manager</b>. In the Android Virtual
448Device Manager window, choose your AVD and launch it in the emulator by selecting the green
449play arrow in the Actions column.</p>
450
451<p>Then, select <b>Tools</b> &gt; <b>Android</b> &gt; <b>Android Device Monitor</b>.
452Select the Emulator Control tab in the Android Device Monitor window, and enter GPS coordinates
453under Location Controls as individual lat/long coordinates, with a GPX file for route playback,
454or 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>&lt;console-port&gt;</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