In this chapter, you'll learn how to use Titanium's Map API to visually represent location data via maps, routes, and annotations. In addition you'll learn best practices with respect to using the API. The context of location is one of the most powerful features of mobile apps, and soon you'll be equipped to visualize that data using native UI components through Titanium.
- Displaying a MapView
- Handling MapView events
- Android Maps API Key for Distribution
Displaying a MapView
MapView is the core UI component of the
Ti.Map module. It allows Titanium to make use of a mobile device's underlying native maps to view geographic data and add annotations and routes. As it is a native UI component, users will also have access to features like scrolling and multi-touch zoom. In its most basic form, the
MapView can simply display a basic map given a geographic position via latitude and longitude.
As seen above, those few lines of code generate native maps on both iOS and Android, respectively. Now that we have a basic map, let's discuss some of the properties of the
Ti.Map.MapView in order to see how it can be manipulated.
mapType- Indicates what type of map should be displayed. Below we see the
region- This is an object that contains the 4 properties defining the visible area of the
MapView. Below we can see how the same latitude and longitude of a
regioncan be represented with a different level of zoom via the
latitude- The latitude of your map's target region
longitude- The longitude of your map's target region
latitudeDelta- The measure of latitude north and south from your target region's latitude that will be visible in the
MapView. The smaller the delta value, the closer the zoom on your map.
longitudeDelta- The measure of longitude east and west from your target region's longitude that will be visible in the
animate- A boolean that indicates whether or not map actions, like opening and adding annotations, should be animated
regionFit- A boolean that indicates if the map should attempt to fit the
MapViewinto the region in the visible view
userLocation- A boolean that indicates if the map should show the user's current device location as a pin on the map
There are 2 more components that add a significant amount of functionality to your
mapViews. They are
routes. They allow us to add places of interest to our maps as well as plot paths between them. We'll address each in the following sections. But let's first discuss how we can handle events on our basic
Handling MapView Events
In addition to the typical touch interaction events that all views have,
MapViews have a couple more that give you more refined control. In many cases, we want to know exactly how a user's interaction with our initial map has changed its appearance. Also, having events that let us know when the map is loading and completed allow us to make our location based apps more responsive.
Here's the 3 events specific to
MapView that give you that additional control, and one additional event for handling mapping errors:
- complete - This event is fired when the
MapViewhas completed querying and rendering
- loading - This event is fired when the
MapViewhas started querying for new data, as well as rendering the new map. This is typically the result of the user changing the visible region of the map.
regionChanged - The event is fired when the visible region of our
MapViewhas changed. This can occur from programmatic changes, or from user interaction with the map. The new region data is returned in the following structure:
- error - This event let's us know when ever there is an error encountered by the underlying native maps. Often times these errors are not critical, but need to be handled in order to preserve a quality user experience.
As mentioned, the most common way to trigger the above events is through user interaction via scrolling and zooming. Let's change the
MapView example code to handle all of the aforementioned events.
Now we'll run the example again, this time zooming the map out after it renders.
And here is the event console output from this interaction.
Notice the order of events.
loading is first, signifying that new map data needs to be queried.
complete follows, letting us know that the preceding map query has completed. Finally, we get the
regionChanged event which gives us the new coordinates and deltas for the visible map region. This is the typical flow for all map interactions.
So now that we can display a basic
MapView and handle user interactions with it, let's take a look at how we can use annotations and routes to further extend the
Annotations, created with the
Ti.Map.createAnnotation() function, allow us to mark places of interest on our
MapViews with "pins", images, and text. They can be added when a
MapView is created via the
annotations array property, or anytime afterwards with the
Ti.Map.MapView.addAnnotation() function. Users can even interact with them to learn more about annotated locations.
Adding an annotation to a
MapView is simple. Let's modify the basic
MapView example to see how we can add the Appcelerator headquarters, and a few other locations, as annotations. To make things more interesting, we'll use a number of the styling properties available to annotations through the Titanium API.
We just created an array full of annotations, then passed that array to the
MapView for use when it was created. Even if we had only one annotation, we still need to pass it to the
MapView as an entry in an array. With the array of annotations constructed, we are ready to display them in a
MapView. Here's what it looks like on Android and iPhone, respectively.
As we can see, there's many
Annotation properties available for styling and interaction. We can add text, animations, colors, and even more UI components through use of these properties. Let's take a look at each of the properties used in this example.
animate- A boolean variable that indicates whether or not the annotation should be animated when it is added to the
image- The URL to an image to be used in place of the default pin image
leftButton- A button that will appear on the left side of your annotation when clicked. This property must have a value equal to the URL of an image, or to a
leftView- A Titanium View object that will appear on the left side of your annotation when clicked. This property can be a single view like a
Ti.UI.Label, or it can be a hierarchy of views.
pincolor- The color of the default pin representing an annotation. It can have the following values:
rightButton- A button that will appear on the right side of your annotation when clicked. This property must have a value equal to the URL of an image, or to a
rightView- A Titanium View object that will appear on the right side of your annotation when clicked. This property can be a single view like a
Ti.UI.Label, or it can be a hierarchy of views.
subtitle- The subtitle text that appears on your annotation when clicked
title- The main title text that appears on your annotation when clicked
So now you know how to create a
MapView, handle changes in its region, and add locations of interest via
Annotations. There's one more bit of functionality:
routes. In the next section we'll discuss
routes, a feature that allows us to create paths between locations on a
Routes allow us to draw paths between locations on a
MapView. These paths can be driving directions, bike paths, or any other reason you have to connect point A to point B.
Routes are added to
MapViews via the
Ti.Map.MapView.addRoute() function. To use the
addRoute() function, we pass it a properly structured
route object that will then be represented on the
route object should take the following form:
width fields are self-explanatory, the
points array could use some additional detail.
points holds the array of latitude and longitude coordinates that represent each point in our
route. As geometry dictates, you must have at least 2 points to draw a line, or route in this case. Limitations on the number of points you can use in a route are platform specific and are not governed by the Titanium API.
So let's go back to our
MapView example one more time and add a route to it. We'll create a route that connects the 3 locations we've already annotated. The route will go from north to south, connecting each location with a red, 4 pixel wide line.
After we add the route to the existing
MapView, we get the following map on iPhone.
Google Maps API Key for Android
Google requires a different Map API key for each certificate that signs an Android application. While Titanium automatically provides you with this key during development, you'll need your own when you build for distribution. API Keys can be obtained without a fee from Google. For a more in depth overview, read the Google Maps External Library overview.
In order to receive an API key that corresponds to your apps' certificate, you'll need to follow these steps:
1. Obtain the MD5 hash of your app's certificate from the keystore
Google uses the MD5 fingerprint of the certificate that signs your mobile application to generate a Maps API Key. This API Key is needed by Titanium when constructing the MapView. When your mobile application is run on the emulator or on a device, the underlying Maps implementation verifies that the API key used to pull map data matches the certificate which signed your application.
In order to get the MD5 hash of your distribution certificate, we run the Java SDK keystore tool
keytool from command line with the following parameters, explained below:
YOUR_KEYSTORE- The full path to your app's keystore file. For more details on how a keystore is generated, please reference the Distributing Android apps chapter of this book, as well as the Android app signing documentation.
ALIAS- The alias you assigned to your keystore when you created it
STOREPASS- The password you assigned to secure your keystore when you created it
Upon successful execution of this command you should receive an output similar to the one below. The MD5 hash required is the
Certificate fingerprint (MD5) field, which has been highlighted. Copy and/or save the value found in this field.
2. Sign up for an Android Maps API Key
Once you have the MD5 fingerprint, log in with your Google (Gmail) account and visit the Android Maps API Key Signup form.
Paste in your fingerprint and agree to the terms. Press Generate API Key. You should see a result similar to the image below.
3. Put your API Key in tiapp.xml in the property ti.android.google.map.api.key
Once you have received your API key, you need only include it in your project's
tiapp.xml file to use it. To do so, we add an application property to the existing file under the main
<ti:app> element. The property will look like this:
So if you were to include this in a basic
tiapp.xml file, it would look something like this:
You are now ready to use the Google map views in your distributable Titanium app.
In this chapter we learned how to use the
Ti.Map module to create, display, annotate, and navigate through maps. We used
Ti.Map.MapView to represent native maps in our mobile app. In addition we used
Ti.Map.Annotations to mark places of interest on our maps, adding more detailed data to our location based interactions. Finally, we learned how we can use
routes to connect points of interest to our maps.