[Android Software Development] michael.the.don:
[Ultimate Guide][Part 8 released][20/09/2011]Android App Development - From Scratch

PART VIII

Using Location-Based Services

Location-based services (LBS) is an umbrella term used to describe the different technologies used to find the device’s current location. The two main LBS elements are:

❑ LocationManager Provides hooks to the location-based services.

❑ LocationProviders Each of which represents a different location-finding technology used to determine the device’s current location.

Selecting a Location Provider

Depending on the device, there may be several technologies that Android can use to determine the current location. Each technology, or Location Provider, will offer different capabilities including power consumption, monetary cost, accuracy, and the ability to determine altitude, speed, or heading information. To get an instance of a specifi c provider, call getProvider, passing in the name:

String providerName = LocationManager.GPS_PROVIDER;

LocationProvider gpsProvider;

gpsProvider = locationManager.getProvider(providerName);

Finding the Available Providers

The LocationManager class includes static string constants that return the provider name for the two most common Location Providers:

❑ LocationManager.GPS_PROVIDER

❑ LocationManager.NETWORK_PROVIDER

To get a list of names for all the providers available on the device, call getProviders, using a Boolean to indicate if you want all, or only the enabled, providers to be returned:

boolean enabledOnly = true;

List<String> providers = locationManager.getProviders(enabledOnly);

Finding Providers Based on Requirement Criteria

In most scenarios, it’s unlikely that you will want to explicitly choose the Location Provider to use. More commonly, you’ll specify the requirements that a provider must meet and let Android determine the best technology to use. Use the Criteria class to dictate the requirements of a provider in terms of accuracy (fine or coarse), power use (low, medium, high), cost, and the ability to return values for altitude, speed, and bearing. The following code creates Criteria that require coarse accuracy, low power consumption, and no need for altitude, bearing, or speed. The provider is permitted to have an associated cost.

Criteria criteria = new Criteria();

criteria.setAccuracy(Criteria.ACCURACY_COARSE);

criteria.setPowerRequirement(Criteria.POWER_LOW);

criteria.setAltitudeRequired(false);

criteria.setBearingRequired(false);

criteria.setSpeedRequired(false);

criteria.setCostAllowed(true);

Having defined the required Criteria, you can use getBestProvider to return the best matching Location Provider or getProviders to return all the possible matches. The following snippet demonstrates using getBestProvider to return the best provider for your criteria where the Boolean lets you restrict the result to a currently enabled provider:

String bestProvider = locationManager.getBestProvider(criteria, true);

If more than one Location Provider matches your criteria, the one with the greatest accuracy is returned. If no Location Providers meet your requirements, the criteria are loosened, in the following order, until a provider is found:

❑ Power use

❑ Accuracy

❑ Ability to return bearing, speed, and altitude

The criterion for allowing a device with monetary cost is never implicitly relaxed. If no provider is found, null is returned. To see a list of names for all the providers that match your criteria, you can use getProviders. It accepts Criteria and returns a fi ltered String list of all available Location Providers that match them. As with the getBestProvider call, if no matching providers are found, this call returns null.

List<String> matchingProviders = locationManager.getProviders(criteria,

false);

Finding Your Location

The purpose of location-based services is to find the physical location of the device. Access to the location-based services is handled using the Location Manager system Service. To access the Location Manager, request an instance of the LOCATION_SERVICE using the getSystemService method, as shown in the following snippet:

String serviceString = Context.LOCATION_SERVICE;

LocationManager locationManager;

locationManager = (LocationManager)getSystemService(serviceString);

Before you can use the Location Manager, you need to add one or more uses-permission tags to your manifest to support access to the LBS hardware. The following snippet shows the fine and coarse permissions. Of the default providers, the GPS provider requires fi ne permission, while the Network provider requires only coarse. An application that has been granted fine permission will have coarse permission granted implicitly.

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

<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION”/>

You can find the last location fix determined by a particular Location Provider using the getLastKnownLocation method, passing in the name of the Location Provider. The following example finds the last location fix taken by the GPS provider:

String provider = LocationManager.GPS_PROVIDER;

Location location = locationManager.getLastKnownLocation(provider);

Tracking Movement

Most location-sensitive applications will need to be reactive to user movement. Simply polling the Location Manager will not force it to get new updates from the Location Providers. Use the requestLocationUpdates method to get updates whenever the current location changes, using a LocationListener. Location Listeners also contain hooks for changes in a provider’s status and availability. The requestLocationUpdates method accepts either a specifi c Location Provider name or a set of Criteria to determine the provider to use. To optimize efficiency and minimize cost and power use, you can also specify the minimum time and

the minimum distance between location change updates. The following snippet shows the skeleton code for requesting regular updates based on a minimum time and distance.

String provider = LocationManager.GPS_PROVIDER;

int t = 5000; // milliseconds

int distance = 5; // meters

LocationListener myLocationListener = new LocationListener() {

public void onLocationChanged(Location location) {

// Update application based on new location.

}

public void onProviderDisabled(String provider){

// Update application if provider disabled.

}

public void onProviderEnabled(String provider){

// Update application if provider enabled.

}

public void onStatusChanged(String provider, int status,

Bundle extras){

// Update application if provider hardware status changed.

}

};

locationManager.requestLocationUpdates(provider, t, distance,

myLocationListener);

Using the Geocoder

Geocoding lets you translate between street addresses and longitude/latitude map coordinates. This can give you a recognizable context for the locations and coordinates used in location-based services and map-based Activities. The Geocoder class provides access to two geocoding functions:

❑ Forward Geocoding Finds the latitude and longitude of an address.

❑ Reverse Geocoding Finds the street address for a given latitude and longitude.

The results from these calls will be contextualized using a locale, where a locale is used to define your usual location and language. The following snippet shows how you set the locale when creating your Geocoder. If you don’t specify a locale, it will assume your device’s default.

Geocoder geocoder = new Geocoder(getApplicationContext(),

Locale.getDefault());

Both geocoding functions return a list of Address objects. Each list can contain several possible results, up to a limit you specify when making the call. Each Address object is populated with as much detail as the Geocoder was able to resolve. This can include the latitude, longitude, phone number, and increasingly granular address details from country to street and house number.

A note to all the readers and the app developers: using location based services or tracing movement will come directly under the privacy policy. An unauthorized tracking will lead to privacy breach. So if u want to use them, do so freely but mention why the location based services are needed, or if your app is totally based on location.