blob: 531300f22a1974df86d9547a8488835e5a81bdb5 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001page.title=Hello, MapView
2parent.title=Hello, Views
3parent.link=index.html
4@jd:body
5
Dirk Doughertye1d9b552009-04-21 20:39:18 -07006<div class="special">
7<p>This tutorial requires that you have the Google Maps external library
Dirk Doughertyf11d7d52009-08-05 19:04:18 -07008installed in your SDK environment. By default the Android SDK includes the
Dirk Doughertye1d9b552009-04-21 20:39:18 -07009Google APIs add-on, which in turn includes the Maps external library. If you
10don't have the Google APIs SDK add-on, you can download it from this
11location:</p>
12
13<p style="margin-left:2em;"><a
14href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a></p>
15
16<p>The Google APIs add-on requires Android 1.5 SDK or later release. After
17installing the add-on in your SDK, set your project properties to use the build
18target called "Google APIs Add-on". See the instructions for setting a build
19target in <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing in
20Eclipse with ADT</a> or <a
21href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>,
22as appropriate for your environment. </p>
23
24<p>You will also need to use the android tool to set up an AVD that uses the
25Google APIs deployment target. See <a
26href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> for
27more information. Once you have set up your environment, you will be able to
28build and run the project described in this tutorial</a></p>
29
30</div>
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032<p>A MapView allows you to create your own map-viewing Activity.
33First, we'll create a simple Activity that can view and navigate a map. Then we will add some overlay items.</p>
34
35<ol>
36 <li>Start a new project/Activity called HelloMapView.
37
38 <li>Because we're using the Google Maps library,
39 which is not a part of the standard Android library, we need to
40 declare it in the Android Manifest. Open the AndroidManifest.xml
41 file and add the following as a child of the <code>&lt;application></code> element:
42
43 <pre>&lt;uses-library android:name="com.google.android.maps" /></pre>
44 </li>
45 <li>We also need access to the internet in order to retrieve the Google Maps tiles,
46 so the application must request the {@link android.Manifest.permission#INTERNET INTERNET} permissions.
47 In the manifest file, add the following as a child of the <code>&lt;manifest></code> element:
48 <pre>&lt;uses-permission android:name="android.permission.INTERNET" /></pre>
49 </li>
50 <li>Now open the main layout file for your project. Define a layout with a com.google.android.maps.MapView
51 inside a android.widget.RelativeLayout:
52
53<pre>
54&lt;?xml version="1.0" encoding="utf-8"?>
55&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
56 android:id="@+id/mainlayout"
57 android:orientation="vertical"
58 android:layout_width="fill_parent"
59 android:layout_height="fill_parent" >
60
61 &lt;com.google.android.maps.MapView
62 android:id="@+id/mapview"
63 android:layout_width="fill_parent"
64 android:layout_height="fill_parent"
65 android:clickable="true"
66 android:apiKey="<em>Your Maps API Key</em>"
67 />
68
69&lt;/RelativeLayout>
70</pre>
71 <p>The <code>clickable</code> attribute defines whether you want to allow user-interaction with the map.
72 In this case, we set it "true" so that the user can navigate.</p>
73
74 <p>The <code>apiKey</code> attribute holds the Google Maps API Key that proves your application and signer
75 certificate has been registered with the Google Maps service. Because MapView uses Google Maps data, this key is required
76 in order to receive the map data, even while you are developing. Registration is free and it only takes a couple
77 minutes to register your certificate and receive a Maps API Key. For instructions on getting a key, read
Dirk Dougherty392d29a2009-05-01 13:01:24 -070078 <a href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining a Maps API Key</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 (For the purpose of this tutorial, you should register with the fingerprint of the SDK debug certificate.)
80 Once you've acquired the Maps API Key, insert it for the <code>apiKey</code> value.</p></li>
81
82 <li>Now open the HelloMapView.java file. For this Activity, we're going to extend the special sub-class of
83 Activity called MapActivity, so change the class declaration to extend
84 MapActicity, instead of Activity:</p>
85
86 <pre>public class HelloMapView extends MapActivity {</pre>
87
88 <li>The <code>isRouteDisplayed()</code> method is required, so add it inside the class:
89<pre>
90&#64;Override
91protected boolean isRouteDisplayed() {
92 return false;
93}
94</pre>
95<p>You can actually run this now, but all it does is allow you to pan around the map.</p>
96<p>Android provides a handy {@link android.widget.ZoomControls} widget for zooming in and out of a View.
97MapView can automatically hook one for us by requesting it with the <code>getZoomControls()</code>
98method. Let's do this.</p>
99
100<li>Go back to the layout file. We need a new ViewGroup element, in which we'll
101 place the ZoomControls. Just below the MapView element (but inside the RelativeLayout), add this element:
102<pre>
103&lt;LinearLayout
104 android:id="@+id/zoomview"
105 android:layout_width="wrap_content"
106 android:layout_height="wrap_content"
107 android:layout_alignBottom="@id/mapview"
108 android:layout_centerHorizontal="true"
109/></pre>
110
111 <p>It doesn't really matter what kind of ViewGroup we use, because we just want a
112 container that we can position within our root RelativeLayout.</p>
113
114 <p>The last two attributes are available only to an element that's a child of a
115 RelativeLayout. <code>layout_alignBottom</code> aligns the bottom of this element to the bottom of
116 the element identified with a resource tag (which must be a sibling to this element).
117 <code>layout_centerHorizontal</code> centers this on the horizontal plane.</p></li>
118
119 <li>Now go back to the HelloMapView class. We'll now retrieve the ZoomControls object from
120 the MapView and add it to our new layout element. First, at the top of the HelloMapView,
121 instantiate handles for the MapView and LinearLayout, plus a ZoomControl object:
122<pre>
123LinearLayout linearLayout;
124MapView mapView;
125ZoomControls mZoom;</pre></li>
126
127 <li>Then initialize each of these in <code>onCreate()</code>. We'll capture the LinearLayout and
128 MapView through their layout resources. Then get the ZoomControls from the MapView::
129<pre>
130linearLayout = (LinearLayout) findViewById(R.id.zoomview);
131mapView = (MapView) findViewById(R.id.mapview);
132mZoom = (ZoomControls) mapView.getZoomControls();</pre>
133
134 <p>By using the ZoomControls object provided by MapView, we don't have to do any of the work
135 required to actually perform the zoom operations. The ZoomControls widget that MapView
136 returns for us is already hooked into the MapView and works as soon as we add it to the
137 layout. The controls will appear whenever the user touches the map, then dissapear after
138 a few moments of inactivity.</p></li>
139
140 <li>Now just plug our ZoomControls into the LinearLayout we added:
141
142 <pre>linearLayout.addView(mZoom);</pre></li>
143
144 <li>Run it.</li>
145</ol>
146
147<hr/>
148
149<p>So, we now have full interaction controls. All well and good, but what we really want our map
150for is custom markers and layovers. Let's add some Overlay
151objects to our map. To do this, we're going to
152implement the ItemizedOverlay
153class, which can manage a whole set of Overlay items for us.</p>
154
155<ol>
156 <li>Create a new Java class named HelloItemizedOverlay that implements ItemizedOverlay.
157
158 <p>When using Eclipse, right-click the package name in the Eclipse Package Explorer, and select New > Class. Fill-in
159 the Name field as <em>HelloItemizedOverlay</em>. For the Superclass, enter
160 <em>com.google.android.maps.ItemizedOverlay</em>. Click the checkbox for <em>Constructors from
161 superclass</em>. Click Finish.</p></li>
162
163 <li> First thing, we need an OverlayItem ArrayList, in which we'll put each of the OverlayItem
164 objects we want on our map. Add this at the top of the HelloItemizedOverlay class:
165
166 <pre>private ArrayList&lt;OverlayItem> mOverlays = new ArrayList&lt;OverlayItem>();</pre></li>
167
168 <li>All the constructor does is define the default marker to be used on each of the OverlayItems.
169 In order for the Drawable to actually get drawn, it must have its bounds defined. And we want the
170 center-point at the bottom of the image to be the point at which it's attached to the map
171 coordinates. We handle all this with the boundCenterBottom() method. Wrap this around our
172 defaultMarker, so the super constructor call looks like this:
173
174 <pre>super(boundCenterBottom(defaultMarker));</pre></li>
175
176 <li>In order to add new OverlayItems to our ArrayList, we need a new public method. We'll handle
177 this with the following method:
178
179<pre>
180public void addOverlay(OverlayItem overlay) {
181 mOverlays.add(overlay);
182 populate();
183}</pre>
184
185 <p>Each time we add a new OverlayItem, we must call <code>populate()</code>, which will read each of out
186 OverlayItems and prepare them to be drawn.</p></li>
187
188 <li>In order for the <code>populate()</code> method to read each OverlayItem, it will make a request to
189 <code>createItem(int)</code>. We must define this method to properly read from our ArrayList. Replace the
190 existing contents of the createItem method with a <code>get()</code> call to our ArrayList:
191
192<pre>
193&#64;Override
194protected OverlayItem createItem(int i) {
195 return mOverlays.get(i);
196}
197</pre></li>
198
199 <li>We're also required to override the <code>size()</code> method. Replace the existing contents of the
200 method with a size request to our ArrayList:
201
202 <pre>return mOverlays.size();</pre></li>
203</ol>
204
205
206<p>That's it for the HelloItemizedOverlay class. We're now ready to use it.</p>
207
208<hr/>
209<p>Go back to the HelloMapView
210class. We'll start by creating one OverlayItem, adding to an instance of our HelloItemizedOverlay,
211and then adding this to the MapView.</p>
212
213<img src="images/androidmarker.png" align="right" />
214<p>First, we need the image that we'll use for our map overlay. Here, we'll use the Android on the
215right as our marker. Drag this image (or your own) to the res/drawable/ directory of your project workspace.</p>
216
217<p>Now we're ready to work in the HelloMapView:</p>
218
219<ol>
220 <li>First we need some more types. Add the following at the top of the HelloMapView class:
221
222<pre>
223List&lt;Overlay> mapOverlays;
224Drawable drawable;
225HelloItemizedOverlay itemizedOverlay;</pre></li>
226
227 <li>Now pick up where we left off in the <code>onCreate()</code> method. Instantiate the
228 new fields:
229
230<pre>
231mapOverlays = mapView.getOverlays();
232drawable = this.getResources().getDrawable(R.drawable.androidmarker);
233itemizedoverlay = new HelloItemizedOverlay(drawable);</pre>
234
235 <p>All overlay elements on a map are held by the MapView, so when we want to add some, we must
236 first retrieve the List with <code>getOverlays()</code> methods. We instantiate the Drawable, which will
237 be used as our map marker, by using our Context resources to get the Drawable we placed in
238 the res/drawable/ directory (androidmarker.png). Our HelloItemizedOverlay takes the Drawable in order to set the
239 default marker.</p></li>
240
241 <li>Now let's make our first OverlayItem by creating a GeoPoint
242 that defines our map coordinates, then pass it to a new OverlayItem:
243
244<pre>
245GeoPoint point = new GeoPoint(19240000,-99120000);
246OverlayItem overlayitem = new OverlayItem(point, "", "");</pre>
247
248 <p>GeoPoint coordinates are based in microdegrees (degrees * 1e6). The OverlayItem takes this
249 GeoPoint and two strings. Here, we won't concern ourselves with the strings, which can display
250 text when we click our marker, because we haven't yet written the click handler for the OverlayItem.</p></li>
251
252 <li>All that's left is for us to add this OverlayItem to our collection in the HelloItemizedOverlay,
253 and add this to the List of Overlay objects retrieved from the MapView:
254
255<pre>
256itemizedoverlay.addOverlay(overlayitem);
257mapOverlays.add(itemizedoverlay);</pre></li>
258
259 <li>Run it!</li>
260</ol>
261
262<p>We've sent our droid to Mexico City. Hola, Mundo!</p>
263<p>You should see the following:</p>
264<img src="images/hello-mapview.png" width="150px" />
265
266<p>Because we created our ItemizedOverlay class with an ArrayList, we can continue adding new
267OverlayItems. Try adding another one. Before the <code>addOverlay()</code> method is called, add these lines:</p>
268<pre>
269GeoPoint point2 = new GeoPoint(35410000, 139460000);
270OverlayItem overlayitem2 = new OverlayItem(point2, "", "");
271</pre>
272<p>Run it again... We've sent a new droid to Tokyo. Sekai, konichiwa!</p>
273