330 likes | 403 Views
Cosc 5/4775. MapView a nd XML parsing. MapView. The MapView widget and MapActivity gives you access to Android maps. Then you can add things to the map with Overlays. A very basic MapView widget, zoomed so you can see Wyoming. Note you need to use the GoogleAPIs in the emulator.
E N D
Cosc 5/4775 MapView and XML parsing
MapView • The MapView widget and MapActivity gives you access to Android maps. • Then you can add things to the map with Overlays. • A very basic MapView widget, zoomed so you can see Wyoming. • Note you need to use the GoogleAPIs in the emulator.
Map View and Activity • MapActivity public class MapDemoextends MapActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); MapViewmapView = (MapView) findViewById(R.id.mapview); mapView.setBuiltInZoomControls(true); } @Override protected booleanisRouteDisplayed() { // For accounting purposes, the server needs to know whether or not you are currently displaying any kind of route information, such as a set of driving directions. return false; } • main.xml <?xml version="1.0" encoding="utf-8"?> <com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey=“Your MAP API Key here" /> This code should show a Google map
Android Manifest.xml file • You will also need to lines to the manifest.xml file … </activity> <uses-library android:name="com.google.android.maps" /> </application> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
Google Maps API Key • The Mapview requires a key. • You can use the debug key that eclipsed generated for you. This uses Windows 7 • C:\users\<user>\android\debug.keystore • Note, this key expires one year after it was created. • If you are working on different machines, you will need to copy this key around or get multiple API keys for you project! • cd \users\<user>\android • keytool –list –keystoredebug.keystore • This produces a fingerprint that will look something like this: • Certificate fingerprint (MD5): 94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98
Google Maps API Key (2) • Enter the fingerprint into google’s page • http://code.google.com/android/maps-api-signup.html • Also it will ask you to log in. • It will then give you a API key • Example: (not a valid key for the record) 195Ud0lrI89HAFXIcuQbzsuAftqnR3d_pZHSuNA • Now enter that key into MapView key and create a entry in strings.xml file as well. • Like this: • <string name="mapskey"> 195Ud0lrI89HAFXIcuQbzsuAftqnR3d_pZHSuNA</string>
A Note • Google Maps library documentation. • Which is not included in the standard development documentation.
Overlays on the map • Once you have a map, you then add an Overlay onto the map for “your stuff”. • There are two types • Overlay • Base class representing an overlay which may be displayed on top of a map • ItemizedOverlay (subclass of overlay) • This handles sorting north-to-south for drawing, creating span bounds, drawing a marker for each point, and maintaining a focused item. It also matches screen-taps to items, and dispatches Focus-change events to an optional listener.
GeoPoints • A GeoPoint is the class that holds a single Latitude and longitude point • GeoPoint(int latitudeE6, int longitudeE6) • The E6 is how it represents lat/long point in microdegrees. • Microdegree = Degree *1E6 (1E6 is a constant you use to convert)
Overlay • So if you want to put some location points on the map with an extend the Overlay class. • We need to extend Overlay and the draw method Public class myOverlay extends Overlay { GeopointMyPoint; //the point we want to draw public myOverlay(GeoPointgp) { MyPoint = gp; } @Override public void draw(Canvas c, MapViewmapView, boolean shadow) { //code on the following slides. } }
Overlay draw method • public void draw(Canvas c, MapViewmapView, boolean shadow) • This method is called twice, once shadow true and then again shadow false. If (shadow ==false) { //now draw } else { //unless you want to draw a shadow, do nothing. } super.draw(c, mapView, shadow); //for anything else }
Overlay draw method (2) • Drawing • Second problem, lat/long coordiantes need to corrected to x,y “pixel” locations on the map. • We using the Projection method to convert. • You will need to get the current projection each time you draw, since a zoom/pan will change projection • Get a project with this code. Projection projection = mapView.getProjection();
Overlay draw method (3) • Finally draw the point in the shadow=false true side of the if statement. Projection projection = mapView.getProjection(); Point mp = new Point(); //now convert geopoint to a x,y pixel location projection.toPixels(MyPoint, mp); //assume black a declared paint variable c.drawPoint(mp.x,mp.y,black);
Adding the Overlay • In the MapActivity GeoPointpoint = new GeoPoint( (int) (41.312927 * 1E6), (int) (-105.587251*1E6) ); mapView.getOverlays().add(new myOverlay(point)); //now the map will draw my overlay
Overlay draw method a line • If we want to draw a line between 2 (or more) geopoints, same idea • Convert the points from GeoPoints to pixel and then draw them using a drawLine method • If it is lots of points, use the drawPath method. • If it is an area, still use drawPath, but use a Paint object that with fill style. • And the constructor for myOverlay takes an ArrayList of Geopoints.
Drawing an Area example // ArrayList<GeoPoint> gp is the list of GeoPoints. Path p = new Path(); Point mp = new Point(); //convert the first point projection.toPixels(gp.get(0), mp); p.moveTo(mp.x, mp.y); //now convert the rest of the points into the path for(intj=1; j<gp.size(); j++) { mp= new Point(); projection.toPixels(gp.get(j), mp); p.lineTo(mp.x, mp.y); } //set the brush correctly. myColor.setStyle(Paint.Style.FILL); myColor.setColor(Color.RED); myColor.setAlpha(50); //we want to be able to see the map through the area we are drawing. c.drawPath(p, myColor );
ItemizedOverlay • The ItemizedOverlay will draw points and a Marker on the map • Also gives up the ability to detect if the user tap our point as well. • Uses the OverlayItem class as well. • OverlayItem(GeoPoint point, Stringtitle, Stringsnippet) • The Construct an overlayitem.
In MapActivity • Get the overlays from the Map List<Overlay> mapOverlays = mapView.getOverlays(); • ItemOverlay requires a Marker, we are using the Icon. Drawabledrawable = this.getResources().getDrawable(R.drawable.ic_launcher); HelloItemizedOverlayitemizedoverlay = new HelloItemizedOverlay(drawable,this); • Create the overlay items, two in this case. GeoPointpoint = new GeoPoint(30443769,-91158458); OverlayItemoverlayitem = new OverlayItem(point, "Howdy!", "I'm in Laramie!"); GeoPoint point2 = new GeoPoint(17385812,78480667); OverlayItem overlayitem2 = new OverlayItem(point2, "Namashkaar!", "I'm in Hyderabad, India!"); • Add them to the itemized overaly itemizedoverlay.addOverlay(overlayitem); itemizedoverlay.addOverlay(overlayitem2); • Add the itemizedoverly to the map. mapOverlays.add(itemizedoverlay);
Extend the itemizedOverlay public class HelloItemizedOverlay extends ItemizedOverlay<OverlayItem> { private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>(); private Context mContext; public HelloItemizedOverlay(DrawabledefaultMarker, Context context) { super(boundCenterBottom(defaultMarker)); mContext = context; } public void addOverlay(OverlayItem overlay) { mOverlays.add(overlay); populate(); //needed to process all the new Overlayitems. }
Extend the itemizedOverlay (2) @Override protected OverlayItemcreateItem(inti) { return mOverlays.get(i); } @Override public int size(){ return mOverlays.size(); } //override the OnTap event to create an dialog box with the information, when the tap our geopoints. @Override protected booleanonTap(int index) { OverlayItemitem = mOverlays.get(index); AlertDialog.Builderdialog = new AlertDialog.Builder(mContext); dialog.setTitle(item.getTitle()); dialog.setMessage(item.getSnippet()); dialog.show(); return true; } }
Areas and lines. • The ItemizedOverlay is not setup to handle more then a single GeoPoint per OverlayItem. • We would need to extend the OverlayItem, so it can include a ArrayList of points. • Change our ItemizedOverlay to draw the area, like was done in the Overlay. • Override the HitText(…) method, so see if a user tapped in the area as well.
Android XML parsing
XML parsing • Since a lot of map data can be found in XML files (called kml) • We need to be able to parse xml files for this project as well. • There is an xml parser in android, called sax. • First we setup the SAX parser and create a Handler to process our k/xml files. • Uses the following packages javax.xml.parsers.SAXParser, javax.xml.parsers.SAXParserFactory, and org.xml.sax.*
Initial setup of SAX • create the factory SAXParserFactoryfactory = SAXParserFactory.newInstance(); • create a parser SAXParserparser = factory.newSAXParser(); • create the reader (scanner) XMLReaderxmlreader = parser.getXMLReader();
setup of SAX to parse • Assign our handler, on the next slides xmlreader.setContentHandler(MyDefaultHander); • Perform the synchronous parse of the data xmlreader.parse(InputSourceOurSource); • Example: InputSourceis = new InputSource( getResources().openRawResource(R.raw.cats)); • At this point the parse of the data is done or it failed, throwing an Exception that we should handle.
DefaultHandler • Part of the org.xml.sax.helpers package. • This part handles our xml parsing, we add the pieces necessary to pull out the information we want from the xml file. • This is done by override several methods • startDocument(), endDocument(), startElement, endElement, and characters. • There are more methods, we this is the minimum methods to process out the xml.
DefaultHandler (2) • startDocument() • Receive notification of the beginning of the document. • Setup whatever data structure you are using to hold all the data from the xml document. • endDocument() • Receive notification of the end of the document. • Finalized your data structure, as necessary.
DefaultHandler(3) • startElement • Called when a start tag is found • Examples: <kml>, <name>, <Placemark> • endElement • Called when an end tag is found • Examples: </kml>, </name>, </Placemark> • charaters • Called when data is found. This is when data is found between a start and end tag.
Example k/xml file and calls StartDocument call <?xml version="1.0" encoding="UTF-8"?> <kmlxmlns … > StartElement called <Document> StartElement called <Placemark id="ID_00000"> StartElement called <name> StartElement called Absaroka characters called </name> endElement called <coordinates> StartElement called -109.3,44.70,0 -109.9,44.70,0 -109.9,44.20,0 characters called -109.3,44.2,0 -109.3,44.70,0 characters called </coordinates>endElementcalled </Placemark>endElementcalled </Document>endElementcalled </kml>endElement called endDocument called
Dealing the calls. • So in your StartElement you going to have to setup “something”, so you know where to put the data. • Boolean variables are handy. • In characters, check the variables, so you know what the data is based on the startelement • Remember this maybe called several times in a row. • And in EndElement, finished the data as needed and set the Boolean to false.
At this point. • We’ll look at the source code MapDemo to see how this is all working. • In the SaxHandler.java
References • http://codemagician.wordpress.com/2010/05/06/android-google-mapview-tutorial-done-right/ • http://code.google.com/android/maps-api-signup.html • http://developer.android.com/resources/tutorials/views/hello-mapview.html • http://code.google.com/android/add-ons/google-apis/reference/index.html
Q A &