| page.title=Google Map View |
| parent.title=Hello, Views |
| parent.link=index.html |
| @jd:body |
| |
| <p>Using the Google Maps library, you can create your own map-viewing Activity. In this |
| tutorial, you'll create a simple map application in two parts. In Part 1, you'll create an app that |
| shows a map the user can pan and zoom. In Part 2, you'll add overlay items that mark |
| points of interest.</p> |
| |
| <div class="special"> |
| <p>This tutorial requires that you have the external Google Maps library |
| installed in your SDK environment. The Maps library is included with the Google APIs |
| add-on, which you can install using the Android SDK and |
| AVD Manager. To learn how, see <a href="{@docRoot}sdk/adding-components.html">Adding SDK |
| Components</a>.</p> |
| |
| <p>After installing the Google APIs add-on in your SDK, set your project properties to use the build |
| target called "Google APIs by Google Inc.". See the instructions for setting a build |
| target in <a href="{@docRoot}guide/developing/projects/projects-eclipse.html#CreatingAProject"> |
| Creating and Managing Projects in Eclipse</a> or <a |
| href="{@docRoot}guide/developing/projects/projects-cmdline.html#CreatingAProject"> |
| Creating and Managing Projects on the Command Line</a>, as appropriate for your environment.</p> |
| |
| <p>You will also need to set up a new AVD that uses the same Google APIs deployment target. See <a |
| href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a> for |
| more information.</p> |
| |
| <p>For reference material, see the <a |
| href="http://code.google.com/android/add-ons/google-apis/reference/index.html">Google Maps |
| library documentation</a>.</p> |
| |
| </div> |
| |
| <h2>Part 1: Creating a Map Activity</h2> |
| |
| <ol> |
| <li>Start a new project named <em>HelloGoogleMaps</em>.</li> |
| |
| <li>Because the Maps library is not a part of the standard Android library, you must |
| declare it in the Android Manifest. Open the <code>AndroidManifest.xml</code> |
| file and add the following as a child of the <code><application></code> element: |
| <pre><uses-library android:name="com.google.android.maps" /></pre> |
| </li> |
| |
| <li>You also need access to the Internet in order to retrieve map tiles, |
| so you must also request the {@link android.Manifest.permission#INTERNET} permission. |
| In the manifest file, add the following as a child of the <code><manifest></code> element: |
| <pre><uses-permission android:name="android.permission.INTERNET" /></pre> |
| </li> |
| |
| <li>While you're in the manifest, give the map some more space by getting rid of the title bar |
| with the "NoTitleBar" theme: |
| <pre> |
| <activity android:name=".HelloGoogleMaps" android:label="@string/app_name" |
| <strong>android:theme="@android:style/Theme.NoTitleBar"</strong>> |
| </pre> |
| </li> |
| |
| |
| <li>Open the <code>res/layout/main.xml</code> file and add a single |
| {@code com.google.android.maps.MapView} as the root node: |
| <pre> |
| <?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="<em>Your Maps API Key goes here</em>" |
| /> |
| </pre> |
| <p>The <code>android:clickable</code> attribute defines whether you want to allow |
| user-interaction with the map. If this is "false" then touching the map does nothing.</p> |
| |
| <p>The <code>android:apiKey</code> attribute holds the Maps API Key for your |
| application, which proves your application and signer certificate has been registered with the |
| Maps service. This is required in order to receive the map data, even while you are |
| developing. Registration to the service is free and it only takes a couple |
| minutes to register your certificate and get a Maps API Key.</p> |
| <p>Go now to get a key. For instructions, read |
| <a href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining a Maps API |
| Key</a>. For the purpose of this tutorial, you should <a |
| href="http://code.google.com/android/add-ons/google-apis/mapkey.html#getdebugfingerprint">register |
| with the SDK debug certificate</a>, which will only be valid while your application is signed |
| with the debug key (once you sign with your private key, you will need a new API key). |
| When you get your key, insert it for the value of <code>android:apiKey</code>.</p> |
| </li> |
| |
| <li>Now open the <code>HelloGoogleMaps.java</code> file. For this Activity, extend |
| {@code MapActivity} (instead of {@code android.app.Activity}):</p> |
| |
| <pre>public class HelloGoogleMaps extends MapActivity {</pre> |
| <p>This is a special sub-class of {@link android.app.Activity}, provided by the Maps |
| library, which provides important map capabilities.</p> |
| |
| <li>Inside every {@code MapActivity}, the <code>isRouteDisplayed()</code> method is required, so |
| override this method: |
| <pre> |
| @Override |
| protected boolean isRouteDisplayed() { |
| return false; |
| } |
| </pre> |
| <p>This method is required for some accounting from the Maps service to see if you're currently |
| displaying any route information. In this case, you're not, so return false.</p> |
| </li> |
| |
| <li>Now add the standard {@link android.app.Activity#onCreate(Bundle) onCreate()} callback method |
| to the class: |
| <pre> |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.main); |
| } |
| </pre> |
| <p>This loads the layout file created above. In fact, this is now a workable application that will |
| display map tiles and allow the user to pan around the map. But there's no ability to zoom. |
| Fortunately, there's a very simple zoom feature built into the {@code MapView} class, which you can |
| summon with {@code setBuiltInZoomControls(boolean)}. Do this at the end of the {@link |
| android.app.Activity#onCreate(Bundle) onCreate()} method:</p> |
| <pre> |
| MapView mapView = (MapView) findViewById(R.id.mapview); |
| mapView.setBuiltInZoomControls(true); |
| </pre> |
| </li> |
| <li>That's all there is to it. Run the application. (Remember, you must have an <a |
| href="{@docRoot}guide/developing/devices/index.html">AVD</a> configured to use the Google APIs |
| target, or be using a development device that includes the Maps library.)</li> |
| </ol> |
| |
| <h2>Part 2: Adding Overlay Items</h2> |
| |
| <p>So, now you have a map, but in many cases you'll also want to create your own map |
| markers and lay-overs. That's what you'll do now. In order to do so, you must implement the |
| {@code ItemizedOverlay} class, which can manage a whole set of {@code Overlay} (which are the |
| individual items placed on the map).</p> |
| |
| <ol> |
| <li>Create a new Java class named <code>HelloItemizedOverlay</code> that implements |
| {@code ItemizedOverlay}. |
| |
| <p>When using Eclipse, right-click the package name in the Eclipse Package Explorer, and |
| select <strong>New > Class</strong>. Fill-in |
| the Name field as <em>HelloItemizedOverlay</em>. For the Superclass, enter |
| "com.google.android.maps.ItemizedOverlay". Click the checkbox for <em>Constructors from |
| superclass</em>. Click Finish.</p></li> |
| |
| <li>First, you need an <code>OverlayItem</code> {@link java.util.ArrayList}, in which you'll put |
| each of the <code>OverlayItem</code> objects you want on the map. Add this at the top of the |
| <code>HelloItemizedOverlay</code> class: |
| |
| <pre>private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();</pre> |
| </li> |
| |
| <li>Now define the <code>HelloItemizedOverlay</code> constructors. The constructor must |
| define the default marker for each of the {@code OverlayItem}s. In order for the {@link |
| android.graphics.drawable.Drawable} to actually get drawn, it must have its bounds defined. Most |
| commonly, you want the center-point at the bottom of the image to be the point at which it's |
| attached to the map coordinates. This is handled for you with the {@code boundCenterBottom()} |
| method. Wrap this around our defaultMarker, so the super constructor call looks like this: |
| <pre> |
| public HelloItemizedOverlay(Drawable defaultMarker) { |
| super(boundCenterBottom(defaultMarker)); |
| } |
| </pre> |
| </li> |
| |
| <li>In order to add new {@code OverlayItem}s to the ArrayList, you need a new method: |
| <pre> |
| public void addOverlay(OverlayItem overlay) { |
| mOverlays.add(overlay); |
| populate(); |
| }</pre> |
| <p>Each time you add a new {@code OverlayItem} to the ArrayList, you must call |
| <code>populate()</code> for the {@code ItemizedOverlay}, which will read each of the |
| {@code OverlayItem}s and prepare them to be drawn.</p> |
| </li> |
| |
| <li>When the <code>populate()</code> method executes, it will call <code>createItem(int)</code> in |
| the {@code ItemizedOverlay} to retrieve each {@code OverlayItem}. You must override this method to |
| properly read from the ArrayList and return the {@code OverlayItem} from the position specified |
| by the given integer. Your override method should look like this: |
| |
| <pre> |
| @Override |
| protected OverlayItem createItem(int i) { |
| return mOverlays.get(i); |
| } |
| </pre> |
| </li> |
| |
| <li>You must also override the <code>size()</code> method to return the current number of |
| items in the ArrayList: |
| <pre> |
| @Override |
| public int size() { |
| return mOverlays.size(); |
| } |
| </pre> |
| </li> |
| |
| <li>Now set up the ability to handle touch events on the overlay items. First, you're |
| going to need a reference to the application {@link android.content.Context} as a member of |
| this class. So add {@code Context mContext} as a class member, then initialize it with a |
| new class constructor: |
| <pre> |
| public HelloItemizedOverlay(Drawable defaultMarker, Context context) { |
| super(defaultMarker); |
| mContext = context; |
| } |
| </pre> |
| <p>This passes the {@code defaultMarker} up to the default constructor to bound its coordinates |
| and then initialize {@code mContext} with the given {@link android.content.Context}.</p> |
| |
| <p>Then override the {@code onTap(int)} callback method, which will handle the event |
| when an item is tapped by the user:</p> |
| <pre> |
| @Override |
| protected boolean onTap(int index) { |
| OverlayItem item = mOverlays.get(index); |
| AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); |
| dialog.setTitle(item.getTitle()); |
| dialog.setMessage(item.getSnippet()); |
| dialog.show(); |
| return true; |
| } |
| </pre> |
| <p>This uses the member {@code android.content.Context} to create a new {@link |
| android.app.AlertDialog.Builder} and uses the tapped {@code OverlayItem}'s title and snippet for |
| the dialog's title and message text. (You'll see the {@code OverlayItem} title and snippet defined |
| when you create it below.)</p> |
| </li> |
| |
| </ol> |
| |
| <p>You're now done with the <code>HelloItemizedOverlay</code> class and can start using it |
| to add items on the map.</p> |
| |
| <p>Go back to the <code>HelloGoogleMaps</code> class. In the following procedure, you'll create an |
| {@code OverlayItem} and add it to an instance of the <code>HelloItemizedOverlay</code> class, then |
| add the <code>HelloItemizedOverlay</code> to the <code>MapView</code> using a {@code GeoPoint} |
| to define its coordinates on the map.</p> |
| |
| <img src="images/androidmarker.png" align="right" /> |
| <ol> |
| <li>First, you need the image for the map overlay. If you don't have one handy, use the Android on |
| the right. Drag this image (or your own) into the <code>res/drawable/</code> directory of your |
| project.</li> |
| |
| <li>At the end of your existing {@code onCreate()} method, instantiate : |
| |
| <pre> |
| List<Overlay> mapOverlays = mapView.getOverlays(); |
| Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker); |
| HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable, this);</pre> |
| |
| <p>All overlay elements on a map are held by the {@code MapView}, so when you want to add some, |
| you have to get a list from the <code>getOverlays()</code> method. Then instantiate the {@link |
| android.graphics.drawable.Drawable} used for the map marker, which was saved in the {@code |
| res/drawable/} directory. The constructor for {@code HelloItemizedOverlay} (your custom {@code |
| ItemizedOverlay}) takes the Drawable in order to set the default marker for all overlay |
| items.</p> |
| </li> |
| |
| <li>Now create a {@code GeoPoint} that defines the map coordinates for the first overlay item, |
| and pass it to a new {@code OverlayItem}: |
| <pre> |
| GeoPoint point = new GeoPoint(19240000,-99120000); |
| OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!"); |
| </pre> |
| |
| <p>{@code GeoPoint} coordinates are specified in microdegrees (<code>degrees * 1e6</code>). The |
| {@code OverlayItem} constructor accepts the {@code GeoPoint} location, a string for the |
| item's title, and a string for the item's snippet text, respectively.</p> |
| </li> |
| |
| <li>All that's left is to add this {@code OverlayItem} to your collection in the |
| {@code HelloItemizedOverlay} instance, then add the {@code HelloItemizedOverlay} to the MapView: |
| <pre> |
| itemizedoverlay.addOverlay(overlayitem); |
| mapOverlays.add(itemizedoverlay); |
| </pre> |
| </li> |
| |
| <li>Now run the application.</li> |
| </ol> |
| |
| <p>You should see the following:</p> |
| <img src="images/hello-mapview.png" width="150px" /> |
| <p>When you tap the overlay item, you'll see the dialog appear.</p> |
| |
| <p>Because the {@code ItemizedOverlay} class uses an {@code java.util.ArrayList} for all of the |
| {@code OverlayItem}s, it's easy to add more. Try adding another one. Before the |
| <code>addOverlay()</code> method is called, add these lines:</p> |
| <pre> |
| GeoPoint point2 = new GeoPoint(35410000, 139460000); |
| OverlayItem overlayitem2 = new OverlayItem(point2, "Sekai, konichiwa!", "I'm in Japan!"); |
| </pre> |
| <p>Run the application again. (You probably need to move the map to find the new overlay item.)</p> |
| |