android Gps Api

Obtaining User Location

Challenges in Determining User Location

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

  • Multitude of location sources

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

  • User movement

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

  • Varying accuracy

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

These problems can make it difficult to obtain a reliableuser location reading. This document provides information to help you meetthese challenges to obtain a reliable location reading. It also provides ideasthat you can use in your application to provide the user with an accurate andresponsive geo-location experience.

Requesting Location Updates

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

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

For example, the following code shows how to define aLocationListener 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 networklocation provider.
      makeUseOfNewLocation(location);
    }

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

    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 cancontrol the frequency at which your listener receives updates with the secondand third parameter—the second is the minimum time interval betweennotifications and the third is the minimum change in distance betweennotifications—setting both to zero requests location notifications asfrequently as possible. The last parameter is yourLocationListener, 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 theGPS and the Network Location Provider by callingrequestLocationUpdates() 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 or ACCESS_FINE_LOCATION permission, respectively, in your Android manifest file.For example:

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

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

Note: Ifyou are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for bothproviders. (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 dueto the less than optimal accuracy, user movement, the multitude of methods toobtain the location, and the desire to conserve battery, getting user locationis complicated. To overcome the obstacles of obtaining a good user locationwhile preserving battery power, you must define a consistent model thatspecifies how your application obtains the user location. This model includeswhen you start and stop listening for updates and when to use cached locationdata.

Flow for obtaining user location

Here's the typical flow of procedures for obtaining theuser 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 visualizesthe period in which an application is listening for location updates and theevents that occur during that time.


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

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

Deciding when to start listening for updates

You might want to start listening for location updates assoon as your application starts, or only after users activate a certainfeature. Be aware that long windows of listening for location fixes can consumea lot of battery power, but short periods might not allow for sufficientaccuracy.

As demonstrated above, you can begin listening forupdates by callingrequestLocationUpdates():

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 receivethe first location fix is often too long for users wait. Until a more accuratelocation is provided to your location listener, you should utilize a cachedlocation 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 longernecessary might range from very simple to very complex depending on yourapplication. A short gap between when the location is acquired and when thelocation is used, improves the accuracy of the estimate. Always beware thatlistening for a long time consumes a lot of battery power, so as soon as youhave the information you need, you should stop listening for updates by callingremoveUpdates(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 themost accurate. However, because the accuracy of a location fix varies, the mostrecent fix is not always the best. You should include logic for choosinglocation fixes based on several criteria. The criteria also varies depending onthe use-cases of the application and field testing.

Here are a few steps you can take to validate theaccuracy 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 somethinglike this:

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

/** Determines whether one Location reading is better than the current Locationfix
  * @param location  The new Location that you want to evaluate
  * @param currentBestLocation  The current Location fix, to whichyou want to compare the new one
  */
protected boolean isBetterLocation(Location location, LocationcurrentBestLocation) {
    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 beworse
    } 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 = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider =isSameProvider(location.getProvider(),
            currentBestLocation.getProvider());

    // Determine location quality using a combination of timelinessand accuracy
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate&& isFromSameProvider) {
        return true;
    }
    return false;
}

/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
    if (provider1 == null) {
      return provider2 == null;
    }
    return provider1.equals(provider2);
}

Adjusting the model to save battery and data exchange

As you test your application, you might find that yourmodel for providing good location and good performance needs some adjustment.Here are some things you might change to find a good balance between the two.

Reduce the size of the window

A smaller window in which you listen for location updatesmeans less interaction with GPS and network location services, thus, preservingbattery life. But it also allows for fewer locations from which to choose a bestestimate.

Set the location providers to return updates lessfrequently

Reducing the rate at which new updates appear during thewindow can also improve battery efficiency, but at the cost of accuracy. Thevalue of the trade-off depends on how your application is used. You can reducethe rate of updates by increasing the parameters in requestLocationUpdates() that specify the interval time and minimum distancechange.

Restrict a set of providers

Depending on the environment where your application isused or the desired level of accuracy, you might choose to use only the NetworkLocation Provider or only GPS, instead of both. Interacting with only one ofthe services reduces battery usage at a potential cost of accuracy.

Common application cases

There are many reasons you might want to obtain the userlocation in your application. Below are a couple scenarios in which you can usethe user location to enrich your application. Each scenario also describes goodpractices for when you should start and stop listening for the location, inorder to get a good reading and help preserve battery life.

Tagging user-created content with a location

You might be creating an application where user-createdcontent is tagged with a location. Think of users sharing their localexperiences, posting a review for a restaurant, or recording some content thatcan be augmented with their current location. A model of how this interactionmight happen, with respect to the location services, is visualized in figure 2.


Figure 2. A timeline representing the window in which the user location is obtainedand listening stops when the user consumes the current location.

This lines up with the previous model of how userlocation is obtained in code (figure 1). For best location accuracy, you mightchoose to start listening for location updates when users begin creating thecontent or even when the application starts, then stop listening for updateswhen content is ready to be posted or recorded. You might need to consider howlong a typical task of creating the content takes and judge if this duration allowsfor efficient collection of a location estimate.

Helping the user decide on where to go

You might be creating an application that attempts toprovide users with a set of options about where to go. For example, you'relooking to provide a list of nearby restaurants, stores, and entertainment andthe order of recommendations changes depending on the user location.

To accommodate such a flow, you might choose to:

  • Rearrange recommendations when a new best estimate is obtained
  • Stop listening for updates if the order of recommendations has stabilized

This kind of model is visualized in figure 3.

 

Figure 3. A timeline representing the window in which a dynamic set of data isupdated each time the user location updates.

Providing Mock Location Data

As you develop your application, you'll certainly need totest how well your model for obtaining user location works. This is most easilydone using a real Android-powered device. If, however, you don't have a device,you can still test your location-based features by mocking location data in theAndroid emulator. There are three different ways to send your application mocklocation data: using Eclipse, DDMS, or the "geo" command in theemulator console.

Note:Providing mock location data is injected as GPS location data, so you mustrequest location updates from GPS_PROVIDER in order for mock location data to work.

Using Eclipse

Select Window > Show View > Other> Emulator Control.

In the Emulator Control panel, enter GPS coordinatesunder Location Controls as individual lat/long coordinates, with a GPX file forroute playback, or a KML file for multiple place marks. (Be sure that you havea device selected in the Devices panel—available from Window > ShowView >Other > Devices.)

Using DDMS

With the DDMS tool, you can simulate location data a fewdifferent ways:

  • Manually send individual longitude/latitude coordinates to the device.
  • Use a GPX file describing a route for playback to the device.
  • Use a KML file describing individual place marks for sequenced playback to the device.

For more information on using DDMS to spoof locationdata, seeUsing DDMS.

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值