Chapter 9. Location-Based Services

WHAT YOU WILL LEARN IN THIS CHAPTER

  • How to display Google Maps in your Android application

  • How to display the zoom controls on the map

  • How to switch between the different map views

  • How to add markers to maps

  • How to get the address location touched on the map

  • How to perform geocoding and reverse geocoding

  • How to obtain geographical data using GPS, Cell-ID, and Wi-Fi triangulation

  • How to monitor for a location

We have all seen the explosive growth of mobile apps in recent years. One category of apps that is very popular is location-based services, commonly known as LBS. LBS apps track your location, and may offer additional services such as locating amenities nearby, as well as offering suggestions for route planning, and so on. Of course, one of the key ingredients in a LBS app is maps, which present a visual representation of your location.

In this chapter, you will learn how to make use of the Google Maps in your Android application, and how to manipulate it programmatically. In addition, you will learn how to obtain your geographical location using the LocationManager class available in the Android SDK.

DISPLAYING MAPS

Google Maps is one of the many applications bundled with the Android platform. In addition to simply using the Maps application, you can also embed it into your own applications and make it do some very cool things. This section describes how to use Google Maps in your Android applications and programmatically perform the following:

  • Change the views of Google Maps.

  • Obtain the latitude and longitude of locations in Google Maps.

  • Perform geocoding and reverse geocoding (translating an address to latitude and longitude and vice versa).

  • Add markers to Google Maps.

Creating the Project

To get started, you need to first create an Android project so that you can display the Google Maps in your activity.

Obtaining the Maps API Key

Beginning with the Android SDK release v1.0, you need to apply for a free Google Maps API key before you can integrate Google Maps into your Android application. When you apply for the key, you must also agree to Google's terms of use, so be sure to read them carefully.

To apply for a key, follow the series of steps outlined next.

Note

Google provides detailed documentation on applying for a Maps API key at http://code.google.com/android/add-ons/google-apis/mapkey.html.

First, if you are testing the application on the Android Emulator or an Android device directly connected to your development machine, locate the SDK debug certificate located in the default folder (C:Users<username>.android for Windows 7 users). You can verify the existence of the debug certificate by going to Eclipse and selecting Window

Obtaining the Maps API Key

Note

For Windows XP users, the default Android folder is C:Documents and Settings<username>Local SettingsApplication DataAndroid.

FIGURE 9-3

Figure 9-3. FIGURE 9-3

The filename of the debug keystore is debug.keystore. This is the certificate that Eclipse uses to sign your application so that it may be run on the Android Emulator or devices.

Using the debug keystore, you need to extract its MD5 fingerprint using the Keytool.exe application included with your JDK installation. This fingerprint is needed to apply for the free Google Maps key. You can usually find the Keytool.exe in the C:Program FilesJava<JDK_version_number>in folder.

Issue the following command (see Figure 9-4) to extract the MD5 fingerprint:

keytool.exe -list -alias androiddebugkey -keystore
"C:Users<username>.androiddebug.keystore" -storepass android
-keypass android
FIGURE 9-4

Figure 9-4. FIGURE 9-4

In this example, my MD5 fingerprint is EF:7A:61:EA:AF:E0:B4:2D:FD:43:5E:1D:26:04:34:BA.

Copy the MD5 certificate fingerprint and navigate your web browser to: http://code.google.com/android/maps-api-signup.html. Follow the instructions on the page to complete the application and obtain the Google Maps key. When you are done, you should see something similar to what is shown in Figure 9-5.

FIGURE 9-5

Figure 9-5. FIGURE 9-5

Note

Although you can use the MD5 fingerprint of the debug keystore to obtain the Maps API key for debugging your application on the Android Emulator or devices, the key will not be valid if you try to deploy your Android application as an APK file. Once you are ready to deploy your application to the Android Market (or other methods of distribution), you need to reapply for a Maps API key using the certificate that will be used to sign your application. Chapter 11 discusses this topic in more detail.

Displaying the Map

You are now ready to display Google Maps in your Android application. This involves two main tasks:

  • Modify your AndroidManifest.xml file by adding both the <uses-library> element and the INTERNET permission.

  • Add the MapView element to your UI.

The following Try It Out shows you how.

Displaying the Zoom Control

The previous section showed how you can display Google Maps in your Android application. You can pan the map to any desired location and it will be updated on-the-fly. However, on the emulator there is no way to zoom in or out from a particular location (on a real Android device you can pinch the map to zoom it). Thus, in this section, you will learn how you can let users zoom in or out of the map using the built-in zoom controls.

Besides displaying the zoom controls, you can also programmatically zoom in or out of the map using the zoomIn() or zoomOut() method of the MapController class. The following Try It Out shows you how to achieve this.

Changing Views

By default, Google Maps is displayed in map view, which is basically drawings of streets and places of interest. You can also set Google Maps to display in satellite view using the setSatellite() method of the MapView class:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     mapView = (MapView) findViewById(R.id.mapView);
     mapView.setBuiltInZoomControls(true);
     mapView.setSatellite(true);
}

Figure 9-8 shows Google Maps displayed in satellite view.

FIGURE 9-8

Figure 9-8. FIGURE 9-8

Besides satellite view, you can also display the map in street view (which highlights all the streets on the map) using the setStreetView() method. Figure 9-9 shows the map displaying a location in both street view (left) and satellite view (right).

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mapView = (MapView) findViewById(R.id.mapView);
    mapView.setBuiltInZoomControls(true);
    mapView.setSatellite(true);
    mapView.setStreetView(true);
}

If you want to display traffic conditions on the map, use the setTraffic() method

mapView.setTraffic(true);
FIGURE 9-9

Figure 9-9. FIGURE 9-9

Figure 9-10 shows the map displaying the current traffic conditions. The different colors reflect the varying traffic conditions. In general, green color equates to smooth traffic of about 50 miles per hour, yellow equates to moderate traffic of about 25-50 miles per hour, and red equates to slow traffic of about less than 25 miles per hour.

FIGURE 9-10

Figure 9-10. FIGURE 9-10

Note that the traffic information is only available in major cities in the United States, France, Britain, Australia, and Canada, with new cities and countries frequently added.

Navigating to a Specific Location

By default, Google Maps displays the map of the United States when it is first loaded. However, you can also set Google Maps to display a particular location. In this case, you can use the animateTo() method of the MapController class.

The following Try It Out shows how you can programmatically animate Google Maps to a particular location.

Adding Markers

Adding markers to a map to indicate places of interest enables your users to easily locate the places they are looking for. The following Try It Out shows you how to add a marker to Google Maps.

Getting the Location That Was Touched

After using Google Maps for a while, you may want to know the latitude and longitude of a location corresponding to the position on the screen that was just touched. Knowing this information is very useful, as you can determine a location's address, a process known as reverse geocoding (you will learn how this is done in the next section).

If you have added an overlay to the map, you can override the onTouchEvent() method within the MapOverlay class. This method is fired every time the user touches the map. This method has two parameters: MotionEvent and MapView. Using the MotionEvent parameter, you can determine whether the user has lifted his or her finger from the screen using the getAction() method. In the following code snippet, if the user has touched and then lifted the finger, you display the latitude and longitude of the location touched:

import android.view.MotionEvent;
import android.widget.Toast;
//...

    class MapOverlay extends com.google.android.maps.Overlay
    {
        @Override
        public boolean draw(Canvas canvas, MapView mapView,
        boolean shadow, long when)
        {
            super.draw(canvas, mapView, shadow);

            //---translate the GeoPoint to screen pixels---
            Point screenPts = new Point();
            mapView.getProjection().toPixels(p, screenPts);

            //---add the marker---
            Bitmap bmp = BitmapFactory.decodeResource(
                getResources(), R.drawable.pushpin);
            canvas.drawBitmap(bmp, screenPts.x, screenPts.y-50, null);
            return true;
        }

        @Override
        public boolean onTouchEvent(MotionEvent event, MapView mapView)
        {
            //---when user lifts his finger---
            if(event.getAction() == 1) {
               GeoPoint p = mapView.getProjection().fromPixels(
                   (int) event.getX(),
                   (int) event.getY());
                   Toast.makeText(getBaseContext(),
                       "Location: "+
                       p.getLatitudeE6() / 1E6 + ","+
                       p.getLongitudeE6() /1E6 ,
                       Toast.LENGTH_SHORT).show();
            }
            return false;
       }
}

The getProjection() method returns a projection for converting between screen-pixel coordinates and latitude/longitude coordinates. The fromPixels() method then converts the screen coordinates into a GeoPoint object.

Figure 9-15 shows the map displaying a set of coordinates when the user clicks a location on the map.

FIGURE 9-15

Figure 9-15. FIGURE 9-15

Geocoding and Reverse Geocoding

As mentioned in the preceding section, if you know the latitude and longitude of a location, you can find out its address using a process known as reverse geocoding. Google Maps in Android supports this via the Geocoder class. The following code snippet shows how you can retrieve the address of a location just touched using the getFromLocation() method:

import android.location.Address;
import android.location.Geocoder;
import java.util.Locale;
import java.io.IOException;
//...

        @Override
        public boolean onTouchEvent(MotionEvent event, MapView mapView)
        {
            //---when user lifts his finger---
            if (event.getAction() == 1) {
                GeoPoint p = mapView.getProjection().fromPixels(
                    (int) event.getX(),
                    (int) event.getY());
                    /*
                    Toast.makeText(getBaseContext(),
                        "Location: "+
                        p.getLatitudeE6() / 1E6 + "," +
                        p.getLongitudeE6() /1E6 ,
                        Toast.LENGTH_SHORT).show();
*/

                Geocoder geoCoder = newGeocoder(
                    getBaseContext(), Locale.getDefault());
                try {
                    List<Address> addresses = geoCoder.getFromLocation(
                        p.getLatitudeE6()  / 1E6,
                        p.getLongitudeE6() / 1E6, 1);

                    String add = "";
                    if(addresses.size() > 0)
                    {
                        for(inti=0; i<addresses.get(0).getMaxAddressLineIndex();
                             i++)
                           add += addresses.get(0).getAddressLine(i) + "
";
                    }
                    Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();
                }
                catch(IOException e) {
                    e.printStackTrace();
                }
                return true;
        }
        return false;
    }
}

The Geocoder object converts the latitude and longitude into an address using the getFromLocation() method. Once the address is obtained, you display it using the Toast class. Figure 9-16 shows the application displaying the address of a location that was touched on the map.

If you know the address of a location but want to know its latitude and longitude, you can do so via geocoding. Again, you can use the Geocoder class for this purpose. The following code shows how you can find the exact location of the Empire State Building by using the getFromLocationName() method:

//---geo-coding---
Geocoder geoCoder = new Geocoder(this, Locale.getDefault());
try {
    List<Address> addresses = geoCoder.getFromLocationName(
        "empire state building", 5);

    String add = "";
    if(addresses.size() > 0) {
       p = new GeoPoint(
              (int) (addresses.get(0).getLatitude() * 1E6),
              (int) (addresses.get(0).getLongitude() * 1E6));
       mc.animateTo(p);
       mapView.invalidate();
    }
} catch(IOException e) {
            e.printStackTrace();
        }

Figure 9-17 shows the map navigating to the location of the Empire State Building.

FIGURE 9-16

Figure 9-16. FIGURE 9-16

FIGURE 9-17

Figure 9-17. FIGURE 9-17

GETTING LOCATION DATA

Nowadays, mobile devices are commonly equipped with GPS receivers. Because of the many satellites orbiting the earth, you can use a GPS receiver to find your location easily. However, GPS requires a clear sky to work and hence does not always work indoors or where satellites can't penetrate (such as a tunnel through a mountain).

Another effective way to locate your position is through cell tower triangulation. When a mobile phone is switched on, it is constantly in contact with base stations surrounding it. By knowing the identity of cell towers, it is possible to translate this information into a physical location through the use of various databases containing the cell towers' identities and their exact geographical locations. The advantage of cell tower triangulation is that it works indoors, without the need to obtain information from satellites. However, it is not as precise as GPS because its accuracy depends on overlapping signal coverage, which varies quite a bit. Cell tower triangulation works best in densely populated areas where the cell towers are closely located.

A third method of locating your position is to rely on Wi-Fi triangulation. Rather than connect to cell towers, the device connects to a Wi-Fi network and checks the service provider against databases to determine the location serviced by the provider. Of the three methods described here, Wi-Fi triangulation is the least accurate.

On the Android, the SDK provides the LocationManager class to help your device determine the user's physical location. The following Try It Out shows you how this is done in code.

If you want to use Cell-ID and Wi-Fi triangulation (important for indoor use) for obtaining your location data, you can use the network location provider, like this:

lm.requestLocationUpdates(
        LocationManager.NETWORK_PROVIDER,
        0,
        0,
        locationListener);

You can combine both the GPS location provider with the network location provider within your application.

Monitoring a Location

One very cool feature of the LocationManager class is its ability to monitor a specific location. This is achieved using the addProximityAlert() method. The following code snippet shows how to monitor a particular location so that if the user is within a five-meter radius from that location, your application will fire an intent to launch the web browser:

//---use the LocationManager class to obtain locations data---
lm = (LocationManager)
     getSystemService(Context.LOCATION_SERVICE);

//---PendingIntent to launch activity if the user is within some locations---
PendingIntent pendIntent = PendingIntent.getActivity(
    this, 0, new
    Intent(android.content.Intent.ACTION_VIEW,
      Uri.parse("http://www.amazon.com")), 0);

lm.addProximityAlert(37.422006, −122.084095, 5, −1, pendIntent);

The addProximityAlert() method takes five arguments: latitude, longitude, radius (in meters), expiration (time for the proximity alert to be valid, after which it will be deleted; −1 for no expiration), and the pending intent.

Note that if the Android device's screen goes to sleep, the proximity is also checked once every four minutes in order to preserve the battery life of the device.

SUMMARY

This chapter took a whirlwind tour of the MapView object, which displays Google Maps in your Android application. You have learned the various ways in which the map can be manipulated, and you have also seen how you can obtain geographical location data using the various network providers: GPS, Cell-ID, or Wi-Fi triangulation.

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

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