Location Based Services on Android – Part 2/3 – ItemizedOverlay

This is the second part of my blog series about how to use location based services in Google Android.

The first part of this series describes the integration of the google map view and the use of the MyLocationOverlay. In the second part I demonstrate how to use an ItemizedOverlay on a google map. Third and last part of this series describes how to build a custom Overlay and show it on the map.

Part 2 – Google Maps and ItemizedOverlay

In this part we will integrate an ItemizedOverlay to a Google Map view in Android. Whenever a new location is received with the GPS sensor we will capture that location, move the map to this position and show an icon.

You should already have integrated a google map. If you do not know how to do this – read the first part of this series. You can use the application of the first part of this series as base.

First I will provide the needed source code. I will not explain every single line of code, but explain the important steps.

To use a Google Maps View with an ItemizedOverlay we need an Activity and a class overwriting Itemized Overlay.

  • Activity: LocationBasedServicesV2
  • Overlay: MyItemizedOverlay

The activity

package de.itemis.frey.blog.lbsv2;
 
import java.util.Iterator;
import java.util.List;
 
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
 
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
 
/**
 * This application demonstrates the use of the google maps view in combination
 * with an ItemizedOverlay.
 *
 * @author frey
 */
public class LocationBasedServicesV2 extends MapActivity {
 
	private MapView myMap;
	private LocationManager locManager;
	private LocationListener locListener;
 
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
 
		initMap();
		initLocationManager();
	}
 
	/**
	 * Initialise the map and adds the zoomcontrols to the LinearLayout.
	 */
	private void initMap() {
		myMap = (MapView) findViewById(R.id.mymap);
 
		View zoomView = myMap.getZoomControls();
		LinearLayout myzoom = (LinearLayout) findViewById(R.id.myzoom);
		myzoom.addView(zoomView);
		myMap.displayZoomControls(true);
 
	}
 
	/**
	 * Initialise the location manager.
	 */
	private void initLocationManager() {
		locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
 
		locListener = new LocationListener() {
 
			public void onLocationChanged(Location newLocation) {
				createAndShowMyItemizedOverlay(newLocation);
			}
 
			public void onProviderDisabled(String arg0) {
			}
 
			public void onProviderEnabled(String arg0) {
			}
 
			public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
			}
		};
		locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
				locListener);
 
	}
 
	/**
	 * This method will bea called whenever a cahnge of the current position
	 * is submitted via the GPS.
	 * @param newLocation
	 */
	protected void createAndShowMyItemizedOverlay(Location newLocation) {
		List overlays = myMap.getOverlays();
 
		// first remove old overlay
		if (overlays.size() > 0) {
			for (Iterator iterator = overlays.iterator(); iterator.hasNext();) {
				iterator.next();
				iterator.remove();
			}
		}
 
		// transform the location to a geopoint
		GeoPoint geopoint = new GeoPoint(
				(int) (newLocation.getLatitude() * 1E6), (int) (newLocation
						.getLongitude() * 1E6));
 
		// initialize icon
		Drawable icon = getResources().getDrawable(R.drawable.pointer);
		icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon
				.getIntrinsicHeight());
 
		// create my overlay and show it
		MyItemizedOverlay overlay = new MyItemizedOverlay(icon);
		OverlayItem item = new OverlayItem(geopoint, "My Location", null);
		overlay.addItem(item);
		myMap.getOverlays().add(overlay);
 
		// move to location
		myMap.getController().animateTo(geopoint);
 
		// redraw map
		myMap.postInvalidate();
	}
 
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}

MyItemizedOverlay

package de.itemis.frey.blog.lbsv2;
 
import java.util.ArrayList;
import java.util.List;
 
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
 
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
 
public class MyItemizedOverlay extends ItemizedOverlay {
 
	private List items;
	private Drawable marker;
 
	public MyItemizedOverlay(Drawable defaultMarker) {
		super(defaultMarker);
		items = new ArrayList();
		marker = defaultMarker;
	}
 
	@Override
	protected OverlayItem createItem(int index) {
		return (OverlayItem)items.get(index);
	}
 
	@Override
	public int size() {
		return items.size();
 
	}
 
	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * com.google.android.maps.ItemizedOverlay#draw(android.graphics.Canvas,
	 * com.google.android.maps.MapView, boolean)
	 */
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		super.draw(canvas, mapView, shadow);
		boundCenterBottom(marker);
 
	}
 
	public void addItem(OverlayItem item) {
		items.add(item);
		populate();
	}
 
}

Receive location changes from the gps sensor

After starting the application and initialising the map (initMap()), we initialize a LocationManager (initLocationManager()). A LocationManager provides capabilities to receive information from the GPS sensor.

To get informed about position changes we need an instance of a LocationListener and bind it to the LocationManager. Its only necessary to implent the method onLocationChanged(), when the location changes we call the method createAndShowMyItemizedOverlay() and submit the new location as parameter.

Create the ItemizedOverlay and add it to the map

Whenever a new position is received from the GPS sensor the method createAndShowMyItemizedOverlay() is called. Inside this method we want to create an Overlay containing an icon showing the current position on the map. The method does many things which should be splitted in several methods in a productive environment – i leave them in this single method to keep things small and avoid source code-”jumps”.

First we remove previously added overlays from the map if necessary and transform the received Location to a GeoPoint, which is better supported by the Google Maps API.

Next we create the icon we want to use as marker for the position. The icon is an image “pointer.png” which is stored in the folder “res/drawable”. We create an instance of the MyitemizedOverlay and pass the created icon as paramter.

Now we use the geopoint to create an OverlayItem and add it to the Overlay. After adding the MyItemizedOverlay we animate the map to the position.

postInvalidate() is used to inform the map to redraw itself.

MyItemizedOverlay

To use ItemizedOverlays you have to extend the class ItemizedOverlay. You have to overwrite the methods createItem(), size() and create the constructor with marker as parameter. All methods are pretty simple and need no further explanation.

In addition i used the methods addItem() and draw().

The method populate() in addItem() is used to start the processing the ItemizedOverlay, it should be called as soon as data is available.

In the draw()-method, we call boundCenterBottom() to inform the ItemizedOverlay about the orientation of our overlay.

Testing the application

For testing of the application use the DDMS capabilites of your eclipse – or the connect vie telnet to the Android console and use the “geo fix” command as described in the first part of this series.

You are welcome to post comments or suggestions for improvement.

The complete series:

Autor: Andreas Frey
Datum: Tuesday, 7. April 2009 14:18
Trackback: Trackback-URL Themengebiet: Google Maps API, Google Android, Location Based Services, Tutorial

Feed zum Beitrag: RSS 2.0 Diesen Artikel kommentieren

9 Kommentare

  1. 1

    Great tutorial, thank you! I have just a few comments for changes I have on the source code:

    You: if (overlays.size() > 0) {
    I: if (overlays.size() > 0) {

    you: Drawable icon = getResources().getDrawable(R.drawable.pointer);

    I: Drawable icon = getResources().getDrawable(R.drawable.icon);

    you: protected OverlayItem createItem(int index) {return items.get(index);}

    I: protected OverlayItem createItem(int index) {return (OverlayItem) items.get(index); }

    Again, thank you for this nice introduction to Google Maps

  2. 2

    Hello Konrad,
    thank you for your comment.

    - I used my own Icon as marker on the map.
    - The method createItem is changed now.

  3. 3

    Andreas,

    I have followed your tutorial exactly (except for a few variable names). I was using the Android android icon like in http://developer.android.com/guide/tutorials/views/hello-mapview.html

    However, when I run the application, it keeps showing the icon from the previous tutorial (with the flashing blue dot). Any ideas??

  4. 4

    …in addition to my previous post:
    never mind the icon, got that sorted out. However, I have another severe problem now:

    I can only provide a location twice, either through DDMS or telnet. The onStatusChanged method returns gps as available. The icon shows up when I send the first location, moves when I send the second location. When I send a location for the third time, nothing happens. The onLocationChanged method isn’t called, neither are any other locationListener methods – gps isn’t reported to be unavailable or anything. MapActivity reports an error as soon as our Activity is started, saying “Couldn’t get connection factory client”.

  5. 5

    Hello Lex,

    This is a bug of the emulator. Look here for details: http://groups.google.com/group/android-developers/browse_frm/thread/3f4c9d83ddcf5815/3dcd5c81abb3752b

  6. 6

    I don’t know but there’s smt wrong with this line

    if (overlays.size() > 0)

    In my eclipse, it said that “gt can not be resolved”

    Please help me :( (

  7. 7

    Oh my god, that’s “>”. I don’t know how but thanks for your tutorial

    OMG!!! There’s nothing displays on my map except the map. There’s no icon (although I added an icon into drawable folder) on my map

  8. 8

    Is there anything else in res/drawable/ aside from the PNG file? Did you have to reference the PNG file from another of the res/ XML files at all?

  9. 9

    In the res/drawable there must be a file named “pointer.png”. That is all. No there is no more reference – the reference to this file comes from the generated R.java.

Kommentar abgeben