Home | History | Annotate | Download | only in views
      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/eclipse-adt.html">Developing in
     21 Eclipse with ADT</a> or <a
     22 href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>,
     23 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/tools/avd.html">Android 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>&lt;application></code> element:
     43   <pre>&lt;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>&lt;manifest></code> element:
     49   <pre>&lt;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 &lt;activity android:name=".HelloGoogleMaps" android:label="@string/app_name"
     56      <strong>android:theme="@android:style/Theme.NoTitleBar"</strong>&gt;
     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 &lt;?xml version="1.0" encoding="utf-8"?>
     65 &lt;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 &#64;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 &#64;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/tools/avd.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&lt;OverlayItem> mOverlays = new ArrayList&lt;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 &#64;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 &#64;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 &#64;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&lt;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