Chapter 32

Accessing Location-Based Services

A popular feature on current mobile devices is GPS capability, so the device can tell you where you are at any point in time. While the most common uses of GPS services are for mapping and getting directions, there are other things you can do if you know your location. For example, you might set up a dynamic chat application based on physical location, so you're chatting with those people who are nearest to you. Or you could automatically geo-tag posts to Twitter or similar services.

GPS is not the only way a mobile device can identify your location. Alternatives include the following:

  • The European equivalent to GPS, called Galileo, which is still under development at the time of this writing
  • Cell tower triangulation, where your position is determined based on signal strength to nearby cell towers
  • Proximity to public Wi-Fi hotspots that have known geographic locations

Android devices may have one or more of these services available to them. You, as a developer, can ask the device for your location, plus details on which providers are available. There are even ways for you to simulate your location in the emulator, for use in testing your location-enabled applications.

Location Providers: They Know Where You're Hiding

Android devices can have access to several different means of determining your location. Some will have better accuracy than others. Some may be free, while others may have a cost associated with them. Some may be able to tell you more than just your current position, such as your elevation over sea level or your current speed.

Android has abstracted all this out into a set of LocationProvider objects. Your Android environment will have zero or more LocationProvider instances: one for each distinct locating service that is available on the device. Providers know not only your location, but also are aware of their own characteristics, in terms of accuracy, cost, and so on.

You, as a developer, will use a LocationManager, which holds the LocationProvider set, to figure out which LocationProvider is right for your particular circumstance. You will also need a permission in your application, or the various location APIs will fail due to a security violation. Depending on which location providers you wish to use, you may need ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION, or both. (Permissions are discussed in Chapter 28.)

Finding Yourself

The obvious thing to do with a location service is to figure out where you are right now.

To determine your current location, first you need to get a LocationManager—call getSystemService(LOCATION_SERVICE) from your activity or service and cast it to be a LocationManager.

The next step is to get the name of the LocationProvider you want to use. Here, you have two main options:

  • Ask the user to pick a provider.
  • Find the best-match provider based on a set of criteria.

If you want the user to pick a provider, calling getProviders() on the LocationManager will give you a List of providers, which you can then present to the user for selection.

Alternatively, you can create and populate a Criteria object, stating the particulars of what you want out of a LocationProvider. Here are some of the criteria you can specify:

  • setAltitudeRequired(): Indicates whether or not you need the current altitude.
  • setAccuracy(): Sets a minimum level of accuracy, in meters, for the position.
  • setCostAllowed(): Controls if the provider must be free or if it can incur a cost on behalf of the device user.

Given a filled-in Critieria object, call getBestProvider() on your LocationManager. Android will sift through the criteria and give you the best answer. Note that not all of your criteria may be met. All but the monetary cost criterion might be relaxed if nothing matches.

You are also welcome to hardwire in a LocationProvider name (e.g., GPS_PROVIDER), perhaps just for testing purposes.

Once you know the name of the LocationProvider, you can call getLastKnownPosition() to find out where you were recently. Note that “recently” might be fairly out of date (e.g., the phone was turned off) or even null if there has been no location recorded for that provider yet. Calling getLastKnownPosition() incurs no monetary or power cost, since the provider does not need to be activated to get the value.

This method returns a Location object, which can give you the latitude and longitude of the device in degrees as a Java double. If the particular location provider offers other data, you can get at that as well:

  • For altitude, hasAltitude() will tell you if there is an altitude value, and getAltitude() will return the altitude in meters.
  • For bearing (i.e., compass-style direction), hasBearing() will tell you if there is a bearing available, and getBearing() will return it as degrees east of true north.
  • For speed, hasSpeed() will tell you if the speed is known and getSpeed() will return the speed in meters per second.

A more likely approach to getting the Location from a LocationProvider, though, is to register for updates, as described in the next section.

On the Move

Not all location providers are necessarily immediately responsive. GPS, for example, requires activating a radio and getting a fix from the satellites before you get a location. That is why Android does not offer a getMeMyCurrentLocationNow() method. Combine that with the fact that your users may want their movements to be reflected in your application, and you are probably best off registering for location updates and using that as your means of getting the current location.

The Weather and WeatherPlus sample applications show how to register for updates: call requestLocationUpdates() on your LocationManager instance. This method takes four parameters:

  • The name of the location provider you wish to use
  • How long, in milliseconds, must have elapsed before you might get a location update
  • How far, in meters, the device must have moved before you might get a location update
  • A LocationListener that will be notified of key location-related events

Here's an example of a LocationListener:

LocationListener onLocationChange=new LocationListener() {
  public void onLocationChanged(Location location) {
    updateForecast(location);
  }

  public void onProviderDisabled(String provider) {
    // required for interface, not used
  }

  public void onProviderEnabled(String provider) {
    // required for interface, not used
  }

  public void onStatusChanged(String provider, int status,
                               Bundle extras) {
    // required for interface, not used
  }
};

Here, all we do is call updateForecast() with the Location supplied to the onLocationChanged() callback method. The updateForecast() implementation, as shown in Chapter 29, builds a web page with the current forecast for the location, and sends a broadcast so the activity knows an update is available.

When you no longer need the updates, call removeUpdates() with the LocationListener you registered. If you fail to do this, your application will continue receiving location updates even after all activities and such are closed up, which will also prevent Android from reclaiming your application's memory.

Are We There Yet? Are We There Yet? Are We There Yet?

Sometimes, you are not interested in where you are now, or even when you move, but want to know when you get to where you're going. This could be an end destination, or it could be getting to the next step on a set of directions, so you can give the user the next instruction.

To accomplish this, LocationManager offers addProximityAlert(). This registers an PendingIntent, which will be fired off when the device gets within a certain distance of a certain location. The addProximityAlert() method takes the following as parameters:

  • The latitude and longitude of the position of interest
  • A radius, specifying how close you should be to that position for the Intent to be raised
  • A duration for the registration, in milliseconds (after this period, the registration automatically lapses); a value of -1 means the registration lasts until you manually remove it via removeProximityAlert()
  • The PendingIntent to be raised when the device is within the target zone expressed by the position and radius

Note that it is not guaranteed that you will actually receive an Intent. There may be in an interruption in location services, or the device may not be in the target zone during the period of time the proximity alert is active. For example, if the position is off by a bit, and the radius is a little too tight, the device might only skirt the edge of the target zone, or it may go by the target zone so quickly that the device's location isn't sampled during that time.

It is up to you to arrange for an activity or intent receiver to respond to the Intent you register with the proximity alert. What you do when the Intent arrives is up to you. For example, you might set up a notification (e.g., vibrate the device), log the information to a content provider, or post a message to a web site.

Note that you will receive the Intent whenever the position is sampled and you are within the target zone, not just upon entering the zone. Hence, you will get the Intent several times—perhaps quite a few times, depending on the size of the target zone and the speed of the device's movement.

Testing…Testing…

The Android emulator does not have the ability to get a fix from GPS, triangulate your position from cell towers, or identify your location by some nearby Wi-Fi signal. So, if you want to simulate a moving device, you will need to have some means of providing mock location data to the emulator.

For whatever reason, this particular area has undergone significant changes as Android itself has evolved. It used to be that you could provide mock location data within your application, which was very handy for demonstration purposes. Alas, those options were removed in Android 1.0.

One likely option for supplying mock location data is the Dalvik Debug Monitor Service (DDMS). This is an external program, separate from the emulator, which can feed the emulator single location points or full routes to traverse, in a few different formats. DDMS is described in greater detail in Chapter 35.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.236.231