Obtaining User Location

Location and Maps:


Obtaining User Location






Knowing where the user is allows your application to be smarter and deliver better information to the user. When developing a location-aware application for Android, you can utilize GPS and Android's Network Location Provider to acquire the user location. Although GPS is most accurate, it only works outdoors, it quickly consumes battery power, and doesn't return the location as quickly as users want. Android's Network Location Provider determines user location using cell tower and Wi-Fi signals, providing location information in a way that works indoors and outdoors, responds faster, and uses less battery power. To obtain the user location in your application, you can use both GPS and the Network Location Provider, or just one.


Challenges in Determining User Location


Obtaining user location from a mobile device can be complicated. There are several reasons why a location reading (regardless of the source) can contain errors and be inaccurate. Some sources of error in the user location include:




  • Multitude of location sources

    GPS, Cell-ID, and Wi-Fi can each provide a clue to users location. Determining which to use and trust is a matter of trade-offs in accuracy, speed, and battery-efficiency.




  • User movement

    Because the user location changes, you must account for movement by re-estimating user location every so often.




  • Varying accuracy

    Location estimates coming from each location source are not consistent in their accuracy. A location obtained 10 seconds ago from one source might be more accurate than the newest location from another or same source.




These problems can make it difficult to obtain a reliable user location reading. This document provides information to help you meet these challenges to obtain a reliable location reading. It also provides ideas that you can use in your application to provide the user with an accurate and responsive geo-location experience.


Requesting Location Updates


Before addressing some of the location errors described above, here is an introduction to how you can obtain user location on Android.


Getting user location in Android works by means of callback. You indicate that you'd like to receive location updates from the LocationManager ("Location Manager") by callingrequestLocationUpdates(), passing it a LocationListener. Your LocationListener must implement several callback methods that the Location Manager calls when the user location changes or when the status of the service changes.


For example, the following code shows how to define a LocationListener and request location updates:


// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}

public void onStatusChanged(String provider, int status, Bundle extras) {}

public void onProviderEnabled(String provider) {}

public void onProviderDisabled(String provider) {}
};

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

The first parameter in requestLocationUpdates() is the type of location provider to use (in this case, the Network Location Provider for cell tower and Wi-Fi based location). You can control the frequency at which your listener receives updates with the second and third parameter—the second is the minimum time interval between notifications and the third is the minimum change in distance between notifications—setting both to zero requests location notifications as frequently as possible. The last parameter is your LocationListener, which receives callbacks for location updates.


To request location updates from the GPS provider, substitute GPS_PROVIDER for NETWORK_PROVIDER. You can also request location updates from both the GPS and the Network Location Provider by calling requestLocationUpdates() twice—once for NETWORK_PROVIDER and once for GPS_PROVIDER.


Requesting User Permissions


In order to receive location updates from NETWORK_PROVIDER or GPS_PROVIDER, you must request user permission by declaring either the ACCESS_COARSE_LOCATION orACCESS_FINE_LOCATION permission, respectively, in your Android manifest file. For example:


<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
</manifest>

Without these permissions, your application will fail at runtime when requesting location updates.


Note: If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for both providers. (Permission for ACCESS_COARSE_LOCATION includes permission only for NETWORK_PROVIDER.)


Defining a Model for the Best Performance


Location-based applications are now commonplace, but due to the less than optimal accuracy, user movement, the multitude of methods to obtain the location, and the desire to conserve battery, getting user location is complicated. To overcome the obstacles of obtaining a good user location while preserving battery power, you must define a consistent model that specifies how your application obtains the user location. This model includes when you start and stop listening for updates and when to use cached location data.


Flow for obtaining user location


Here's the typical flow of procedures for obtaining the user location:



  1. Start application.

  2. Sometime later, start listening for updates from desired location providers.

  3. Maintain a "current best estimate" of location by filtering out new, but less accurate fixes.

  4. Stop listening for location updates.

  5. Take advantage of the last best location estimate.


Figure 1 demonstrates this model in a timeline that visualizes the period in which an application is listening for location updates and the events that occur during that time.





Figure 1. A timeline representing the window in which an application listens for location updates.


This model of a window—during which location updates are received—frames many of the decisions you need to make when adding location-based services to your application.


Deciding when to start listening for updates


You might want to start listening for location updates as soon as your application starts, or only after users activate a certain feature. Be aware that long windows of listening for location fixes can consume a lot of battery power, but short periods might not allow for sufficient accuracy.


As demonstrated above, you can begin listening for updates by calling requestLocationUpdates():


LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
// Or, use GPS location data:
// LocationProvider locationProvider = LocationManager.GPS_PROVIDER;

locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);

Getting a fast fix with the last known location


The time it takes for your location listener to receive the first location fix is often too long for users wait. Until a more accurate location is provided to your location listener, you should utilize a cached location by calling getLastKnownLocation(String):


LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
// Or use LocationManager.GPS_PROVIDER

Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);

Deciding when to stop listening for updates


The logic of deciding when new fixes are no longer necessary might range from very simple to very complex depending on your application. A short gap between when the location is acquired and when the location is used, improves the accuracy of the estimate. Always beware that listening for a long time consumes a lot of battery power, so as soon as you have the information you need, you should stop listening for updates by calling removeUpdates(PendingIntent):


// Remove the listener you previously added
locationManager.removeUpdates(locationListener);



Maintaining a current best estimate


You might expect that the most recent location fix is the most accurate. However, because the accuracy of a location fix varies, the most recent fix is not always the best. You should include logic for choosing location fixes based on several criteria. The criteria also varies depending on the use-cases of the application and field testing.


Here are a few steps you can take to validate the accuracy of a location fix:



  • Check if the location retrieved is significantly newer than the previous estimate.

  • Check if the accuracy claimed by the location is better or worse than the previous estimate.

  • Check which provider the new location is from and determine if you trust it more.




An elaborate example of this logic can look something like this:


private static final int TWO_MINUTES = 1000 * 60 * 2;

/** Determines whether one Location reading is better than the current Location fix
* @param location The new Location that you want to evaluate
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}

// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;

// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}

// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate =






مواضيع متعلقة


اهم الفاعليات لهذا الشهر


الشبكات الإجتماعية

تغريدات تويتر