1 page.title=Google Map View 2 parent.title=Hello, Views 3 parent.link=index.html 4 @jd:body 5 6 <p>Using the Google Maps library, you can create your own map-viewing Activity. In this 7 tutorial, you'll create a simple map application in two parts. In Part 1, you'll create an app that 8 shows a map the user can pan and zoom. In Part 2, you'll add overlay items that mark 9 points of interest.</p> 10 11 <div class="special"> 12 <p>This tutorial requires that you have the external Google Maps library 13 installed in your SDK environment. The Maps library is included with the Google APIs 14 add-on, which you can install using the Android SDK and 15 AVD Manager. To learn how, see <a href="{@docRoot}sdk/adding-components.html">Adding SDK 16 Components</a>.</p> 17 18 <p>After installing the Google APIs add-on in your SDK, set your project properties to use the build 19 target called "Google APIs by Google Inc.". See the instructions for setting a build 20 target in <a href="{@docRoot}guide/developing/projects/projects-eclipse.html#CreatingAProject"> 21 Creating and Managing Projects in Eclipse</a> or <a 22 href="{@docRoot}guide/developing/projects/projects-cmdline.html#CreatingAProject"> 23 Creating and Managing Projects on the Command Line</a>, as appropriate for your environment.</p> 24 25 <p>You will also need to set up a new AVD that uses the same Google APIs deployment target. See <a 26 href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a> for 27 more information.</p> 28 29 <p>For reference material, see the <a 30 href="http://code.google.com/android/add-ons/google-apis/reference/index.html">Google Maps 31 library documentation</a>.</p> 32 33 </div> 34 35 <h2>Part 1: Creating a Map Activity</h2> 36 37 <ol> 38 <li>Start a new project named <em>HelloGoogleMaps</em>.</li> 39 40 <li>Because the Maps library is not a part of the standard Android library, you must 41 declare it in the Android Manifest. Open the <code>AndroidManifest.xml</code> 42 file and add the following as a child of the <code><application></code> element: 43 <pre><uses-library android:name="com.google.android.maps" /></pre> 44 </li> 45 46 <li>You also need access to the Internet in order to retrieve map tiles, 47 so you must also request the {@link android.Manifest.permission#INTERNET} permission. 48 In the manifest file, add the following as a child of the <code><manifest></code> element: 49 <pre><uses-permission android:name="android.permission.INTERNET" /></pre> 50 </li> 51 52 <li>While you're in the manifest, give the map some more space by getting rid of the title bar 53 with the "NoTitleBar" theme: 54 <pre> 55 <activity android:name=".HelloGoogleMaps" android:label="@string/app_name" 56 <strong>android:theme="@android:style/Theme.NoTitleBar"</strong>> 57 </pre> 58 </li> 59 60 61 <li>Open the <code>res/layout/main.xml</code> file and add a single 62 {@code com.google.android.maps.MapView} as the root node: 63 <pre> 64 <?xml version="1.0" encoding="utf-8"?> 65 <com.google.android.maps.MapView 66 xmlns:android="http://schemas.android.com/apk/res/android" 67 android:id="@+id/mapview" 68 android:layout_width="fill_parent" 69 android:layout_height="fill_parent" 70 android:clickable="true" 71 android:apiKey="<em>Your Maps API Key goes here</em>" 72 /> 73 </pre> 74 <p>The <code>android:clickable</code> attribute defines whether you want to allow 75 user-interaction with the map. If this is "false" then touching the map does nothing.</p> 76 77 <p>The <code>android:apiKey</code> attribute holds the Maps API Key for your 78 application, which proves your application and signer certificate has been registered with the 79 Maps service. This is required in order to receive the map data, even while you are 80 developing. Registration to the service is free and it only takes a couple 81 minutes to register your certificate and get a Maps API Key.</p> 82 <p>Go now to get a key. For instructions, read 83 <a href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining a Maps API 84 Key</a>. For the purpose of this tutorial, you should <a 85 href="http://code.google.com/android/add-ons/google-apis/mapkey.html#getdebugfingerprint">register 86 with the SDK debug certificate</a>, which will only be valid while your application is signed 87 with the debug key (once you sign with your private key, you will need a new API key). 88 When you get your key, insert it for the value of <code>android:apiKey</code>.</p> 89 </li> 90 91 <li>Now open the <code>HelloGoogleMaps.java</code> file. For this Activity, extend 92 {@code MapActivity} (instead of {@code android.app.Activity}):</p> 93 94 <pre>public class HelloGoogleMaps extends MapActivity {</pre> 95 <p>This is a special sub-class of {@link android.app.Activity}, provided by the Maps 96 library, which provides important map capabilities.</p> 97 98 <li>Inside every {@code MapActivity}, the <code>isRouteDisplayed()</code> method is required, so 99 override this method: 100 <pre> 101 @Override 102 protected boolean isRouteDisplayed() { 103 return false; 104 } 105 </pre> 106 <p>This method is required for some accounting from the Maps service to see if you're currently 107 displaying any route information. In this case, you're not, so return false.</p> 108 </li> 109 110 <li>Now add the standard {@link android.app.Activity#onCreate(Bundle) onCreate()} callback method 111 to the class: 112 <pre> 113 @Override 114 public void onCreate(Bundle savedInstanceState) { 115 super.onCreate(savedInstanceState); 116 setContentView(R.layout.main); 117 } 118 </pre> 119 <p>This loads the layout file created above. In fact, this is now a workable application that will 120 display map tiles and allow the user to pan around the map. But there's no ability to zoom. 121 Fortunately, there's a very simple zoom feature built into the {@code MapView} class, which you can 122 summon with {@code setBuiltInZoomControls(boolean)}. Do this at the end of the {@link 123 android.app.Activity#onCreate(Bundle) onCreate()} method:</p> 124 <pre> 125 MapView mapView = (MapView) findViewById(R.id.mapview); 126 mapView.setBuiltInZoomControls(true); 127 </pre> 128 </li> 129 <li>That's all there is to it. Run the application. (Remember, you must have an <a 130 href="{@docRoot}guide/developing/devices/index.html">AVD</a> configured to use the Google APIs 131 target, or be using a development device that includes the Maps library.)</li> 132 </ol> 133 134 <h2>Part 2: Adding Overlay Items</h2> 135 136 <p>So, now you have a map, but in many cases you'll also want to create your own map 137 markers and lay-overs. That's what you'll do now. In order to do so, you must implement the 138 {@code ItemizedOverlay} class, which can manage a whole set of {@code Overlay} (which are the 139 individual items placed on the map).</p> 140 141 <ol> 142 <li>Create a new Java class named <code>HelloItemizedOverlay</code> that implements 143 {@code ItemizedOverlay}. 144 145 <p>When using Eclipse, right-click the package name in the Eclipse Package Explorer, and 146 select <strong>New > Class</strong>. Fill-in 147 the Name field as <em>HelloItemizedOverlay</em>. For the Superclass, enter 148 "com.google.android.maps.ItemizedOverlay". Click the checkbox for <em>Constructors from 149 superclass</em>. Click Finish.</p></li> 150 151 <li>First, you need an <code>OverlayItem</code> {@link java.util.ArrayList}, in which you'll put 152 each of the <code>OverlayItem</code> objects you want on the map. Add this at the top of the 153 <code>HelloItemizedOverlay</code> class: 154 155 <pre>private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();</pre> 156 </li> 157 158 <li>Now define the <code>HelloItemizedOverlay</code> constructors. The constructor must 159 define the default marker for each of the {@code OverlayItem}s. In order for the {@link 160 android.graphics.drawable.Drawable} to actually get drawn, it must have its bounds defined. Most 161 commonly, you want the center-point at the bottom of the image to be the point at which it's 162 attached to the map coordinates. This is handled for you with the {@code boundCenterBottom()} 163 method. Wrap this around our defaultMarker, so the super constructor call looks like this: 164 <pre> 165 public HelloItemizedOverlay(Drawable defaultMarker) { 166 super(boundCenterBottom(defaultMarker)); 167 } 168 </pre> 169 </li> 170 171 <li>In order to add new {@code OverlayItem}s to the ArrayList, you need a new method: 172 <pre> 173 public void addOverlay(OverlayItem overlay) { 174 mOverlays.add(overlay); 175 populate(); 176 }</pre> 177 <p>Each time you add a new {@code OverlayItem} to the ArrayList, you must call 178 <code>populate()</code> for the {@code ItemizedOverlay}, which will read each of the 179 {@code OverlayItem}s and prepare them to be drawn.</p> 180 </li> 181 182 <li>When the <code>populate()</code> method executes, it will call <code>createItem(int)</code> in 183 the {@code ItemizedOverlay} to retrieve each {@code OverlayItem}. You must override this method to 184 properly read from the ArrayList and return the {@code OverlayItem} from the position specified 185 by the given integer. Your override method should look like this: 186 187 <pre> 188 @Override 189 protected OverlayItem createItem(int i) { 190 return mOverlays.get(i); 191 } 192 </pre> 193 </li> 194 195 <li>You must also override the <code>size()</code> method to return the current number of 196 items in the ArrayList: 197 <pre> 198 @Override 199 public int size() { 200 return mOverlays.size(); 201 } 202 </pre> 203 </li> 204 205 <li>Now set up the ability to handle touch events on the overlay items. First, you're 206 going to need a reference to the application {@link android.content.Context} as a member of 207 this class. So add {@code Context mContext} as a class member, then initialize it with a 208 new class constructor: 209 <pre> 210 public HelloItemizedOverlay(Drawable defaultMarker, Context context) { 211 super(defaultMarker); 212 mContext = context; 213 } 214 </pre> 215 <p>This passes the {@code defaultMarker} up to the default constructor to bound its coordinates 216 and then initialize {@code mContext} with the given {@link android.content.Context}.</p> 217 218 <p>Then override the {@code onTap(int)} callback method, which will handle the event 219 when an item is tapped by the user:</p> 220 <pre> 221 @Override 222 protected boolean onTap(int index) { 223 OverlayItem item = mOverlays.get(index); 224 AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); 225 dialog.setTitle(item.getTitle()); 226 dialog.setMessage(item.getSnippet()); 227 dialog.show(); 228 return true; 229 } 230 </pre> 231 <p>This uses the member {@code android.content.Context} to create a new {@link 232 android.app.AlertDialog.Builder} and uses the tapped {@code OverlayItem}'s title and snippet for 233 the dialog's title and message text. (You'll see the {@code OverlayItem} title and snippet defined 234 when you create it below.)</p> 235 </li> 236 237 </ol> 238 239 <p>You're now done with the <code>HelloItemizedOverlay</code> class and can start using it 240 to add items on the map.</p> 241 242 <p>Go back to the <code>HelloGoogleMaps</code> class. In the following procedure, you'll create an 243 {@code OverlayItem} and add it to an instance of the <code>HelloItemizedOverlay</code> class, then 244 add the <code>HelloItemizedOverlay</code> to the <code>MapView</code> using a {@code GeoPoint} 245 to define its coordinates on the map.</p> 246 247 <img src="images/androidmarker.png" align="right" /> 248 <ol> 249 <li>First, you need the image for the map overlay. If you don't have one handy, use the Android on 250 the right. Drag this image (or your own) into the <code>res/drawable/</code> directory of your 251 project.</li> 252 253 <li>At the end of your existing {@code onCreate()} method, instantiate : 254 255 <pre> 256 List<Overlay> mapOverlays = mapView.getOverlays(); 257 Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker); 258 HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable);</pre> 259 260 <p>All overlay elements on a map are held by the {@code MapView}, so when you want to add some, 261 you have to get a list from the <code>getOverlays()</code> method. Then instantiate the {@link 262 android.graphics.drawable.Drawable} used for the map marker, which was saved in the {@code 263 res/drawable/} directory. The constructor for {@code HelloItemizedOverlay} (your custom {@code 264 ItemizedOverlay}) takes the Drawable in order to set the default marker for all overlay 265 items.</p> 266 </li> 267 268 <li>Now create a {@code GeoPoint} that defines the map coordinates for the first overlay item, 269 and pass it to a new {@code OverlayItem}: 270 <pre> 271 GeoPoint point = new GeoPoint(19240000,-99120000); 272 OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!"); 273 </pre> 274 275 <p>{@code GeoPoint} coordinates are specified in microdegrees (<code>degrees * 1e6</code>). The 276 {@code OverlayItem} constructor accepts the {@code GeoPoint} location, a string for the 277 item's title, and a string for the item's snippet text, respectively.</p> 278 </li> 279 280 <li>All that's left is to add this {@code OverlayItem} to your collection in the 281 {@code HelloItemizedOverlay} instance, then add the {@code HelloItemizedOverlay} to the MapView: 282 <pre> 283 itemizedoverlay.addOverlay(overlayitem); 284 mapOverlays.add(itemizedoverlay); 285 </pre> 286 </li> 287 288 <li>Now run the application.</li> 289 </ol> 290 291 <p>You should see the following:</p> 292 <img src="images/hello-mapview.png" width="150px" /> 293 <p>When you tap the overlay item, you'll see the dialog appear.</p> 294 295 <p>Because the {@code ItemizedOverlay} class uses an {@code java.util.ArrayList} for all of the 296 {@code OverlayItem}s, it's easy to add more. Try adding another one. Before the 297 <code>addOverlay()</code> method is called, add these lines:</p> 298 <pre> 299 GeoPoint point2 = new GeoPoint(35410000, 139460000); 300 OverlayItem overlayitem2 = new OverlayItem(point2, "Sekai, konichiwa!", "I'm in Japan!"); 301 </pre> 302 <p>Run the application again. (You probably need to move the map to find the new overlay item.)</p> 303 304