Cleveland State University

CIS493. Mobile Application Development Using Android

TUTORIAL. BUILDING A SIMPLE MAPPING APPLICATION

The goal of this tutorial is to create a simple mapping application that we will call Adonde?We assume you have installed the most recent Android SDK[1], you have obtained a Google Maps API key [3], and your Eclipse IDE includes the ADT plugin[2] .

The user of this application will type in a valid address and a map of the given place will be drawn on the phone’s screen. Figure 1-(Left) depicts on a road mapthe location of “Cleveland State University”. The expected input is an address such as “123 Main Ave. Cleveland OH”, or a location such as “Rock and Roll Hall of Fame”. Observe the map includes a view control to zoom in and out. You can also touch the screen and drag the map on any direction.

As you already know, when a new Android application is created the Eclipse ADT provides the basic skeleton of the solution. The code is stored in a package inside the /src folder; resources such as pictures, files, etc. are stored in the /res subdirectory (see Figure 1-Right). In our example the class Adonde extends Android’s native MapActivity interface which provides means of displaying and navigating a map held in a MapView container.

The GUI definition –holding the MapView widget- is stored as an XML document in the /res/layout/main.xml file. The AndroidManifest.xml file contains a list of all the activities, and special permissions requested by the application. Now we are ready to work on the program.

Figure 1:(Left) Screen-shot of the Android Adonde application showing a map and coordinates of “Cleveland State University”. (Right) Structure of the app shown from Eclipse’s Package Explorer.

CREATING THE APPLICATION

STEP1.Open the AndroidManifest.xml file and add the following statement as a child of the<application>element:

<uses-library android:name="com.google.android.maps" />

We need Internet access to retrieve the Google Maps tiles, so the application must request theINTERNET permissions. In the AndroidManifest file, add the following statement as a child of the<manifest>element:

<uses-permission android:name="android.permission.INTERNET" />

STEP2. Now open the main layout file for your project. Define a nested linear layout to hold the GUI component as indicated below.

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"

xmlns:android="

<TextView

android:id="@+id/myCaption"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Address/Coordinates" />

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:orientation="horizontal"

<EditText

android:id="@+id/myAddress"

android:layout_width="260px"

android:layout_height="wrap_content"

android:hint="Enter location (address)"

android:textSize="18sp" />

<Button

android:id="@+id/myBtnSearch"

android:layout_width="59px"

android:layout_height="wrap_content"

android:text="Go" />

</LinearLayout>

<com.google.android.maps.MapView

android:id="@+id/myMap"

android:apiKey=

"Your personal Google Maps key goes here"

android:layout_width="fill_parent"

android:layout_height="350px"

android:clickable="true" />

</LinearLayout>

Theandroid:clickable=”true”clause consents to user-interaction with the map. The android:apiKeyattribute holds the public Google Maps API Key obtained after you register with the Google Maps service[5].

STEP3. Now open the Adonde.java file. Instead of a general purpose Activity class we want to override the specialized MapActivity interface. We also need to add our rendition of the mandatory isRouteDisplayed()method. Change the class declaration to:

publicclass HelloMapView extends MapActivity {

@Override
protectedboolean isRouteDisplayed() {
return false;
}

Continue working with the Adonde class, now add a definition for our class variables

private TextView lblCaption;

private EditText txtAddress;

private Button btnSearch;

private MapView myMap;

private doublelat, lon;

We proceedoverriding the onCreate method. Here the GUI components introduced in the XML layout will be ‘wired-up’ to the Java objects defined above. A call to findViewById associates the internal object identifier given to a GUI object to its corresponding class variable. For instance txtAddress is the object handler for the GUI EditText control defined as myAddress.

@Override

protectedvoid onCreate(Bundle icicle) {

super.onCreate(icicle);

setContentView(R.layout.main);

txtAddress = (EditText) findViewById(R.id.myAddress);

lblCaption = (TextView) findViewById(R.id.myCaption);

btnSearch = (Button) findViewById(R.id.myBtnSearch);

myMap = (MapView) findViewById(R.id.myMap);

myMap.setBuiltInZoomControls(true);

The method setContentView loads the GUI file (main.xml) on the screen. The last statement adds zooming capabilities to the MapView. Now we introduce the command button and its listener. Type in the following code:

btnSearch = (Button) findViewById(R.id.myBtnSearch);

btnSearch.setOnClickListener(new OnClickListener() {

publicvoid onClick(View v) {

geoC = new Geocoder(getApplicationContext());

String inputAddress = txtAddress.getText().toString();

try {//make an Address list with top 3 matches

List<Address> lstFoundAddresses = geoC.getFromLocationName(

inputAddress, 3);

if (lstFoundAddresses.size() == 0)

showMsg("Nothing found - Invalid address");

else {

navigateToLocation(lstFoundAddresses.get(0), myMap );

}

} catch (Exception e) {

showMsg(e.getMessage());

}

}// onClick

}); // btnSearch

GeoCoder is an Android class used to associate a physical address to its coordinate values (stored in a GeoPoint as latitude and longitude in microdegrees). When the command button is pressed the string in the txtAddress box is passed as a GeoCoder object to the method getFromLocationName. This method makes an Internet call to the Google Maps Service server and returns a list of the best n matches. In our example we ask for 3 options, however we just look at the first address and ignore the rest of the list. This process is called reverse geo-coding because we go from a textual address to a numeric coordinate value. The method navigateToLocation draws the map centered on the given latitude and longitude pair.

Continue the tutorial by entering the code:

publicvoid navigateToLocation( Address adr, MapView map) {

try {

//covert coordinate microdegrees to integer values

double latitude = adr.getLatitude() * 1000000;

double longitude = adr.getLongitude() * 1000000;

lblCaption.setText("Lat:" + latitude + " Lon: " + longitude);

GeoPoint geoPt = new GeoPoint((int) latitude, (int) longitude);

MapController mapCtrl = map.getController();

mapCtrl.animateTo(geoPt); // move map to the GeoPt

mapCtrl.setZoom(17); // zoom at chosen level

mapCtrl.setCenter(geoPt); // center the map on GeoPt

map.setSatellite(false); // display road-map view

map.setTraffic(false); // do not show traffic info

} catch (Exception e) {

showMsg( e.getMessage() );

}

}// navigateToLocation

In this fragment the coordinates found earlier are used to center the corresponding map. In our example the location is displayed using a zooming factor of 17 (max is 21), and intentionally disregard “satellite” and “traffic” view. The map is clickable therefore it could be dragged and resized. We need just to add our showMsg method; it is used to display messages that fade from the screen after a few seconds.

privatevoid showMsg(String theMsg){

Toast.makeText(getApplicationContext(),theMsg, Toast.LENGTH_SHORT).show();

}//showMsg

at this point our application is ready to run!

6. REFERENCES

[1]Android Developer’s Guide – available at:

[2]Eclipse IDE – Plugin for Android. Available at Accessed Feb 2010.

[3]Obtaining a Google Maps API Key. Available at Accessed Feb 2010.

V. Matos – Adonde Tutorial - 1