Where Am I

Start by creating a "Hello, Android" application using these parameters in the New Project wizard:

Project name: LocationTest Build Target: Android 2.2 Application name: LocationTest Package name: org.example.locationtest Create Activity: LocationTest Min SDK Version: 8

Access to location information is protected by Android permissions. To gain access, you'll need to add these lines in the AndroidManifest.xml file before the <application> tag:

Download LocationTest/AndroidManifest.xml

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

6:24 PM

LocationTest

Location providers:

LocatlonPrQvlder[raime=gp5Jeriablecl=true1

getAccuracy=flre1getPowerRequlremert=highl hasMonetaryCost^falsejequlresCel^false, requlresNetwork=fal5e1requlresSatellite=trueJ

supportsAltitude^true^upportsBearlng^true, supportsSpeed=true]

Best provider is: gps

Locations {starting with last known):

Locatlon[unknown]

Provider status changed: gps, status=temporarily unavailable, extras=Bundle[rnParcelledData. dataSize=52]

Locatlon[mProvlder=gps, mTime=1247973339000, m Latltude=37.422006J rr

Longitude=-122.084095, mHasAltitude=t rue, mAltitude=0.01mHasSpeed=falseJ

mSpeed=0.0ImHasBearlng=talse, mBearlng=0.0JmHasAccuracy=fal5eI

mAccuracy=0.0,mExtras=Bundle[rnParcelledData.

dataSize=52]]

Figure 8.1: Testing the LocationManager

In this example, both fine-grained location providers such as GPS and coarse-grained location providers such as cell tower triangulation will be supported.

For the user interface, we're going to print all the location data into a big scrolling TextView, which is defined in res/layout/main.xml:

Download LocationTest/res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/output" android:layout_width= "fill_parent" android:layout_height="wrap_content" /> </ScrollView>

With the preliminaries out of the way, we can start coding. Here's the outline of the LocationTest class and the onCreate() method. (Ignore the reference to LocationListener on line 15 for now; we'll come back to it later.)

Download LocationTest/src/org/example/locationtest/LocationTest.java

Line 1 package org.example.locationtest;

- import java.util.List;

5 import android.app.Activity;

- import android.location.Criteria;

- import android.location.Location;

- import android.location.LocationListener;

- import android.location.LocationManager; 10 import android.location.LocationProvider;

- import android.os.Bundle;

- import android.widget.TextView;

- public class LocationTest extends Activity implements

15 LocationListener {

private LocationManager mgr;

- private TextView output; private String best;

20 ©Override public void onCreate(Bundle savedlnstanceState) {

- super.onCreate(savedlnstanceState);

- setContentView(R.layout.main);

25 mgr = (LocationManager) getSystemService(LOCATION_SERVICE);

- output = (TextView) findViewByld(R.id.output);

log("Location providers:");

- dumpProviders();

Criteria criteria = new Criteria();

- best = mgr.getBestProvider(criteria, true); log("\nBest provider is: " + best);

35 log("\nLocations (starting with last known):");

Location location = mgr.getLastKnownLocation(best);

- dumpLocation(location);

The starting point for Android location services is the getSystemService() call on line 25. It returns a LocationManager class that we save into a field for later use.

On line 29, we call our dumpProviders() method to print a list of all the location providers in the system.

Next we need to pick one of the possible providers to use. I've seen some examples that simply pick the first available one, but I recommend using the getBestProvider() method, as shown here. Android will pick the best provider according to a Criteria that you provide (see line 31). If you have any restrictions on cost, power, accuracy, and so on, this is where you put them. In this example, there are no restrictions.

Depending on the provider, it may take some time for the device to figure out your current location. This could be a few seconds, a minute, or more. However, Android remembers the last position it returned, so we can query and print that immediately on line 36. This location could be out of date—for example, if the device was turned off and moved— but it's usually better than nothing.

Knowing where we were is only half the fun. Where are we going next? Updating the Location

To have Android notify you about location changes, call the requestLo-cationUpdates() method on the LocationManager object. To save battery power, we want updates only when the program is in the foreground. Therefore, we need to hook into the Android activity life-cycle methods by overriding onResume() and onPause():

Download LocationTest/src/org/example/locationtest/LocationTest.java

@Override protected void onResume() { super.onResume();

// Start updates (doc recommends delay >= 60000 ms) mgr.requestLocationUpdates(best, 15000, 1, this);

@Override protected void onPause() { super.onPause();

// Stop updates to save power while app paused mgr.removeUpdates(this);

When the application resumes, we call requestLocationUpdates( ) to start the update process. It takes four parameters: the provider name, a delay (so you don't get updates too often), a minimum distance (changes less than this are ignored), and a LocationListener object.

When the application pauses, we call removeUpdates() to stop getting updates. The location provider will be powered down if it's not needed for a while.

Now you know why LocationTest implements LocationListener, so we could just pass a reference to the activity instead of making a new listener object. That will save us about 1KB of memory at runtime.

Here's the definition of the four methods required by that interface:

Download LocationTest/src/org/example/locationtest/LocationTest.java

public void onLocationChanged(Location location) { dumpLocation(location);

public void onProviderDisabled(String provider) { log("\nProvider disabled: " + provider);

public void onProviderEnabled(String provider) { log("\nProvider enabled: " + provider);

public void onStatusChanged(String provider, int status, Bundle extras) { log("\nProvider status changed: " + provider + ", status=" + S[status] + ", extras=" + extras);

The most important method in the bunch is onLocationChanged().

As the name suggests, it's called every time the provider notices that the device's location has changed. The onProviderDisabled(), onProviderEn-abled( ), and onStatusChanged( ) methods can be used to switch to other providers in case your first choice becomes unavailable.

The code for the remaining methods of LocationTest—log(), dumpProvi-ders(), and dumpLocation()—is not very interesting, but here it is for completeness:

Download LocationTest/src/org/example/locationtest/LocationTest.java

// Define human readable names private static final String[] A = { "invalid", "n/a", "fine", "coarse" }; private static final String[] P = { "invalid", "n/a", "low", "medium", "high" };

private static final String[] S = { "out of service", "temporarily unavailable", "available" };

/** Write a string to the output window */ private void 1og(String string) { output.append(string + "\n");

/** Write information from all location providers */ private void dumpProviders() {

List<String> providers = mgr.getA77Providers(); for (String provider : providers) { dumpProvider(provider);

/** Write information from a single location provider */ private void dumpProvider(String provider) {

LocationProvider info = mgr.getProvider(provider); StringBuilder builder = new StringBui1der(); bui1der.append("LocationProvider[") .append("name=") .append(info.getName()) .append( ",enab7ed=")

.append(mgr.isProviderEnab1ed(provider)) .append( ",getAccuracy=") .append(A[info.getAccuracy() + 1]) .append(",getPowerRequirement=") .append(P[info.getPowerRequirement() + 1]) .append(",hasMonetaryCost=") .append(info.hasMonetaryCost()) .append(",requiresCe77=") .append(info.requiresCe11()) .append(",requiresNetwork=") .append(info.requiresNetwork()) .append(",requiresSate77ite=") .append(info.requiresSate17ite()) .append(",supportsA7titude=") .append(info.supportsA7titude()) .append(",supportsBearing=") .append(info.supportsBearing()) .append(",supportsSpeed=") .append(info.supportsSpeed()) .append("j"); 7og(bui7der.toString());

/** Describe the given 7ocation, which might be nu77 */ private void dumpLocation(Location 7ocation) { if (7ocation == null)

7og("\nLocation[unknown]"); else

if you don't want to type it all in, you can find it all in the downloadable samples on the book's website.

0 0

Post a comment