Advertisement
ActionScript

Implement a Map Using the Google Map API for Flash

by

Twice a month, we revisit some of our readers’ favorite posts from throughout the history of Activetuts+. This tutorial was first published in May, 2009.

In this tutorial we'll see how we can create a map in Flash using the Google Map API. We'll cover some of the basics such as zooming in on the map and adding some controls. We'll also look at how we can add markers to our map and how we can load data using an XML file.


Step 1: The Google Map API Key

Before we can start creating our map in Flash we need to setup a few things. To use the Google Map API you will need a personal API Key. To get this go to http://code.google.com/intl/nl/apis/maps/documentation/flash/ and click the link on the right side of the page "Sign up for a Google Maps API Key".

google maps api for flash

Step 2: Sign Up

Clicking the "Sign up for a Google Maps API Key" link brings us to the next page where we can generate our personal API Key. Scroll down the page, agree with the terms and conditions (you could read these too if you're really interested) and add the url of the website where you want to use the application (you will need a different API Key for every domain where you want to place a map). After that, click "Generate API Key".

google maps api for flash

Step 3: Save It!

Now you'll see your personal API Key for the selected domain. Copy the API Key and paste or save it somewhere as we'll need it very soon.

google maps api for flash

Step 4: The Google Map SWC Component

Ok, now we have our API Key but we still need one more thing before we can start to create our map in Flash. We need to download the Google Map SWC component. To do so, go to http://code.google.com/intl/nl/apis/maps/documentation/flash/ and click "Download the Google Maps API for Flash SDK". A popup window will appear, choose to Save the "sdk.zip" file and download it.

google maps api for flash

Step 5: Install the SDK Component

Now we need to install the SDK component to use it in Flash. To do so, navigate to the location where you saved the Google Maps API for Flash SDK and find the non-Flex version of the interface library. In my case this is (lib/map_1_9.swc). Now copy the "map_1_9.swc" file.

google maps api for flash

Step 6: Folders

Afterwards, if you have Flash currently open, quit the application and search for this folder:

  • (Windows) C:\Program Files\Adobe\Adobe Flash CS3 (or your Flash version)\en (or your language)\Configuration\Components
  • (Mac OS X) Macintosh HD/Applications/Adobe Flash CS3 (or your Flash version)/Configuration/Components

Inside that folder create a new folder named "google" and Paste the "map_1_9.swc" file inside it. Flash is now set up to support the Google Maps API for Flash.

google maps api for flash

Step 7: New ActionScript 3.0 File

Ok. That's all done and dusted! Now we can finally start creating our map in Flash. Start Flash CS3 or CS4 and create a new ActionScript 3.0 file, default stage size (550 x 400).

google maps api for flash

Step 8: Save It!

Now simply save the file; hit "Ctrl+S" or go to File > Save in the menu. Save it to the location you want and name it whatever you want. I'll name it "google_map".

google maps api for flash

Step 9: The GoogleMapsLibrary

Open the Components panel "Ctrl+F7" or click Window > Components in the menu and drag the GoogleMapsLibrary onto the stage.

google maps api for flash

Step 10: The Actions Layer

Create a new layer, double-click on its name and rename it to "actions".

google maps api for flash

Step 11: Import..

Now with the actions layer selected open the actions panel by hitting "F9" or clicking Window > Actions. Add these lines of code:

import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
google maps api for flash

Step 12: Create the Map

Now let's add the map! When we load the movie this piece of code will create a map and set it on the stage. Inside the code we see the variable "map.key"; here we have to add our personal API Key. Open the file where you saved the API Key and Copy/Paste it into the variable.

// Create The Map
var map:Map = new Map();
map.key = "Your API Key here";
map.setSize(new Point(stage.stageWidth, stage.stageHeight));
this.addChild(map);
google maps api for flash

Step 13: Test Movie

Ok, now go and test your movie "Ctrl+Enter" or click Control > Test Movie in the menu and you will see that you've just created a map.

google maps api for flash

Step 14: Controls

At this stage we can only drag the map around. That's not really what we're looking for, so let's add some controls to the map which will allow us to zoom and move about. To add controls to our map we need to update our code. First we need to call a few extra classes:

import com.google.maps.controls.ZoomControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.MapTypeControl;

After that we need to create a new function to call once the map is created. We name that function "onMapReady()". Inside this function we add our controls to the map.

function onMapReady(event:MapEvent):void {
  map.addControl(new ZoomControl());
  map.addControl(new PositionControl());
  map.addControl(new MapTypeControl());
}

Now we just need to call the "onMapReady()" function whenever our map is loaded. To do that we need to add a extra line to our first piece of code.

map.addEventListener(MapEvent.MAP_READY, onMapReady);

Our full code now looks like this:

import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
import com.google.maps.controls.ZoomControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.MapTypeControl;

// Create The Map
var map:Map = new Map();
map.key = "Your API Key Here";
map.setSize(new Point(stage.stageWidth, stage.stageHeight));
map.addEventListener(MapEvent.MAP_READY, onMapReady);
this.addChild(map);

function onMapReady(event:MapEvent):void {
  map.addControl(new ZoomControl());
  map.addControl(new PositionControl());
  map.addControl(new MapTypeControl());
}
google maps api for flash

Step 15: More..

Now test your movie "Ctrl+Enter" or click Control > Test Movie in the menu and you will see our map now has controls. We're able to zoom in and even change our map to Satellite, Hybrid and Terrain view. That's very cool but we want more..

google maps api for flash

Step 16: Latitude and Longitude

Let's zoom into a specific location once our map loads for the first time. Say I'm a surfer and I want to create a map of the surf spots in my home town. We don't want people to manually have to zoom in and search for the area, so we'll fix that in a sec. The only thing we have to add is one small line of code to our "onMapReady()" function.

map.setCenter(new LatLng(28.74659,-13.93447), 9, MapType.HYBRID_MAP_TYPE);

What we actually do here is create a new LatLng point on the map. First we specify 2 values: the "latitude" and the "longitude" from our region. Then we set our zoom value; I opted to use 9. The zoom ranges from 0 to about 16 (this can vary from region to region). Lastly we set the map type; I opted here for the HYBRID_MAP_TYPE.

Our "onMapReady()" function now looks like this:

function onMapReady(event:MapEvent):void {
  map.setCenter(new LatLng(28.74659,-13.93447), 9, MapType.HYBRID_MAP_TYPE);
  map.addControl(new ZoomControl());
  map.addControl(new PositionControl());
  map.addControl(new MapTypeControl());
}

If we test our movie you can see that lots of things have changed. Once the map is loaded we zoom into our specific region and our map type is now Hybrid. To determine the latitude and longitude for your region you could use Google Earth or an online tool like http://itouchmap.com/latlong.html.

google maps api for flash

Step 17: Add a Marker

Now let's add a simple marker to our map. Just add 2 more classes:

import com.google.maps.overlays.MarkerOptions;
import com.google.maps.overlays.Marker;

and update the "onMapReady()" function with this piece of code:

var marker:Marker = new Marker(
							     new LatLng(28.74659, -13.93447)	     		           
		     		            );
map.addOverlay(marker);

Again we create a LatLng point with some specific latitude/longitude values for our location. Then we call the "addOverlay()" to put our marker on the map. Our full code now looks like this:

import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
import com.google.maps.controls.ZoomControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.overlays.MarkerOptions;
import com.google.maps.overlays.Marker;

// Create The Map
var map:Map = new Map();
map.key = "ABQIAAAAUeTGkbea0ftVnzbVMwAPKxT2yXp_ZAY8_ufC3CFXhHIE1NvwkxTlsMw9FdPd5mJqEw01CzwnlVdxDw";
map.setSize(new Point(stage.stageWidth, stage.stageHeight));
map.addEventListener(MapEvent.MAP_READY, onMapReady);
this.addChild(map);

function onMapReady(event:MapEvent):void {
  map.setCenter(new LatLng(28.74659,-13.93447), 9, MapType.HYBRID_MAP_TYPE);
  map.addControl(new ZoomControl());
  map.addControl(new PositionControl());
  map.addControl(new MapTypeControl());
  
  var marker:Marker = new Marker(
							     new LatLng(28.74659, -13.93447)	     		           
		     		            );
  map.addOverlay(marker);
}

Go and test your movie. You'll see our marker on the map.

google maps api for flash

Step 18: Still More..

Now let's take everything to the next level. We have a map with zoom controls and a marker. What more do we need? Well I'll tell you. We need MORE MARKERS, TOOLTIPS, INFO WINDOWS and we want to load everything from an XML file. So let's get started. First we'll create our XML file. Open your Favorite XML editor and create this file:

<?xml version="1.0" encoding="utf-8"?>
 <map_xml>
 
  <location>
   <lat>28.74659</lat>
   <lon>-13.93447</lon>
   <name_tip>Majanicho</name_tip>
   <title_tip><![CDATA[Majanicho]]></title_tip>
   <content_tip><![CDATA[Majanicho is a very good surf spot for longboarding it offers very long rides.]]></content_tip>
  </location>
  
  <location>
   <lat>28.738764</lat>
   <lon>-13.955126</lon>
   <name_tip>Derecha de los Alemanes</name_tip>
   <title_tip><![CDATA[La Derecha de los Alemanes]]></title_tip>
   <content_tip><![CDATA[La Derecha de los Alemanes is another very good spot for longboarders but shortboarders will have some epic days out here to.]]></content_tip>
  </location>
  
  <location>
   <lat>28.741022</lat>
   <lon>-13.951821</lon>
   <name_tip>The Bubbel</name_tip>
   <title_tip><![CDATA[The Bubbel aka La Derecha]]></title_tip>
   <content_tip><![CDATA[The Bubbel is one of the most famouse waves in Fuerteventura its a really hollow reef break and it has some epic barrels on offer.]]></content_tip>
  </location>
 
 </map_xml>

Step 19: onMapReady()

Once our map is loaded we need to pull the XML data into our Flash file. Create a new function named "xmlLoader()" and we'll call that function in our "onMapReady()" function. First we need to delete the code we added to create our marker just a few steps before. Then we'll add the line to call the "xmlLoader()" function. Our "onMapReady()" function should now look like this:

function onMapReady(event:MapEvent):void {
  map.setCenter(new LatLng(28.74659,-13.93447), 9, MapType.HYBRID_MAP_TYPE);
  map.addControl(new ZoomControl());
  map.addControl(new PositionControl());
  map.addControl(new MapTypeControl());
  xmlLoader();
}

Next we want to create the "xmlLoader()" function.

function xmlLoader(){
	
}

In the next step we'll fill it up.


Step 20: Load XML

Ok here we are. Let's load our XML data. Inside the "xmlLoader()" function we add this code:

 function loadXML(e:Event):void{
	 XML.ignoreWhitespace = true; 
	 var map_xml:XML = new XML(e.target.data);
 }// end of loadXML function

 var xmlLoader:URLLoader = new URLLoader();
 xmlLoader.addEventListener(Event.COMPLETE, loadXML);
 xmlLoader.load(new URLRequest("xml.xml"));

This will get us our XML data to work with.


Step 21: Loop Through the Locations

As we have 3 locations in our XML file we'll need to create a "For" loop and store all the data in some Arrays. Inside our "loadXML()" function we add this piece of code to create the For loop:

for (var i:Number = 0; i < map_xml.location.length(); i++){
		 trace(map_xml.location[i].title_tip);
		 		
	 }// end of for loop

To test if things are working for us we'll trace the "title_tip" variable. Test your movie and you should get the following output:

google maps api for flash

Step 22: Variables

Next we have to create some variables to store our data loaded from the XML file. Inside our For loop we add these variables:

var latlng:LatLng = new LatLng(map_xml.location[i].lat, map_xml.location[i].lon);
var tip = map_xml.location[i].name_tip;
var myTitle:String = map_xml.location[i].title_tip;
var myContent:String = map_xml.location[i].content_tip;

If you want you can delete the "trace()" line we used before. Our For loop now looks like this:

for (var i:Number = 0; i < map_xml.location.length(); i++){
		 
		 var latlng:LatLng = new LatLng(map_xml.location[i].lat, map_xml.location[i].lon);
		 var tip = map_xml.location[i].name_tip;
		 var myTitle:String = map_xml.location[i].title_tip;
		 var myContent:String = map_xml.location[i].content_tip;		 		
	 }// end of for loop

Step 23: Additional Markers..

Ok! We need to add a marker to the map for each of our three locations. Now that we have all the data stored in our variables we'll have to create a new function named "createMarker()". Inside our "loadXML()" function we add this new function:

// Add Markers On The Map
function createMarker(latlng:LatLng, number:Number, tip, myTitle, myContent):Marker {
               var i:Marker = new Marker(
										 latlng,
										 new MarkerOptions({ 
                                                           hasShadow: true,
				                                           tooltip: ""+tip  
                                                           })
										 );
               return i;
}// end function createMarker

We still need to call this "createMarker()" function in order to see our markers on the map. To do that we need to add a extra line of code at the end of our For loop:

map.addOverlay(createMarker(latlng,i, tip, myTitle, myContent));

This is what our "loadXML()" function should look like now:

function loadXML(e:Event):void{
	 XML.ignoreWhitespace = true; 
	 var map_xml:XML = new XML(e.target.data);
	 
	 for (var i:Number = 0; i < map_xml.location.length(); i++){
		 
		 var latlng:LatLng = new LatLng(map_xml.location[i].lat, map_xml.location[i].lon);
		 var tip = map_xml.location[i].name_tip;
		 var myTitle:String = map_xml.location[i].title_tip;
		 var myContent:String = map_xml.location[i].content_tip;
		 
		 map.addOverlay(createMarker(latlng,i, tip, myTitle, myContent));
	 }// end of for loop
	 
	 // Add Markers On The Map
	 function createMarker(latlng:LatLng, number:Number, tip, myTitle, myContent):Marker {
               var i:Marker = new Marker(
										 latlng,
										 new MarkerOptions({ 
                                                           hasShadow: true,
				                                           tooltip: ""+tip  
                                                           })
										 );
               return i;
      }// end function createMarker
 }// end of loadXML function

Test your movie and you will see the markers on the map! Note that our 3 points are very close to each other so you may want to zoom in a bit to see them more clearly.

google maps api for flash

Step 24: Info Windows

Finally we need to add some Info Windows. If we click on the markers we'll then get some information about their locations. To do so we need to add 2 more classes:

import com.google.maps.InfoWindowOptions;
import com.google.maps.MapMouseEvent;

..a little more code to our "createMarker()" function..

i.addEventListener(MapMouseEvent.CLICK, function(event:MapMouseEvent):void 
        {
         map.openInfoWindow(event.latLng, new InfoWindowOptions({
                                      titleHTML: ""+myTitle, 
                                      contentHTML: ""+myContent
                                                               }));
																			  											 
		});

Now test your movie and you'll see that our markers are now clickable and that they create an info window with text from the XML file.

google maps api for flash

Conclusion

Thats it! Take a look at our final code:

import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
import com.google.maps.controls.ZoomControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.overlays.MarkerOptions;
import com.google.maps.overlays.Marker;
import com.google.maps.InfoWindowOptions;
import com.google.maps.MapMouseEvent;

// Create The Map
var map:Map = new Map();
map.key = "Your API Key Here";
map.setSize(new Point(stage.stageWidth, stage.stageHeight));
map.addEventListener(MapEvent.MAP_READY, onMapReady);
this.addChild(map);

function onMapReady(event:MapEvent):void {
  map.setCenter(new LatLng(28.74659,-13.93447), 9, MapType.HYBRID_MAP_TYPE);
  map.addControl(new ZoomControl());
  map.addControl(new PositionControl());
  map.addControl(new MapTypeControl());
  xmlLoader();
}

function xmlLoader(){
 function loadXML(e:Event):void{
	 XML.ignoreWhitespace = true; 
	 var map_xml:XML = new XML(e.target.data);
	 
	 for (var i:Number = 0; i < map_xml.location.length(); i++){
		 
		 var latlng:LatLng = new LatLng(map_xml.location[i].lat, map_xml.location[i].lon);
		 var tip = map_xml.location[i].name_tip;
		 var myTitle:String = map_xml.location[i].title_tip;
		 var myContent:String = map_xml.location[i].content_tip;
		 
		 map.addOverlay(createMarker(latlng,i, tip, myTitle, myContent));
	 }// end of for loop
	 
	 // Add Markers On The Map
	 function createMarker(latlng:LatLng, number:Number, tip, myTitle, myContent):Marker {
               var i:Marker = new Marker(
										 latlng,
										 new MarkerOptions({ 
                                                           hasShadow: true,
				                                           tooltip: ""+tip  
                                                           })
										 );
			   i.addEventListener(MapMouseEvent.CLICK, function(event:MapMouseEvent):void 
																			  {
																			  map.openInfoWindow(event.latLng, new InfoWindowOptions({
																																	 titleHTML: ""+myTitle, 
																																	 contentHTML: ""+myContent
																																	 }));
																			  											 
																			  });
               return i;
      }// end function createMarker
 }// end of loadXML function

 var xmlLoader:URLLoader = new URLLoader();
 xmlLoader.addEventListener(Event.COMPLETE, loadXML);
 xmlLoader.load(new URLRequest("xml.xml"));
}

Test your movie Ctrl+Enter to check the outcome. You'll have your own xml based Flash map! You can use it on your website, edit the locations as you want, it's up to you. Go ahead and experiment, if you have any cool results be sure to share them with us.

I hope you liked this tutorial, thanks for reading!

Related Posts
  • Web Design
    HTML & CSS
    How to Add Branded Branch Locations to Google MapsMap thumb
    In this tutorial we'll walk through the process of creating a branded Google map for an imaginary client.Read More…
  • Game Development
    Implementation
    Write Once, Publish Everywhere With HaxePunk: Making a GamePreviewretinaimage
    You've probably had this experience before: you hear about an awesome game, but then you find out that it's only coming out on the one platform that you don't own. It doesn't have to be this way. In this tutorial, you will learn how to use Haxe to make a game in one development platform that can target multiple gaming platforms, including Linux, Mac, Windows, iOS, Android, and Flash.Read More…
  • Game Development
    Implementation
    How to Make Your First Roguelike400px
    Roguelikes have been in the spotlight recently, with games like Dungeons of Dredmor, Spelunky, The Binding of Isaac, and FTL reaching wide audiences and receiving critical acclaim. Long enjoyed by hardcore players in a tiny niche, roguelike elements in various combinations now help bring more depth and replayability to many existing genres.Read More…
  • Code
    JavaScript & AJAX
    Working With IndexedDB - Part 2Indexeddb retina preview
    Welcome to the second part of my IndexedDB article. I strongly recommend reading the first article in this series, as I'll be assuming you are familiar with all the concepts covered so far. In this article, we're going to wrap up the CRUD aspects we didn't finish before (specifically updating and deleting content), and then demonstrate a real world application that we will use to demonstrate other concepts in the final article.Read More…
  • Code
    Android SDK
    Android SDK: Working with Google Maps - Displaying Places of InterestAndroid map preview retina
    With Google Maps in your Android apps, you can provide users with localization functions, such as geographical information. Throughout this series we have been building an Android app in which the Google Maps Android API v2 combines with the Google Places API. So far we have displayed a map, in which the user can see their current location, and we have submitted a Google Places query to return data about nearby places of interest. This required setting up API access for both services. In the final part of the series, we will parse the Google Places JSON data and use it to show the user nearby places of interest. We will also make the app update the markers when the user location changes. This is the last of four parts in a tutorial series on Using Google Maps and Google Places in Android apps: Working with Google Maps - Application Setup Working with Google Maps - Map Setup Working with Google Maps - Places Integration Working with Google Maps - Displaying Nearby Places This is a snapshot of the final app. 1. Process the Place Data Step 1 You will need to add the following import statements to your Activity class for this tutorial: [java] import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.util.Log; [/java] In the last tutorial we created an inner AsyncTask class to handle fetching the data from Google Places in the background. We added the doInBackground method to request and retrieve the data. Now we can implement the onPostExecute method to parse the JSON string returned from doInBackground, inside your AsyncTask class, after the doInBackground method: [java] protected void onPostExecute(String result) { //parse place data returned from Google Places } [/java] Step 2 Back in the second part of this series, we created a Marker object to indicate the user's last recorded location on the map. We are also going to use Markers to show the nearby places of interest. We will use an array to store these Markers. At the top of your Activity class declaration, add the following instance variable: [java] private Marker[] placeMarkers; [/java] By default, the Google Places API returns a maximum of 20 places, so let's define this as a constant too: [java] private final int MAX_PLACES = 20; [/java] When we create the Markers for each place, we will use MarkerOptions objects to configure the Marker details. Create another array instance variable for these: [java] private MarkerOptions[] places; [/java] Now let's instantiate the array. In your Activity onCreate method, after the line in which we set the map type, create an array of the maximum required size: [java] placeMarkers = new Marker[MAX_PLACES]; [/java] Now let's turn to the onPostExecute method we created. First, loop through the Marker array, removing any existing Markers. This method will execute multiple times as the user changes location: [java] if(placeMarkers!=null){ for(int pm=0; pm<placeMarkers.length; pm++){ if(placeMarkers[pm]!=null) placeMarkers[pm].remove(); } } [/java] When the app code first executes, new Markers will be created. However, when the user changes location, these methods will execute again to update the places displayed. For this reason the first thing we must do is remove any existing Markers from the map to prepare for creating a new batch. Step 3 We will be using Java JSON resources to process the retrieved place data. Since these classes throw certain exceptions, we need to build in a level of error handling throughout this section. Start by adding try and catch blocks: [java] try { //parse JSON } catch (Exception e) { e.printStackTrace(); } [/java] Inside the try block, create a new JSONObject and pass it to the result JSON string returned from doInBackground: [java] JSONObject resultObject = new JSONObject(result); [/java] If you look at the Place Search page on the Google Places API documentation, you can see a sample of what the query actually returns in JSON. You will see that the places are contained within an array named "results". Let's first retrieve that array from the returned JSON object: [java] JSONArray placesArray = resultObject.getJSONArray("results"); [/java] You should refer to the sample JSON result as we complete each section of this process - keep the page open in a browser while you complete the remainder of the tutorial. Next let's instantiate the MarkerOptions array we created with the length of the returned "results" array: [java] places = new MarkerOptions[placesArray.length()]; [/java] This should give us a MarkerOptions object for each place returned. Add a loop to iterate through the array of places: [java] //loop through places for (int p=0; p<placesArray.length(); p++) { //parse each place } [/java] Step 4 Now we can parse the data for each place returned. Inside the for loop, we will build details to pass to the MarkerOptions object for the current place. This will include latitude and longitude, place name, type and vicinity, which is an excerpt of the address data for the place. We will retrieve all of this data from the Google Places JSON, passing it to the Marker for the place via its MarkerOptions object. If any of the values are missing in the returned JSON feed, we will simply not display a Marker for that place, in case of Exceptions. To keep track of this, add a boolean flag: [java] boolean missingValue=false; [/java] Now add local variables for each aspect of the place we need to retrieve and pass to the Marker: [java] LatLng placeLL=null; String placeName=""; String vicinity=""; int currIcon = otherIcon; [/java] We create and initialize a LatLng object for the latitude and longitude, strings for the place name and vicinity and initially set the icon to use the default icon drawable we created. Now we need another try block, so that we can detect whether any values are in fact missing: [java] try{ //attempt to retrieve place data values } catch(JSONException jse){ missingValue=true; jse.printStackTrace(); } [/java] We set the missing value flag to true for checking later. Inside this try block, we can now attempt to retrieve the required values from the place data. Start by initializing the boolean flag to false, assuming that there are no missing values until we discover otherwise: [java] missingValue=false; [/java] Now get the current object from the place array: [java] JSONObject placeObject = placesArray.getJSONObject(p); [/java] If you look back at the sample Place Search data, you will see that each place section includes a "geometry" section which in turn contains a "location" section. This is where the latitude and longitude data for the place is, so retrieve it now: [java] JSONObject loc = placeObject.getJSONObject("geometry").getJSONObject("location"); [/java] Attempt to read the latitude and longitude data from this, referring to the "lat" and "lng" values in the JSON: [java] placeLL = new LatLng( Double.valueOf(loc.getString("lat")), Double.valueOf(loc.getString("lng"))); [/java] Next get the "types" array you can see in the JSON sample: [java] JSONArray types = placeObject.getJSONArray("types"); [/java] [tip] Tip: We know this is an array as it appears in the JSON feed surrounded by the "[" and "]" characters. We treat any other nested sections as JSON objects rather than arrays. [/tip] Loop through the type array: [java] for(int t=0; t<types.length(); t++){ //what type is it } [/java] Get the type string: [java] String thisType=types.get(t).toString(); [/java] We are going to use particular icons for certain place types (food, bar and store) so add a conditional: [java] if(thisType.contains("food")){ currIcon = foodIcon; break; } else if(thisType.contains("bar")){ currIcon = drinkIcon; break; } else if(thisType.contains("store")){ currIcon = shopIcon; break; } [/java] The type list for a place may actually contain more than one of these places, but for convenience we will simply use the first one encountered. If the list of types for a place does not contain any of these, we will leave it displaying the default icon. Remember that we specified these types in the Place Search URL query string last time: [text] food|bar|store|museum|art_gallery [/text] This means that the only place types using the default icon will be museums or art galleries, as these are the only other types we asked for. After the loop through the type array, retrieve the vicinity data: [java] vicinity = placeObject.getString("vicinity"); [/java] Finally, retrieve the place name: [java] placeName = placeObject.getString("name"); [/java] Step 5 After the catch block in which you set the missingValue flag to true, check that value and set the place MarkerOptions object to null, so that we don't attempt to instantiate any Marker objects with missing data: [java] if(missingValue) places[p]=null; [/java] Otherwise, we can create a MarkerOptions object at this position in the array: [java] else places[p]=new MarkerOptions() .position(placeLL) .title(placeName) .icon(BitmapDescriptorFactory.fromResource(currIcon)) .snippet(vicinity); [/java] Step 6 Now, at the end of onPostExecute after the outer try and catch blocks, loop through the array of MarkerOptions, instantiating a Marker for each, adding it to the map and storing a reference to it in the array we created: [java] if(places!=null && placeMarkers!=null){ for(int p=0; p<places.length && p<placeMarkers.length; p++){ //will be null if a value was missing if(places[p]!=null) placeMarkers[p]=theMap.addMarker(places[p]); } } [/java] Storing a reference to the Marker allows us to easily remove it when the places are updated, as we implemented at the beginning of the onPostExecute method. Notice that we include two conditional tests each time this loop iterates, in case the Place Search did not return the full 20 places. We also check in case the MarkerOptions is null, indicating that a value was missing. Step 7 Finally, we can instantiate and execute our AsyncTask class. In your updatePlaces method, after the existing code in which we built the search query string, start this background processing to fetch the place data using that string: [java] new GetPlaces().execute(placesSearchStr); [/java] You can run your app now to see it in action. It should display your last recorded location together with nearby places of interest. The colors you see on the Markers will depend on the places returned. Here is the app displaying a user location in Glasgow city center, UK: Perhaps unsurprisingly a lot of the places listed in Glasgow are bars. When the user taps a Marker, they will see the place name and snippet info: 2. Update With User Location Changes Step 1 The app as it stands will execute once when it is launched. Let's build in the functionality required to make it update to reflect changes in the user location, refreshing the nearby place Markers at the same time. Alter the opening line of the Activity class declaration to make it implement the LocationListener interface so that we can detect changes in the user location: [java] public class MyMapActivity extends Activity implements LocationListener { [/java] A Location Listener can respond to various changes, each of which uses a dedicated method. Inside the Activity class, implement these methods: [java] @Override public void onLocationChanged(Location location) { Log.v("MyMapActivity", "location changed"); updatePlaces(); } @Override public void onProviderDisabled(String provider){ Log.v("MyMapActivity", "provider disabled"); } @Override public void onProviderEnabled(String provider) { Log.v("MyMapActivity", "provider enabled"); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.v("MyMapActivity", "status changed"); } [/java] The only one we are really interested in is the first, which indicates that the location has changed. In this case we call the updatePlaces method again. Otherwise we simply write out a Log message. At the end of the updatePlaces method, add a request for the app to receive location updates: [java] locMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 30000, 100, this); [/java] We use the Location Manager we created earlier in the series, requesting updates using the network provider, at delays of 30 seconds (indicated in milliseconds), with a minimum location change of 100 meters and the Activity class itself to receive the updates. You can, of course, alter some of the parameters to suit your own needs. [tip] Tip: Although the requestLocationUpdates method specifies a minimum time and distance for updates, in reality it can cause the onLocationChanged method to execute much more often, which has serious performance implications. In any apps you plan on releasing to users, you should therefore limit the frequency at which your code responds to these location updates. The alternative requestSingleUpdate method used on a timed basis may be worth considering. [/tip] Step 2 Last but not least, we need to take care of what happens when the app pauses and resumes. Override the two methods as follows: [java] @Override protected void onResume() { super.onResume(); if(theMap!=null){ locMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 30000, 100, this); } } @Override protected void onPause() { super.onPause(); if(theMap!=null){ locMan.removeUpdates(this); } } [/java] We check for the GoogleMap object before attempting any processing, as in onCreate. If the app is pausing, we stop it from requesting location updates. If the app is resuming, we start requesting the updates again. [tip] Tip: We've used the LocationManager.NETWORK_PROVIDER a few times in this series. If you are exploring localization functionality in your apps, check out the alternative getBestProvider method with which you can specify criteria for Android to choose a provider based on such factors as accuracy and speed. [/tip] Before We Finish That pretty much completes the app! However, there are many aspects of the Google Maps Android API v2 that we have not even touched on. Once you have your app running you can experiment with features such as rotation and tilting. The updated maps service displays indoor and 3D maps in certain places. The following image shows the 3D facility with the app if the user location was in Venice, Italy: This has the map type set to normal - here is another view of Venice with the hybrid map type set: Conclusion In this tutorial series we have worked through the process of integrating both Google Maps and Google Places APIs in a single Android app. We handled API key access, setting up the development environment, workspace and application to use Google Play Services. We utilized location data, showing the user location together with nearby places of interest, and displaying the data with custom UI elements. Although what we have covered in this series is fairly extensive, it really is only the beginning when it comes to building localization features into Android apps. With the release of Version 2 of the Maps API, Android apps are set to take such functions to the next level.Read More…
  • Code
    Mobile Web Apps
    Creating a Mobile Event Calendar With DHTMLXMobile calendar preview@2x
    This tutorial describes how to build an HTML5-based mobile calendar to track conferences and events that run on iOS and Android phones using a mobile version of dhtmlxScheduler (open source, GPL). At the end, users will be able to add and edit events, select the conference location on Google Maps, and see the events in day, month, or list views.Read More…